Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[safe/jmp/linux-2.6] / drivers / hwmon / hp_accel.c
index ee1ed42..be475e8 100644 (file)
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/semaphore.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
 #include <linux/freezer.h>
-#include <linux/version.h>
 #include <linux/uaccess.h>
 #include <linux/leds.h>
 #include <acpi/acpi_drivers.h>
@@ -85,25 +81,31 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
 
 /**
  * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
- * @handle: the handle of the device
+ * @lis3: pointer to the device struct
  *
- * Returns AE_OK on success.
+ * Returns 0 on success.
  */
-acpi_status lis3lv02d_acpi_init(acpi_handle handle)
+int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
 {
-       return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL);
+       struct acpi_device *dev = lis3->bus_priv;
+       if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
+                                NULL, NULL) != AE_OK)
+               return -EINVAL;
+
+       return 0;
 }
 
 /**
  * lis3lv02d_acpi_read - ACPI ALRD method: read a register
- * @handle: the handle of the device
+ * @lis3: pointer to the device struct
  * @reg:    the register to read
  * @ret:    result of the operation
  *
- * Returns AE_OK on success.
+ * Returns 0 on success.
  */
-acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret)
+int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
 {
+       struct acpi_device *dev = lis3->bus_priv;
        union acpi_object arg0 = { ACPI_TYPE_INTEGER };
        struct acpi_object_list args = { 1, &arg0 };
        unsigned long long lret;
@@ -111,21 +113,22 @@ acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret)
 
        arg0.integer.value = reg;
 
-       status = acpi_evaluate_integer(handle, "ALRD", &args, &lret);
+       status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
        *ret = lret;
-       return status;
+       return (status != AE_OK) ? -EINVAL : 0;
 }
 
 /**
  * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
- * @handle: the handle of the device
+ * @lis3: pointer to the device struct
  * @reg:    the register to write to
  * @val:    the value to write
  *
- * Returns AE_OK on success.
+ * Returns 0 on success.
  */
-acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val)
+int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
 {
+       struct acpi_device *dev = lis3->bus_priv;
        unsigned long long ret; /* Not used when writting */
        union acpi_object in_obj[2];
        struct acpi_object_list args = { 2, in_obj };
@@ -135,7 +138,10 @@ acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val)
        in_obj[1].type          = ACPI_TYPE_INTEGER;
        in_obj[1].integer.value = val;
 
-       return acpi_evaluate_integer(handle, "ALWR", &args, &ret);
+       if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
+               return -EINVAL;
+
+       return 0;
 }
 
 static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
@@ -152,6 +158,7 @@ static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
 static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
+static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
 static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
@@ -185,12 +192,18 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
        AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
        AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+       AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
        AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
        AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+       AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
        AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
-       AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
        AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
-       AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
+       AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
+       AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
+       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
+       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
        /* Intel-based HP Pavilion dv5 */
        AXIS_DMI_MATCH2("HPDV5_I",
                        PRODUCT_NAME, "HP Pavilion dv5",
@@ -201,10 +214,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
                        PRODUCT_NAME, "HP Pavilion dv5",
                        BOARD_NAME, "3600",
                        y_inverted),
+       AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
+       AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+       AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
- * HP Compaq 8710x Notebook PC / Mobile Workstation
  * "NC2400" "HP Compaq nc2400"
  * "NX74x0" "HP Compaq nx74"
  * "NX6325" "HP Compaq nx6325"
@@ -214,7 +229,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
 
 static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
 {
-       acpi_handle handle = lis3_dev.device->handle;
+       struct acpi_device *dev = lis3_dev.bus_priv;
        unsigned long long ret; /* Not used when writing */
        union acpi_object in_obj[1];
        struct acpi_object_list args = { 1, in_obj };
@@ -222,7 +237,7 @@ static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness
        in_obj[0].type          = ACPI_TYPE_INTEGER;
        in_obj[0].integer.value = !!value;
 
-       acpi_evaluate_integer(handle, "ALED", &args, &ret);
+       acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
 }
 
 static struct delayed_led_classdev hpled_led = {
@@ -259,23 +274,6 @@ static void lis3lv02d_enum_resources(struct acpi_device *device)
                printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
 }
 
