* [PATCH 0/1] Add support for Classmate V3 accelerometer to classmate-laptop @ 2012-06-29 12:46 Miguel Gómez 2012-06-29 12:46 ` [PATCH] classmate-laptop: Add support for Classmate V3 accelerometer Miguel Gómez 2012-06-29 13:39 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 0 siblings, 2 replies; 15+ messages in thread From: Miguel Gómez @ 2012-06-29 12:46 UTC (permalink / raw) To: cascardo, don, mjg; +Cc: platform-driver-x86, linux-kernel, Miguel Gómez Classmate V3 has a different accelerometer than the previous versions. Main differences between the new (ACCE0001) and the old one (ACCE0000) are: * ACPI method calls need to receive 4 parameters instead of 2 * Values returned by the accelerometer are 2 bytes signed integers, instead of one unsigned byte * New accelerometer has a new attribute (g_select) besides the sensitivity one. This attribute's possible values are 0 (meaning 1.5g) and 1 (meaning 6g). I haven't been able to find the datasheet of the accelerometer, so I got most of the behaviour of the device by looking at the previous model driver and by experimenting with the hardware. Due to this, the range of the axis values (currently defined as -255-255) may not be exact, and also the fuzz value (16) may not be the best. But, with this configuration, the programs handling the screen rotation developed for previous versions of Classmate are working properly. Initially I thought of modifying the ACCE0000 driver to be able to handle both devices, but the patch was quite big and messy, and it might add problems to the previous hardware, so I decided to implement it as a new driver, following the structure of the ACCE0000 driver. This way the new code won't break the old one. In order to differenciate the new driver code from the old one, all the function names that belong to the new driver end with "v3". Hope everything is ok :) Regards! Miguel Gómez (1): classmate-laptop: Add support for accelerometer in classmate V3. drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 2 deletions(-) -- 1.7.9.5 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] classmate-laptop: Add support for Classmate V3 accelerometer. 2012-06-29 12:46 [PATCH 0/1] Add support for Classmate V3 accelerometer to classmate-laptop Miguel Gómez @ 2012-06-29 12:46 ` Miguel Gómez 2012-06-29 13:39 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 1 sibling, 0 replies; 15+ messages in thread From: Miguel Gómez @ 2012-06-29 12:46 UTC (permalink / raw) To: cascardo, don, mjg; +Cc: platform-driver-x86, linux-kernel, Miguel Gómez Classmate V3 laptop includes a new accelerometer that can't be handled by previous driver. This patch adds a new driver to handle it. Signed-off-by: Miguel Gómez <magomez@igalia.com> --- drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 94f93b6..f8cd3ad 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -31,12 +31,18 @@ MODULE_LICENSE("GPL"); struct cmpc_accel { int sensitivity; + int g_select; + int inputdev_state; }; -#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_DEV_STATE_CLOSED 0 +#define CMPC_ACCEL_DEV_STATE_OPEN 1 +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_G_SELECT_DEFAULT 0 #define CMPC_ACCEL_HID "ACCE0000" +#define CMPC_ACCEL_HID_V3 "ACCE0001" #define CMPC_TABLET_HID "TBLT0000" #define CMPC_IPML_HID "IPML200" #define CMPC_KEYS_HID "FnBT0000" @@ -76,7 +82,388 @@ static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) } /* - * Accelerometer code. + * Accelerometer code for Classmate V3 + */ +static acpi_status cmpc_start_accel_v3(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x3; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_stop_accel_v3(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x4; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_accel_set_sensitivity_v3(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x02; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_accel_set_g_select_v3(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x05; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_get_accel_v3(acpi_handle handle, + int16_t *x, + int16_t *y, + int16_t *z) +{ + union acpi_object param[4]; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + int16_t *locs; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x01; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *obj; + obj = output.pointer; + locs = (int16_t *) obj->buffer.pointer; + *x = locs[0]; + *y = locs[1]; + *z = locs[2]; + kfree(output.pointer); + } + return status; +} + +static void cmpc_accel_handler_v3(struct acpi_device *dev, u32 event) +{ + if (event == 0x81) { + int16_t x, y, z; + acpi_status status; + + status = cmpc_get_accel_v3(dev->handle, &x, &y, &z); + if (ACPI_SUCCESS(status)) { + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + input_report_abs(inputdev, ABS_X, x); + input_report_abs(inputdev, ABS_Y, y); + input_report_abs(inputdev, ABS_Z, z); + input_sync(inputdev); + } + } +} + +static ssize_t cmpc_accel_sensitivity_show_v3(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->sensitivity); +} + +static ssize_t cmpc_accel_sensitivity_store_v3(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long sensitivity; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &sensitivity); + if (r) + return r; + + /* sensitivity must be between 1 and 127 */ + if (sensitivity < 1 || sensitivity > 127) + return -EINVAL; + + accel->sensitivity = sensitivity; + cmpc_accel_set_sensitivity_v3(acpi->handle, sensitivity); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_sensitivity_attr_v3 = { + .attr = { .name = "sensitivity", .mode = 0660 }, + .show = cmpc_accel_sensitivity_show_v3, + .store = cmpc_accel_sensitivity_store_v3 +}; + +static ssize_t cmpc_accel_g_select_show_v3(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->g_select); +} + +static ssize_t cmpc_accel_g_select_store_v3(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long g_select; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &g_select); + if (r) + return r; + + /* 0 means 1.5g, 1 means 6g, everything else is wrong */ + if (g_select != 0 && g_select != 1) + return -EINVAL; + + accel->g_select = g_select; + cmpc_accel_set_g_select_v3(acpi->handle, g_select); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_g_select_attr_v3 = { + .attr = { .name = "g_select", .mode = 0660 }, + .show = cmpc_accel_g_select_show_v3, + .store = cmpc_accel_g_select_store_v3 +}; + +static int cmpc_accel_open_v3(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_accel_set_sensitivity_v3(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v3(acpi->handle, accel->g_select); + + if (ACPI_SUCCESS(cmpc_start_accel_v3(acpi->handle))) { + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_OPEN; + return 0; + } + return -EIO; +} + +static void cmpc_accel_close_v3(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_stop_accel_v3(acpi->handle); + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; +} + +static void cmpc_accel_idev_init_v3(struct input_dev *inputdev) +{ + set_bit(EV_ABS, inputdev->evbit); + input_set_abs_params(inputdev, ABS_X, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Y, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Z, -255, 255, 16, 0); + inputdev->open = cmpc_accel_open_v3; + inputdev->close = cmpc_accel_close_v3; +} + +static int cmpc_accel_suspend_v3(struct acpi_device *acpi, pm_message_t state) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) + return cmpc_stop_accel_v3(acpi->handle); + + return 0; +} + +static int cmpc_accel_resume_v3(struct acpi_device *acpi) +{ + + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) { + cmpc_accel_set_sensitivity_v3(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v3(acpi->handle, accel->g_select); + + if (ACPI_FAILURE(cmpc_start_accel_v3(acpi->handle))) + return -EIO; + } + + return 0; +} + +static int cmpc_accel_add_v3(struct acpi_device *acpi) +{ + int error; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + accel = kmalloc(sizeof(*accel), GFP_KERNEL); + if (!accel) + return -ENOMEM; + + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; + + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; + cmpc_accel_set_sensitivity_v3(acpi->handle, accel->sensitivity); + + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v3); + if (error) + goto failed_sensitivity; + + accel->g_select = CMPC_ACCEL_G_SELECT_DEFAULT; + cmpc_accel_set_g_select_v3(acpi->handle, accel->g_select); + + error = device_create_file(&acpi->dev, &cmpc_accel_g_select_attr_v3); + if (error) + goto failed_g_select; + + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel_v3", + cmpc_accel_idev_init_v3); + if (error) + goto failed_input; + + inputdev = dev_get_drvdata(&acpi->dev); + dev_set_drvdata(&inputdev->dev, accel); + + return 0; + +failed_input: + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v3); +failed_g_select: + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v3); +failed_sensitivity: + kfree(accel); + return error; +} + +static int cmpc_accel_remove_v3(struct acpi_device *acpi, int type) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v3); + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v3); + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_accel_device_ids_v3[] = { + {CMPC_ACCEL_HID_V3, 0}, + {"", 0} +}; + +static struct acpi_driver cmpc_accel_acpi_driver_v3 = { + .owner = THIS_MODULE, + .name = "cmpc_accel_v3", + .class = "cmpc_accel_v3", + .ids = cmpc_accel_device_ids_v3, + .ops = { + .add = cmpc_accel_add_v3, + .remove = cmpc_accel_remove_v3, + .notify = cmpc_accel_handler_v3, + .suspend = cmpc_accel_suspend_v3, + .resume = cmpc_accel_resume_v3, + } +}; + + +/* + * Accelerometer code for classmate V1 and V2 */ static acpi_status cmpc_start_accel(acpi_handle handle) { @@ -723,8 +1110,15 @@ static int cmpc_init(void) if (r) goto failed_accel; + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver_v3); + if (r) + goto failed_accel_v3; + return r; +failed_accel_v3: + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); + failed_accel: acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); @@ -740,6 +1134,7 @@ failed_keys: static void cmpc_exit(void) { + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v3); acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver); @@ -751,6 +1146,7 @@ module_exit(cmpc_exit); static const struct acpi_device_id cmpc_device_ids[] = { {CMPC_ACCEL_HID, 0}, + {CMPC_ACCEL_HID_V3, 0}, {CMPC_TABLET_HID, 0}, {CMPC_IPML_HID, 0}, {CMPC_KEYS_HID, 0}, -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop 2012-06-29 12:46 [PATCH 0/1] Add support for Classmate V3 accelerometer to classmate-laptop Miguel Gómez 2012-06-29 12:46 ` [PATCH] classmate-laptop: Add support for Classmate V3 accelerometer Miguel Gómez @ 2012-06-29 13:39 ` Miguel Gómez 2012-06-29 13:39 ` [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer Miguel Gómez 2012-07-17 14:34 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 1 sibling, 2 replies; 15+ messages in thread From: Miguel Gómez @ 2012-06-29 13:39 UTC (permalink / raw) To: cascardo, don, mjg; +Cc: platform-driver-x86, linux-kernel, Miguel Gómez ************************************************************************ Sorry, I made a mistake with the version. The patch is for Classmate V4 and not for V3, so I adjusted it accordingly. ************************************************************************ Classmate V4 has a different accelerometer than the previous versions. Main differences between the new (ACCE0001) and the old one (ACCE0000) are: * ACPI method calls need to receive 4 parameters instead of 2 * Values returned by the accelerometer are 2 bytes signed integers, instead of one unsigned byte * New accelerometer has a new attribute (g_select) besides the sensitivity one. This attribute's possible values are 0 (meaning 1.5g) and 1 (meaning 6g). I haven't been able to find the datasheet of the accelerometer, so I got most of the behaviour of the device by looking at the previous model driver and by experimenting with the hardware. Due to this, the range of the axis values (currently defined as -255-255) may not be exact, and also the fuzz value (16) may not be the best. But, with this configuration, the programs handling the screen rotation developed for previous versions of Classmate are working properly. Initially I thought of modifying the ACCE0000 driver to be able to handle both devices, but the patch was quite big and messy, and it might add problems to the previous hardware, so I decided to implement it as a new driver, following the structure of the ACCE0000 driver. This way the new code won't break the old one. In order to differenciate the new driver code from the old one, all the function names that belong to the new driver end with "v4". Hope everything is ok :) Regards! Miguel Gómez (1): classmate-laptop: Add support for Classmate V4 accelerometer. drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 2 deletions(-) -- 1.7.9.5 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-06-29 13:39 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez @ 2012-06-29 13:39 ` Miguel Gómez 2012-07-17 22:47 ` Thadeu Lima de Souza Cascardo 2012-07-17 14:34 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 1 sibling, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-06-29 13:39 UTC (permalink / raw) To: cascardo, don, mjg; +Cc: platform-driver-x86, linux-kernel, Miguel Gómez Classmate V4 laptop includes a new accelerometer that can't be handled by previous driver. This patch adds a new driver to handle it. Signed-off-by: Miguel Gómez <magomez@igalia.com> --- drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 94f93b6..5de01bc 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -31,12 +31,18 @@ MODULE_LICENSE("GPL"); struct cmpc_accel { int sensitivity; + int g_select; + int inputdev_state; }; -#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_DEV_STATE_CLOSED 0 +#define CMPC_ACCEL_DEV_STATE_OPEN 1 +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_G_SELECT_DEFAULT 0 #define CMPC_ACCEL_HID "ACCE0000" +#define CMPC_ACCEL_HID_V4 "ACCE0001" #define CMPC_TABLET_HID "TBLT0000" #define CMPC_IPML_HID "IPML200" #define CMPC_KEYS_HID "FnBT0000" @@ -76,7 +82,388 @@ static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) } /* - * Accelerometer code. + * Accelerometer code for Classmate V4 + */ +static acpi_status cmpc_start_accel_v4(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x3; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_stop_accel_v4(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x4; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_accel_set_sensitivity_v4(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x02; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_accel_set_g_select_v4(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x05; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_get_accel_v4(acpi_handle handle, + int16_t *x, + int16_t *y, + int16_t *z) +{ + union acpi_object param[4]; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + int16_t *locs; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x01; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *obj; + obj = output.pointer; + locs = (int16_t *) obj->buffer.pointer; + *x = locs[0]; + *y = locs[1]; + *z = locs[2]; + kfree(output.pointer); + } + return status; +} + +static void cmpc_accel_handler_v4(struct acpi_device *dev, u32 event) +{ + if (event == 0x81) { + int16_t x, y, z; + acpi_status status; + + status = cmpc_get_accel_v4(dev->handle, &x, &y, &z); + if (ACPI_SUCCESS(status)) { + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + input_report_abs(inputdev, ABS_X, x); + input_report_abs(inputdev, ABS_Y, y); + input_report_abs(inputdev, ABS_Z, z); + input_sync(inputdev); + } + } +} + +static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->sensitivity); +} + +static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long sensitivity; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &sensitivity); + if (r) + return r; + + /* sensitivity must be between 1 and 127 */ + if (sensitivity < 1 || sensitivity > 127) + return -EINVAL; + + accel->sensitivity = sensitivity; + cmpc_accel_set_sensitivity_v4(acpi->handle, sensitivity); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_sensitivity_attr_v4 = { + .attr = { .name = "sensitivity", .mode = 0660 }, + .show = cmpc_accel_sensitivity_show_v4, + .store = cmpc_accel_sensitivity_store_v4 +}; + +static ssize_t cmpc_accel_g_select_show_v4(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->g_select); +} + +static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long g_select; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &g_select); + if (r) + return r; + + /* 0 means 1.5g, 1 means 6g, everything else is wrong */ + if (g_select != 0 && g_select != 1) + return -EINVAL; + + accel->g_select = g_select; + cmpc_accel_set_g_select_v4(acpi->handle, g_select); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_g_select_attr_v4 = { + .attr = { .name = "g_select", .mode = 0660 }, + .show = cmpc_accel_g_select_show_v4, + .store = cmpc_accel_g_select_store_v4 +}; + +static int cmpc_accel_open_v4(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); + + if (ACPI_SUCCESS(cmpc_start_accel_v4(acpi->handle))) { + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_OPEN; + return 0; + } + return -EIO; +} + +static void cmpc_accel_close_v4(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_stop_accel_v4(acpi->handle); + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; +} + +static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) +{ + set_bit(EV_ABS, inputdev->evbit); + input_set_abs_params(inputdev, ABS_X, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Y, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Z, -255, 255, 16, 0); + inputdev->open = cmpc_accel_open_v4; + inputdev->close = cmpc_accel_close_v4; +} + +static int cmpc_accel_suspend_v4(struct acpi_device *acpi, pm_message_t state) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) + return cmpc_stop_accel_v4(acpi->handle); + + return 0; +} + +static int cmpc_accel_resume_v4(struct acpi_device *acpi) +{ + + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) { + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); + + if (ACPI_FAILURE(cmpc_start_accel_v4(acpi->handle))) + return -EIO; + } + + return 0; +} + +static int cmpc_accel_add_v4(struct acpi_device *acpi) +{ + int error; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + accel = kmalloc(sizeof(*accel), GFP_KERNEL); + if (!accel) + return -ENOMEM; + + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; + + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); + if (error) + goto failed_sensitivity; + + accel->g_select = CMPC_ACCEL_G_SELECT_DEFAULT; + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); + + error = device_create_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); + if (error) + goto failed_g_select; + + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel_v4", + cmpc_accel_idev_init_v4); + if (error) + goto failed_input; + + inputdev = dev_get_drvdata(&acpi->dev); + dev_set_drvdata(&inputdev->dev, accel); + + return 0; + +failed_input: + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); +failed_g_select: + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); +failed_sensitivity: + kfree(accel); + return error; +} + +static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_accel_device_ids_v4[] = { + {CMPC_ACCEL_HID_V4, 0}, + {"", 0} +}; + +static struct acpi_driver cmpc_accel_acpi_driver_v4 = { + .owner = THIS_MODULE, + .name = "cmpc_accel_v4", + .class = "cmpc_accel_v4", + .ids = cmpc_accel_device_ids_v4, + .ops = { + .add = cmpc_accel_add_v4, + .remove = cmpc_accel_remove_v4, + .notify = cmpc_accel_handler_v4, + .suspend = cmpc_accel_suspend_v4, + .resume = cmpc_accel_resume_v4, + } +}; + + +/* + * Accelerometer code for Classmate versions prior to V4 */ static acpi_status cmpc_start_accel(acpi_handle handle) { @@ -723,8 +1110,15 @@ static int cmpc_init(void) if (r) goto failed_accel; + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver_v4); + if (r) + goto failed_accel_v4; + return r; +failed_accel_v4: + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); + failed_accel: acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); @@ -740,6 +1134,7 @@ failed_keys: static void cmpc_exit(void) { + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v4); acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver); @@ -751,6 +1146,7 @@ module_exit(cmpc_exit); static const struct acpi_device_id cmpc_device_ids[] = { {CMPC_ACCEL_HID, 0}, + {CMPC_ACCEL_HID_V4, 0}, {CMPC_TABLET_HID, 0}, {CMPC_IPML_HID, 0}, {CMPC_KEYS_HID, 0}, -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-06-29 13:39 ` [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer Miguel Gómez @ 2012-07-17 22:47 ` Thadeu Lima de Souza Cascardo 2012-07-18 13:53 ` Miguel Gómez 0 siblings, 1 reply; 15+ messages in thread From: Thadeu Lima de Souza Cascardo @ 2012-07-17 22:47 UTC (permalink / raw) To: Miguel Gómez; +Cc: don, mjg, platform-driver-x86, linux-kernel [-- Attachment #1: Type: text/plain, Size: 14094 bytes --] On Fri, Jun 29, 2012 at 03:39:48PM +0200, Miguel Gómez wrote: > Classmate V4 laptop includes a new accelerometer that can't be handled by > previous driver. This patch adds a new driver to handle it. > > Signed-off-by: Miguel Gómez <magomez@igalia.com> Hi, Miguel. This seems OK to me. Thanks for this work. Do you have the other functionality of the driver working? I am interested to know if you have the function buttons working. Regards. Cascardo. Acked-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> > --- > drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- > 1 file changed, 398 insertions(+), 2 deletions(-) > > diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c > index 94f93b6..5de01bc 100644 > --- a/drivers/platform/x86/classmate-laptop.c > +++ b/drivers/platform/x86/classmate-laptop.c > @@ -31,12 +31,18 @@ MODULE_LICENSE("GPL"); > > struct cmpc_accel { > int sensitivity; > + int g_select; > + int inputdev_state; > }; > > -#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 > +#define CMPC_ACCEL_DEV_STATE_CLOSED 0 > +#define CMPC_ACCEL_DEV_STATE_OPEN 1 > > +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 > +#define CMPC_ACCEL_G_SELECT_DEFAULT 0 > > #define CMPC_ACCEL_HID "ACCE0000" > +#define CMPC_ACCEL_HID_V4 "ACCE0001" > #define CMPC_TABLET_HID "TBLT0000" > #define CMPC_IPML_HID "IPML200" > #define CMPC_KEYS_HID "FnBT0000" > @@ -76,7 +82,388 @@ static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) > } > > /* > - * Accelerometer code. > + * Accelerometer code for Classmate V4 > + */ > +static acpi_status cmpc_start_accel_v4(acpi_handle handle) > +{ > + union acpi_object param[4]; > + struct acpi_object_list input; > + acpi_status status; > + > + param[0].type = ACPI_TYPE_INTEGER; > + param[0].integer.value = 0x3; > + param[1].type = ACPI_TYPE_INTEGER; > + param[1].integer.value = 0; > + param[2].type = ACPI_TYPE_INTEGER; > + param[2].integer.value = 0; > + param[3].type = ACPI_TYPE_INTEGER; > + param[3].integer.value = 0; > + input.count = 4; > + input.pointer = param; > + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); > + return status; > +} > + > +static acpi_status cmpc_stop_accel_v4(acpi_handle handle) > +{ > + union acpi_object param[4]; > + struct acpi_object_list input; > + acpi_status status; > + > + param[0].type = ACPI_TYPE_INTEGER; > + param[0].integer.value = 0x4; > + param[1].type = ACPI_TYPE_INTEGER; > + param[1].integer.value = 0; > + param[2].type = ACPI_TYPE_INTEGER; > + param[2].integer.value = 0; > + param[3].type = ACPI_TYPE_INTEGER; > + param[3].integer.value = 0; > + input.count = 4; > + input.pointer = param; > + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); > + return status; > +} > + > +static acpi_status cmpc_accel_set_sensitivity_v4(acpi_handle handle, int val) > +{ > + union acpi_object param[4]; > + struct acpi_object_list input; > + > + param[0].type = ACPI_TYPE_INTEGER; > + param[0].integer.value = 0x02; > + param[1].type = ACPI_TYPE_INTEGER; > + param[1].integer.value = val; > + param[2].type = ACPI_TYPE_INTEGER; > + param[2].integer.value = 0; > + param[3].type = ACPI_TYPE_INTEGER; > + param[3].integer.value = 0; > + input.count = 4; > + input.pointer = param; > + return acpi_evaluate_object(handle, "ACMD", &input, NULL); > +} > + > +static acpi_status cmpc_accel_set_g_select_v4(acpi_handle handle, int val) > +{ > + union acpi_object param[4]; > + struct acpi_object_list input; > + > + param[0].type = ACPI_TYPE_INTEGER; > + param[0].integer.value = 0x05; > + param[1].type = ACPI_TYPE_INTEGER; > + param[1].integer.value = val; > + param[2].type = ACPI_TYPE_INTEGER; > + param[2].integer.value = 0; > + param[3].type = ACPI_TYPE_INTEGER; > + param[3].integer.value = 0; > + input.count = 4; > + input.pointer = param; > + return acpi_evaluate_object(handle, "ACMD", &input, NULL); > +} > + > +static acpi_status cmpc_get_accel_v4(acpi_handle handle, > + int16_t *x, > + int16_t *y, > + int16_t *z) > +{ > + union acpi_object param[4]; > + struct acpi_object_list input; > + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > + int16_t *locs; > + acpi_status status; > + > + param[0].type = ACPI_TYPE_INTEGER; > + param[0].integer.value = 0x01; > + param[1].type = ACPI_TYPE_INTEGER; > + param[1].integer.value = 0; > + param[2].type = ACPI_TYPE_INTEGER; > + param[2].integer.value = 0; > + param[3].type = ACPI_TYPE_INTEGER; > + param[3].integer.value = 0; > + input.count = 4; > + input.pointer = param; > + status = acpi_evaluate_object(handle, "ACMD", &input, &output); > + if (ACPI_SUCCESS(status)) { > + union acpi_object *obj; > + obj = output.pointer; > + locs = (int16_t *) obj->buffer.pointer; > + *x = locs[0]; > + *y = locs[1]; > + *z = locs[2]; > + kfree(output.pointer); > + } > + return status; > +} > + > +static void cmpc_accel_handler_v4(struct acpi_device *dev, u32 event) > +{ > + if (event == 0x81) { > + int16_t x, y, z; > + acpi_status status; > + > + status = cmpc_get_accel_v4(dev->handle, &x, &y, &z); > + if (ACPI_SUCCESS(status)) { > + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); > + > + input_report_abs(inputdev, ABS_X, x); > + input_report_abs(inputdev, ABS_Y, y); > + input_report_abs(inputdev, ABS_Z, z); > + input_sync(inputdev); > + } > + } > +} > + > +static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct acpi_device *acpi; > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + acpi = to_acpi_device(dev); > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + return sprintf(buf, "%d\n", accel->sensitivity); > +} > + > +static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct acpi_device *acpi; > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + unsigned long sensitivity; > + int r; > + > + acpi = to_acpi_device(dev); > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + r = kstrtoul(buf, 0, &sensitivity); > + if (r) > + return r; > + > + /* sensitivity must be between 1 and 127 */ > + if (sensitivity < 1 || sensitivity > 127) > + return -EINVAL; > + > + accel->sensitivity = sensitivity; > + cmpc_accel_set_sensitivity_v4(acpi->handle, sensitivity); > + > + return strnlen(buf, count); > +} > + > +static struct device_attribute cmpc_accel_sensitivity_attr_v4 = { > + .attr = { .name = "sensitivity", .mode = 0660 }, > + .show = cmpc_accel_sensitivity_show_v4, > + .store = cmpc_accel_sensitivity_store_v4 > +}; > + > +static ssize_t cmpc_accel_g_select_show_v4(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct acpi_device *acpi; > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + acpi = to_acpi_device(dev); > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + return sprintf(buf, "%d\n", accel->g_select); > +} > + > +static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct acpi_device *acpi; > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + unsigned long g_select; > + int r; > + > + acpi = to_acpi_device(dev); > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + r = kstrtoul(buf, 0, &g_select); > + if (r) > + return r; > + > + /* 0 means 1.5g, 1 means 6g, everything else is wrong */ > + if (g_select != 0 && g_select != 1) > + return -EINVAL; > + > + accel->g_select = g_select; > + cmpc_accel_set_g_select_v4(acpi->handle, g_select); > + > + return strnlen(buf, count); > +} > + > +static struct device_attribute cmpc_accel_g_select_attr_v4 = { > + .attr = { .name = "g_select", .mode = 0660 }, > + .show = cmpc_accel_g_select_show_v4, > + .store = cmpc_accel_g_select_store_v4 > +}; > + > +static int cmpc_accel_open_v4(struct input_dev *input) > +{ > + struct acpi_device *acpi; > + struct cmpc_accel *accel; > + > + acpi = to_acpi_device(input->dev.parent); > + accel = dev_get_drvdata(&input->dev); > + > + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); > + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); > + > + if (ACPI_SUCCESS(cmpc_start_accel_v4(acpi->handle))) { > + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_OPEN; > + return 0; > + } > + return -EIO; > +} > + > +static void cmpc_accel_close_v4(struct input_dev *input) > +{ > + struct acpi_device *acpi; > + struct cmpc_accel *accel; > + > + acpi = to_acpi_device(input->dev.parent); > + accel = dev_get_drvdata(&input->dev); > + > + cmpc_stop_accel_v4(acpi->handle); > + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; > +} > + > +static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) > +{ > + set_bit(EV_ABS, inputdev->evbit); > + input_set_abs_params(inputdev, ABS_X, -255, 255, 16, 0); > + input_set_abs_params(inputdev, ABS_Y, -255, 255, 16, 0); > + input_set_abs_params(inputdev, ABS_Z, -255, 255, 16, 0); > + inputdev->open = cmpc_accel_open_v4; > + inputdev->close = cmpc_accel_close_v4; > +} > + > +static int cmpc_accel_suspend_v4(struct acpi_device *acpi, pm_message_t state) > +{ > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) > + return cmpc_stop_accel_v4(acpi->handle); > + > + return 0; > +} > + > +static int cmpc_accel_resume_v4(struct acpi_device *acpi) > +{ > + > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) { > + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); > + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); > + > + if (ACPI_FAILURE(cmpc_start_accel_v4(acpi->handle))) > + return -EIO; > + } > + > + return 0; > +} > + > +static int cmpc_accel_add_v4(struct acpi_device *acpi) > +{ > + int error; > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + accel = kmalloc(sizeof(*accel), GFP_KERNEL); > + if (!accel) > + return -ENOMEM; > + > + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; > + > + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; > + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); > + > + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); > + if (error) > + goto failed_sensitivity; > + > + accel->g_select = CMPC_ACCEL_G_SELECT_DEFAULT; > + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); > + > + error = device_create_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); > + if (error) > + goto failed_g_select; > + > + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel_v4", > + cmpc_accel_idev_init_v4); > + if (error) > + goto failed_input; > + > + inputdev = dev_get_drvdata(&acpi->dev); > + dev_set_drvdata(&inputdev->dev, accel); > + > + return 0; > + > +failed_input: > + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); > +failed_g_select: > + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); > +failed_sensitivity: > + kfree(accel); > + return error; > +} > + > +static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) > +{ > + struct input_dev *inputdev; > + struct cmpc_accel *accel; > + > + inputdev = dev_get_drvdata(&acpi->dev); > + accel = dev_get_drvdata(&inputdev->dev); > + > + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); > + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); > + return cmpc_remove_acpi_notify_device(acpi); > +} > + > +static const struct acpi_device_id cmpc_accel_device_ids_v4[] = { > + {CMPC_ACCEL_HID_V4, 0}, > + {"", 0} > +}; > + > +static struct acpi_driver cmpc_accel_acpi_driver_v4 = { > + .owner = THIS_MODULE, > + .name = "cmpc_accel_v4", > + .class = "cmpc_accel_v4", > + .ids = cmpc_accel_device_ids_v4, > + .ops = { > + .add = cmpc_accel_add_v4, > + .remove = cmpc_accel_remove_v4, > + .notify = cmpc_accel_handler_v4, > + .suspend = cmpc_accel_suspend_v4, > + .resume = cmpc_accel_resume_v4, > + } > +}; > + > + > +/* > + * Accelerometer code for Classmate versions prior to V4 > */ > static acpi_status cmpc_start_accel(acpi_handle handle) > { > @@ -723,8 +1110,15 @@ static int cmpc_init(void) > if (r) > goto failed_accel; > > + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver_v4); > + if (r) > + goto failed_accel_v4; > + > return r; > > +failed_accel_v4: > + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); > + > failed_accel: > acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); > > @@ -740,6 +1134,7 @@ failed_keys: > > static void cmpc_exit(void) > { > + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v4); > acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); > acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); > acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver); > @@ -751,6 +1146,7 @@ module_exit(cmpc_exit); > > static const struct acpi_device_id cmpc_device_ids[] = { > {CMPC_ACCEL_HID, 0}, > + {CMPC_ACCEL_HID_V4, 0}, > {CMPC_TABLET_HID, 0}, > {CMPC_IPML_HID, 0}, > {CMPC_KEYS_HID, 0}, > -- > 1.7.9.5 > [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-17 22:47 ` Thadeu Lima de Souza Cascardo @ 2012-07-18 13:53 ` Miguel Gómez 2012-07-23 13:28 ` Matthew Garrett 0 siblings, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-07-18 13:53 UTC (permalink / raw) To: Thadeu Lima de Souza Cascardo; +Cc: don, mjg, platform-driver-x86, linux-kernel > On Fri, Jun 29, 2012 at 03:39:48PM +0200, Miguel Gómez wrote: >> Classmate V4 laptop includes a new accelerometer that can't be handled by >> previous driver. This patch adds a new driver to handle it. >> >> Signed-off-by: Miguel Gómez <magomez@igalia.com> > > Hi, Miguel. > > This seems OK to me. Thanks for this work. Do you have the other > functionality of the driver working? I am interested to know if you have > the function buttons working. Hi Thadeu I've been giving a look to the buttons code. Currently they are not working because the hardware id reported by the device (FNBT0000) is not the same as the one defined by the driver (FnBT0000), as you an one of my colleagues commented in this thread: https://lkml.org/lkml/2011/6/21/341 I've replaced the id in the driver to FNBT0000 and it made the buttons work like a charm (enabling control of the backlight and LAN as well). To ensure compatibility with older versions of the kernel, a new id can be added (FNBT0000) besides the existent one (FnBT0000), and that works as well (as proposed in the thread). It seems that this problem got a bit forgotten in the lists. Quoting yourself from the last email in the thread: > I am copying the acpi list and Len Brown to see if they can tell us > which one should be the right solution: > > 1) reverting the patch in acpica that puts all names in uppercase > 2) using a case-insensitive match in acpi bus driver > 3) using uppercase name in classmate-laptop driver I think the easiest and less risky way to fix this is by adding a new hardware id (as proposed in the thread's patch), as it doesn't add any side effects (that the other solutions might add), and it doesn't break the behaviour of the old code. What do you think? Regards! -- Miguel Gómez Igalia - http://www.igalia.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-18 13:53 ` Miguel Gómez @ 2012-07-23 13:28 ` Matthew Garrett 2012-07-23 13:33 ` Miguel Gómez 0 siblings, 1 reply; 15+ messages in thread From: Matthew Garrett @ 2012-07-23 13:28 UTC (permalink / raw) To: Miguel Gómez Cc: Thadeu Lima de Souza Cascardo, don, platform-driver-x86, linux-kernel On Wed, Jul 18, 2012 at 03:53:48PM +0200, Miguel Gómez wrote: > >1) reverting the patch in acpica that puts all names in uppercase > >2) using a case-insensitive match in acpi bus driver > >3) using uppercase name in classmate-laptop driver > > I think the easiest and less risky way to fix this is by adding a > new hardware id (as proposed in the thread's patch), as it doesn't > add any side effects (that the other solutions might add), and it > doesn't break the behaviour of the old code. I've lost track of the implementation state here - if all names are upper-cased in acpica, why is this not already matching? -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-23 13:28 ` Matthew Garrett @ 2012-07-23 13:33 ` Miguel Gómez 2012-07-23 13:36 ` Matthew Garrett 0 siblings, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-07-23 13:33 UTC (permalink / raw) To: Matthew Garrett Cc: Thadeu Lima de Souza Cascardo, don, platform-driver-x86, linux-kernel El 23/07/12 15:28, Matthew Garrett escribió: > On Wed, Jul 18, 2012 at 03:53:48PM +0200, Miguel Gómez wrote: > >>> 1) reverting the patch in acpica that puts all names in uppercase >>> 2) using a case-insensitive match in acpi bus driver >>> 3) using uppercase name in classmate-laptop driver >> >> I think the easiest and less risky way to fix this is by adding a >> new hardware id (as proposed in the thread's patch), as it doesn't >> add any side effects (that the other solutions might add), and it >> doesn't break the behaviour of the old code. > > I've lost track of the implementation state here - if all names are > upper-cased in acpica, why is this not already matching? Names are upper-cased in acpica, so the device is reported as FNBT0000. But in the driver it's named FnBT0000, and that's why it doesn't match. -- Miguel Gómez Igalia - http://www.igalia.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-23 13:33 ` Miguel Gómez @ 2012-07-23 13:36 ` Matthew Garrett 2012-07-23 13:44 ` Miguel Gómez 0 siblings, 1 reply; 15+ messages in thread From: Matthew Garrett @ 2012-07-23 13:36 UTC (permalink / raw) To: Miguel Gómez Cc: Thadeu Lima de Souza Cascardo, don, platform-driver-x86, linux-kernel On Mon, Jul 23, 2012 at 03:33:27PM +0200, Miguel Gómez wrote: > Names are upper-cased in acpica, so the device is reported as > FNBT0000. But in the driver it's named FnBT0000, and that's why it > doesn't match. So just change the existing entry in the driver to FNBT0000? -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-23 13:36 ` Matthew Garrett @ 2012-07-23 13:44 ` Miguel Gómez 2012-07-24 3:09 ` Thadeu Lima de Souza Cascardo 0 siblings, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-07-23 13:44 UTC (permalink / raw) To: Matthew Garrett Cc: Thadeu Lima de Souza Cascardo, don, platform-driver-x86, linux-kernel El 23/07/12 15:36, Matthew Garrett escribió: > On Mon, Jul 23, 2012 at 03:33:27PM +0200, Miguel Gómez wrote: > >> Names are upper-cased in acpica, so the device is reported as >> FNBT0000. But in the driver it's named FnBT0000, and that's why it >> doesn't match. > > So just change the existing entry in the driver to FNBT0000? I'd go for it. I can send a patch if you want. But not sure about Thadeu's opinion. In the old thread it seems that he wanted to explore other options besides that. Do you agree with that change Thadeu? -- Miguel Gómez Igalia - http://www.igalia.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer. 2012-07-23 13:44 ` Miguel Gómez @ 2012-07-24 3:09 ` Thadeu Lima de Souza Cascardo 2012-07-24 13:05 ` [PATCH] classmate-laptop: Fix extra keys hardware id Miguel Gómez 0 siblings, 1 reply; 15+ messages in thread From: Thadeu Lima de Souza Cascardo @ 2012-07-24 3:09 UTC (permalink / raw) To: Miguel Gómez; +Cc: Matthew Garrett, don, platform-driver-x86, linux-kernel [-- Attachment #1: Type: text/plain, Size: 827 bytes --] On Mon, Jul 23, 2012 at 03:44:41PM +0200, Miguel Gómez wrote: > El 23/07/12 15:36, Matthew Garrett escribió: > >On Mon, Jul 23, 2012 at 03:33:27PM +0200, Miguel Gómez wrote: > > > >>Names are upper-cased in acpica, so the device is reported as > >>FNBT0000. But in the driver it's named FnBT0000, and that's why it > >>doesn't match. > > > >So just change the existing entry in the driver to FNBT0000? > > I'd go for it. I can send a patch if you want. But not sure about > Thadeu's opinion. In the old thread it seems that he wanted to > explore other options besides that. > > Do you agree with that change Thadeu? > I'd say the other options were met with silence. So, go forward with the patch and I'll ack it. Thanks. Cascardo. > > -- > Miguel Gómez > Igalia - http://www.igalia.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] classmate-laptop: Fix extra keys hardware id. 2012-07-24 3:09 ` Thadeu Lima de Souza Cascardo @ 2012-07-24 13:05 ` Miguel Gómez 2012-07-24 13:17 ` Miguel Gómez 0 siblings, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-07-24 13:05 UTC (permalink / raw) To: cascardo, don, mjg; +Cc: platform-driver-x86, linux-kernel, Miguel Gómez Since ACPI devices ids were changed to use always upper-case letters, the ACPI id of the extra keys (FNBT0000) was not maching the one defined in the driver (FnBT0000), causing the extra keys not to work. The patch replaces the driver id with the one reported by ACPI, fixing the problem. Signed-off-by: Miguel Gómez <magomez@igalia.com> --- drivers/platform/x86/classmate-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index e2230a2..43e6e54 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -39,7 +39,7 @@ struct cmpc_accel { #define CMPC_ACCEL_HID "ACCE0000" #define CMPC_TABLET_HID "TBLT0000" #define CMPC_IPML_HID "IPML200" -#define CMPC_KEYS_HID "FnBT0000" +#define CMPC_KEYS_HID "FNBT0000" /* * Generic input device code. -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] classmate-laptop: Fix extra keys hardware id. 2012-07-24 13:05 ` [PATCH] classmate-laptop: Fix extra keys hardware id Miguel Gómez @ 2012-07-24 13:17 ` Miguel Gómez 2012-07-24 13:21 ` Matthew Garrett 0 siblings, 1 reply; 15+ messages in thread From: Miguel Gómez @ 2012-07-24 13:17 UTC (permalink / raw) To: Miguel Gómez; +Cc: cascardo, don, mjg, platform-driver-x86, linux-kernel > Since ACPI devices ids were changed to use always upper-case letters, the ACPI > id of the extra keys (FNBT0000) was not maching the one defined in the driver > (FnBT0000), causing the extra keys not to work. > > The patch replaces the driver id with the one reported by ACPI, fixing the > problem. > > Signed-off-by: Miguel Gómez <magomez@igalia.com> I've created this patch on top of linux-next, but it won't apply over the patch I've just sent for the accelerometer (neither the later over the former). How do you want me to proceed? Should I sent this again over the accelerometer patch? Regards! -- Miguel Gómez Igalia - http://www.igalia.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] classmate-laptop: Fix extra keys hardware id. 2012-07-24 13:17 ` Miguel Gómez @ 2012-07-24 13:21 ` Matthew Garrett 0 siblings, 0 replies; 15+ messages in thread From: Matthew Garrett @ 2012-07-24 13:21 UTC (permalink / raw) To: Miguel Gómez; +Cc: cascardo, don, platform-driver-x86, linux-kernel On Tue, Jul 24, 2012 at 03:17:26PM +0200, Miguel Gómez wrote: > I've created this patch on top of linux-next, but it won't apply > over the patch I've just sent for the accelerometer (neither the > later over the former). > > How do you want me to proceed? Should I sent this again over the > accelerometer patch? I can merge them. Thanks for the patch! -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop 2012-06-29 13:39 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 2012-06-29 13:39 ` [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer Miguel Gómez @ 2012-07-17 14:34 ` Miguel Gómez 1 sibling, 0 replies; 15+ messages in thread From: Miguel Gómez @ 2012-07-17 14:34 UTC (permalink / raw) To: Miguel Gómez; +Cc: cascardo, don, mjg, platform-driver-x86, linux-kernel Hi! > Miguel Gómez (1): > classmate-laptop: Add support for Classmate V4 accelerometer. > > drivers/platform/x86/classmate-laptop.c | 400 ++++++++++++++++++++++++++++++- > 1 file changed, 398 insertions(+), 2 deletions(-) Anyone had a moment to give a look to this code? I'm eager to get some feedback and fix whatever is needed to put it in shape... and start playing Tux Racer with the Classmate 4 accelerometer :) Regards!! -- Miguel Gómez Igalia - http://www.igalia.com ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-07-24 13:21 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-06-29 12:46 [PATCH 0/1] Add support for Classmate V3 accelerometer to classmate-laptop Miguel Gómez 2012-06-29 12:46 ` [PATCH] classmate-laptop: Add support for Classmate V3 accelerometer Miguel Gómez 2012-06-29 13:39 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez 2012-06-29 13:39 ` [PATCH 1/1 v2] classmate-laptop: Add support for Classmate V4 accelerometer Miguel Gómez 2012-07-17 22:47 ` Thadeu Lima de Souza Cascardo 2012-07-18 13:53 ` Miguel Gómez 2012-07-23 13:28 ` Matthew Garrett 2012-07-23 13:33 ` Miguel Gómez 2012-07-23 13:36 ` Matthew Garrett 2012-07-23 13:44 ` Miguel Gómez 2012-07-24 3:09 ` Thadeu Lima de Souza Cascardo 2012-07-24 13:05 ` [PATCH] classmate-laptop: Fix extra keys hardware id Miguel Gómez 2012-07-24 13:17 ` Miguel Gómez 2012-07-24 13:21 ` Matthew Garrett 2012-07-17 14:34 ` [PATCH 0/1 v2] Add support for Classmate V4 accelerometer to classmate-laptop Miguel Gómez
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).