-static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
-{
-       u8 lo, hi;
-
-       lis3_dev.read(handle, reg - 1, &lo);
-       lis3_dev.read(handle, reg, &hi);
-       /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
-       return (s16)((hi << 8) | lo);
-}
-
-static s16 lis3lv02d_read_8(acpi_handle handle, int reg)
-{
-       s8 lo;
-       lis3_dev.read(handle, reg, &lo);
-       return lo;
-}
-
 static int lis3lv02d_add(struct acpi_device *device)
 {
        int ret;
@@ -283,7 +281,7 @@ static int lis3lv02d_add(struct acpi_device *device)
        if (!device)
                return -EINVAL;
 
-       lis3_dev.device = device;
+       lis3_dev.bus_priv = device;
        lis3_dev.init = lis3lv02d_acpi_init;
        lis3_dev.read = lis3lv02d_acpi_read;
        lis3_dev.write = lis3lv02d_acpi_write;
@@ -291,23 +289,8 @@ static int lis3lv02d_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
        device->driver_data = &lis3_dev;
 
-       lis3lv02d_acpi_read(device->handle, WHO_AM_I, &lis3_dev.whoami);
-       switch (lis3_dev.whoami) {
-       case LIS_DOUBLE_ID:
-               printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n");
-               lis3_dev.read_data = lis3lv02d_read_16;
-               lis3_dev.mdps_max_val = 2048;
-               break;
-       case LIS_SINGLE_ID:
-               printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n");
-               lis3_dev.read_data = lis3lv02d_read_8;
-               lis3_dev.mdps_max_val = 128;
-               break;
-       default:
-               printk(KERN_ERR DRIVER_NAME
-                       ": unknown sensor type 0x%X\n", lis3_dev.whoami);
-               return -EINVAL;
-       }
+       /* obtain IRQ number of our device from ACPI */
+       lis3lv02d_enum_resources(device);
 
        /* If possible use a "standard" axes order */
        if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
@@ -316,18 +299,17 @@ static int lis3lv02d_add(struct acpi_device *device)
                lis3_dev.ac = lis3lv02d_axis_normal;
        }
 
-       INIT_WORK(&hpled_led.work, delayed_set_status_worker);
-       ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+       /* call the core layer do its init */
+       ret = lis3lv02d_init_device(&lis3_dev);
        if (ret)
                return ret;
 
-       /* obtain IRQ number of our device from ACPI */
-       lis3lv02d_enum_resources(lis3_dev.device);
-
-       ret = lis3lv02d_init_device(&lis3_dev);
+       INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+       ret = led_classdev_register(NULL, &hpled_led.led_classdev);
        if (ret) {
+               lis3lv02d_joystick_disable();
+               lis3lv02d_poweroff(&lis3_dev);
                flush_work(&hpled_led.work);
-               led_classdev_unregister(&hpled_led.led_classdev);
                return ret;
        }
 
@@ -340,12 +322,12 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
                return -EINVAL;
 
        lis3lv02d_joystick_disable();
-       lis3lv02d_poweroff(device->handle);
+       lis3lv02d_poweroff(&lis3_dev);
 
        flush_work(&hpled_led.work);
        led_classdev_unregister(&hpled_led.led_classdev);
 
-       return lis3lv02d_remove_fs();
+       return lis3lv02d_remove_fs(&lis3_dev);
 }
 
 
@@ -353,19 +335,13 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
 static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
 {
        /* make sure the device is off when we suspend */
-       lis3lv02d_poweroff(device->handle);
+       lis3lv02d_poweroff(&lis3_dev);
        return 0;
 }
 
 static int lis3lv02d_resume(struct acpi_device *device)
 {
-       /* put back the device in the right state (ACPI might turn it on) */
-       mutex_lock(&lis3_dev.lock);
-       if (lis3_dev.usage > 0)
-               lis3lv02d_poweron(device->handle);
-       else
-               lis3lv02d_poweroff(device->handle);
-       mutex_unlock(&lis3_dev.lock);
+       lis3lv02d_poweron(&lis3_dev);
        return 0;
 }
 #else