]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/input/mouse/appletouch.c
Merge branch 'bjorn-initcall-cleanup' into release
[linux-2.6-omap-h63xx.git] / drivers / input / mouse / appletouch.c
index 079816e6b23b042bff9a883aa984ffea757ee5a6..454b96112f03187b5e5c9ea042af86c166902332 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
- * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005-2008 Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
  * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
 #include <linux/module.h>
 #include <linux/usb/input.h>
 
-/* Type of touchpad */
-enum atp_touchpad_type {
-       ATP_FOUNTAIN,
-       ATP_GEYSER1,
-       ATP_GEYSER2,
-       ATP_GEYSER3,
-       ATP_GEYSER4
+/*
+ * Note: We try to keep the touchpad aspect ratio while still doing only
+ * simple arithmetics:
+ *     0 <= x <= (xsensors - 1) * xfact
+ *     0 <= y <= (ysensors - 1) * yfact
+ */
+struct atp_info {
+       int xsensors;                           /* number of X sensors */
+       int xsensors_17;                        /* 17" models have more sensors */
+       int ysensors;                           /* number of Y sensors */
+       int xfact;                              /* X multiplication factor */
+       int yfact;                              /* Y multiplication factor */
+       int datalen;                            /* size of USB transfers */
+       void (*callback)(struct urb *);         /* callback function */
+};
+
+static void atp_complete_geyser_1_2(struct urb *urb);
+static void atp_complete_geyser_3_4(struct urb *urb);
+
+static const struct atp_info fountain_info = {
+       .xsensors       = 16,
+       .xsensors_17    = 26,
+       .ysensors       = 16,
+       .xfact          = 64,
+       .yfact          = 43,
+       .datalen        = 81,
+       .callback       = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser1_info = {
+       .xsensors       = 16,
+       .xsensors_17    = 26,
+       .ysensors       = 16,
+       .xfact          = 64,
+       .yfact          = 43,
+       .datalen        = 81,
+       .callback       = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser2_info = {
+       .xsensors       = 15,
+       .xsensors_17    = 20,
+       .ysensors       = 9,
+       .xfact          = 64,
+       .yfact          = 43,
+       .datalen        = 64,
+       .callback       = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser3_info = {
+       .xsensors       = 20,
+       .ysensors       = 10,
+       .xfact          = 64,
+       .yfact          = 64,
+       .datalen        = 64,
+       .callback       = atp_complete_geyser_3_4,
 };
 
-#define ATP_DEVICE(prod, type)                                 \
+static const struct atp_info geyser4_info = {
+       .xsensors       = 20,
+       .ysensors       = 10,
+       .xfact          = 64,
+       .yfact          = 64,
+       .datalen        = 64,
+       .callback       = atp_complete_geyser_3_4,
+};
+
+#define ATP_DEVICE(prod, info)                                 \
 {                                                              \
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |             \
                       USB_DEVICE_ID_MATCH_INT_CLASS |          \
@@ -53,7 +111,7 @@ enum atp_touchpad_type {
        .idProduct = (prod),                                    \
        .bInterfaceClass = 0x03,                                \
        .bInterfaceProtocol = 0x02,                             \
-       .driver_info = ATP_ ## type,                            \
+       .driver_info = (unsigned long) &info,                   \
 }
 
 /*
@@ -62,43 +120,39 @@ enum atp_touchpad_type {
  *  According to Info.plist Geyser IV is the same as Geyser III.)
  */
 
-static struct usb_device_id atp_table [] = {
+static struct usb_device_id atp_table[] = {
        /* PowerBooks Feb 2005, iBooks G4 */
-       ATP_DEVICE(0x020e, FOUNTAIN),   /* FOUNTAIN ANSI */
-       ATP_DEVICE(0x020f, FOUNTAIN),   /* FOUNTAIN ISO */
-       ATP_DEVICE(0x030a, FOUNTAIN),   /* FOUNTAIN TP ONLY */
-       ATP_DEVICE(0x030b, GEYSER1),    /* GEYSER 1 TP ONLY */
+       ATP_DEVICE(0x020e, fountain_info),      /* FOUNTAIN ANSI */
+       ATP_DEVICE(0x020f, fountain_info),      /* FOUNTAIN ISO */
+       ATP_DEVICE(0x030a, fountain_info),      /* FOUNTAIN TP ONLY */
+       ATP_DEVICE(0x030b, geyser1_info),       /* GEYSER 1 TP ONLY */
 
        /* PowerBooks Oct 2005 */
-       ATP_DEVICE(0x0214, GEYSER2),    /* GEYSER 2 ANSI */
-       ATP_DEVICE(0x0215, GEYSER2),    /* GEYSER 2 ISO */
-       ATP_DEVICE(0x0216, GEYSER2),    /* GEYSER 2 JIS */
+       ATP_DEVICE(0x0214, geyser2_info),       /* GEYSER 2 ANSI */
+       ATP_DEVICE(0x0215, geyser2_info),       /* GEYSER 2 ISO */
+       ATP_DEVICE(0x0216, geyser2_info),       /* GEYSER 2 JIS */
 
        /* Core Duo MacBook & MacBook Pro */
-       ATP_DEVICE(0x0217, GEYSER3),    /* GEYSER 3 ANSI */
-       ATP_DEVICE(0x0218, GEYSER3),    /* GEYSER 3 ISO */
-       ATP_DEVICE(0x0219, GEYSER3),    /* GEYSER 3 JIS */
+       ATP_DEVICE(0x0217, geyser3_info),       /* GEYSER 3 ANSI */
+       ATP_DEVICE(0x0218, geyser3_info),       /* GEYSER 3 ISO */
+       ATP_DEVICE(0x0219, geyser3_info),       /* GEYSER 3 JIS */
 
        /* Core2 Duo MacBook & MacBook Pro */
-       ATP_DEVICE(0x021a, GEYSER4),    /* GEYSER 4 ANSI */
-       ATP_DEVICE(0x021b, GEYSER4),    /* GEYSER 4 ISO */
-       ATP_DEVICE(0x021c, GEYSER4),    /* GEYSER 4 JIS */
+       ATP_DEVICE(0x021a, geyser4_info),       /* GEYSER 4 ANSI */
+       ATP_DEVICE(0x021b, geyser4_info),       /* GEYSER 4 ISO */
+       ATP_DEVICE(0x021c, geyser4_info),       /* GEYSER 4 JIS */
 
        /* Core2 Duo MacBook3,1 */
-       ATP_DEVICE(0x0229, GEYSER4),    /* GEYSER 4 HF ANSI */
-       ATP_DEVICE(0x022a, GEYSER4),    /* GEYSER 4 HF ISO */
-       ATP_DEVICE(0x022b, GEYSER4),    /* GEYSER 4 HF JIS */
+       ATP_DEVICE(0x0229, geyser4_info),       /* GEYSER 4 HF ANSI */
+       ATP_DEVICE(0x022a, geyser4_info),       /* GEYSER 4 HF ISO */
+       ATP_DEVICE(0x022b, geyser4_info),       /* GEYSER 4 HF JIS */
 
        /* Terminating entry */
        { }
 };
 MODULE_DEVICE_TABLE(usb, atp_table);
 
-/*
- * number of sensors. Note that only 16 instead of 26 X (horizontal)
- * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
- * (vertical) sensors.
- */
+/* maximum number of sensors */
 #define ATP_XSENSORS   26
 #define ATP_YSENSORS   16
 
@@ -107,21 +161,6 @@ MODULE_DEVICE_TABLE(usb, atp_table);
 
 /* maximum pressure this driver will report */
 #define ATP_PRESSURE   300
-/*
- * multiplication factor for the X and Y coordinates.
- * We try to keep the touchpad aspect ratio while still doing only simple
- * arithmetics.
- * The factors below give coordinates like:
- *
- *      0 <= x <  960 on 12" and 15" Powerbooks
- *      0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
- *      0 <= x < 1216 on MacBooks and 15" MacBook Pro
- *
- *      0 <= y <  646 on all Powerbooks
- *      0 <= y <  774 on all MacBooks
- */
-#define ATP_XFACT      64
-#define ATP_YFACT      43
 
 /*
  * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
@@ -159,7 +198,7 @@ struct atp {
        struct urb              *urb;           /* usb request block */
        u8                      *data;          /* transferred data */
        struct input_dev        *input;         /* input dev */
-       enum atp_touchpad_type  type;           /* type of touchpad */
+       const struct atp_info   *info;          /* touchpad model */
        bool                    open;
        bool                    valid;          /* are the samples valid? */
        bool                    size_detect_done;
@@ -169,7 +208,6 @@ struct atp {
        signed char             xy_cur[ATP_XSENSORS + ATP_YSENSORS];
        signed char             xy_old[ATP_XSENSORS + ATP_YSENSORS];
        int                     xy_acc[ATP_XSENSORS + ATP_YSENSORS];
-       int                     datalen;        /* size of USB transfer */
        int                     idlecount;      /* number of empty packets */
        struct work_struct      work;
 };
@@ -359,7 +397,7 @@ static int atp_status_check(struct urb *urb)
                if (!dev->overflow_warned) {
                        printk(KERN_WARNING "appletouch: OVERFLOW with data "
                                "length %d, actual length is %d\n",
-                               dev->datalen, dev->urb->actual_length);
+                               dev->info->datalen, dev->urb->actual_length);
                        dev->overflow_warned = true;
                }
        case -ECONNRESET:
@@ -377,7 +415,7 @@ static int atp_status_check(struct urb *urb)
        }
 
        /* drop incomplete datasets */
-       if (dev->urb->actual_length != dev->datalen) {
+       if (dev->urb->actual_length != dev->info->datalen) {
                dprintk("appletouch: incomplete data package"
                        " (first byte: %d, length: %d).\n",
                        dev->data[0], dev->urb->actual_length);
@@ -387,6 +425,25 @@ static int atp_status_check(struct urb *urb)
        return ATP_URB_STATUS_SUCCESS;
 }
 
+static void atp_detect_size(struct atp *dev)
+{
+       int i;
+
+       /* 17" Powerbooks have extra X sensors */
+       for (i = dev->info->xsensors; i < ATP_XSENSORS; i++) {
+               if (dev->xy_cur[i]) {
+
+                       printk(KERN_INFO "appletouch: 17\" model detected.\n");
+
+                       input_set_abs_params(dev->input, ABS_X, 0,
+                                            (dev->info->xsensors_17 - 1) *
+                                                       dev->info->xfact - 1,
+                                            ATP_FUZZ, 0);
+                       break;
+               }
+       }
+}
+
 /*
  * USB interrupt callback functions
  */
@@ -407,7 +464,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                goto exit;
 
        /* reorder the sensors values */
-       if (dev->type == ATP_GEYSER2) {
+       if (dev->info == &geyser2_info) {
                memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
                /*
@@ -437,8 +494,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                                dev->xy_cur[i + 24] = dev->data[5 * i + 44];
 
                        /* Y values */
-                       dev->xy_cur[i + 26] = dev->data[5 * i +  1];
-                       dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+                       dev->xy_cur[ATP_XSENSORS + i] = dev->data[5 * i +  1];
+                       dev->xy_cur[ATP_XSENSORS + i + 8] = dev->data[5 * i + 3];
                }
        }
 
@@ -453,32 +510,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
                memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
                /* Perform size detection, if not done already */
-               if (!dev->size_detect_done) {
-
-                       /* 17" Powerbooks have extra X sensors */
-                       for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
-                            i < ATP_XSENSORS; i++) {
-                               if (!dev->xy_cur[i])
-                                       continue;
-
-                               printk(KERN_INFO
-                                       "appletouch: 17\" model detected.\n");
-
-                               if (dev->type == ATP_GEYSER2)
-                                       input_set_abs_params(dev->input, ABS_X,
-                                                            0,
-                                                            (20 - 1) *
-                                                            ATP_XFACT - 1,
-                                                            ATP_FUZZ, 0);
-                               else
-                                       input_set_abs_params(dev->input, ABS_X,
-                                                            0,
-                                                            (26 - 1) *
-                                                            ATP_XFACT - 1,
-                                                            ATP_FUZZ, 0);
-                               break;
-                       }
-
+               if (unlikely(!dev->size_detect_done)) {
+                       atp_detect_size(dev);
                        dev->size_detect_done = 1;
                        goto exit;
                }
@@ -499,10 +532,10 @@ static void atp_complete_geyser_1_2(struct urb *urb)
        dbg_dump("accumulator", dev->xy_acc);
 
        x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
-                             ATP_XFACT, &x_z, &x_f);
+                             dev->info->xfact, &x_z, &x_f);
        y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
-                             ATP_YFACT, &y_z, &y_f);
-       key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+                             dev->info->yfact, &y_z, &y_f);
+       key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
 
        if (x && y) {
                if (dev->x_old != -1) {
@@ -583,7 +616,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
        dbg_dump("sample", dev->xy_cur);
 
        /* Just update the base values (i.e. touchpad in untouched state) */
-       if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
+       if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
 
                dprintk(KERN_DEBUG "appletouch: updated base values\n");
 
@@ -610,10 +643,10 @@ static void atp_complete_geyser_3_4(struct urb *urb)
        dbg_dump("accumulator", dev->xy_acc);
 
        x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
-                             ATP_XFACT, &x_z, &x_f);
+                             dev->info->xfact, &x_z, &x_f);
        y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
-                             ATP_YFACT, &y_z, &y_f);
-       key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+                             dev->info->yfact, &y_z, &y_f);
+       key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
 
        if (x && y) {
                if (dev->x_old != -1) {
@@ -705,7 +738,7 @@ static int atp_handle_geyser(struct atp *dev)
 {
        struct usb_device *udev = dev->udev;
 
-       if (dev->type != ATP_FOUNTAIN) {
+       if (dev->info != &fountain_info) {
                /* switch to raw sensor mode */
                if (atp_geyser_init(udev))
                        return -EIO;
@@ -726,6 +759,7 @@ static int atp_probe(struct usb_interface *iface,
        struct usb_endpoint_descriptor *endpoint;
        int int_in_endpointAddr = 0;
        int i, error = -ENOMEM;
+       const struct atp_info *info = (const struct atp_info *)id->driver_info;
 
        /* set up the endpoint information */
        /* use only the first interrupt-in endpoint */
@@ -753,35 +787,22 @@ static int atp_probe(struct usb_interface *iface,
 
        dev->udev = udev;
        dev->input = input_dev;
-       dev->type = id->driver_info;
+       dev->info = info;
        dev->overflow_warned = false;
-       if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1)
-               dev->datalen = 81;
-       else
-               dev->datalen = 64;
 
        dev->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!dev->urb)
                goto err_free_devs;
 
-       dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
+       dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL,
                                     &dev->urb->transfer_dma);
        if (!dev->data)
                goto err_free_urb;
 
-       /* Select the USB complete (callback) function */
-       if (dev->type == ATP_FOUNTAIN ||
-           dev->type == ATP_GEYSER1 ||
-           dev->type == ATP_GEYSER2)
-               usb_fill_int_urb(dev->urb, udev,
-                                usb_rcvintpipe(udev, int_in_endpointAddr),
-                                dev->data, dev->datalen,
-                                atp_complete_geyser_1_2, dev, 1);
-       else
-               usb_fill_int_urb(dev->urb, udev,
-                                usb_rcvintpipe(udev, int_in_endpointAddr),
-                                dev->data, dev->datalen,
-                                atp_complete_geyser_3_4, dev, 1);
+       usb_fill_int_urb(dev->urb, udev,
+                        usb_rcvintpipe(udev, int_in_endpointAddr),
+                        dev->data, dev->info->datalen,
+                        dev->info->callback, dev, 1);
 
        error = atp_handle_geyser(dev);
        if (error)
@@ -802,35 +823,12 @@ static int atp_probe(struct usb_interface *iface,
 
        set_bit(EV_ABS, input_dev->evbit);
 
-       if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
-               /*
-                * MacBook have 20 X sensors, 10 Y sensors
-                */
-               input_set_abs_params(input_dev, ABS_X, 0,
-                                    ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
-               input_set_abs_params(input_dev, ABS_Y, 0,
-                                    ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
-       } else if (dev->type == ATP_GEYSER2) {
-               /*
-                * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
-                * later.
-                */
-               input_set_abs_params(input_dev, ABS_X, 0,
-                                    ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
-               input_set_abs_params(input_dev, ABS_Y, 0,
-                                    ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
-       } else {
-               /*
-                * 12" and 15" Powerbooks only have 16 x sensors,
-                * 17" models are detected later.
-                */
-               input_set_abs_params(input_dev, ABS_X, 0,
-                                    (16 - 1) * ATP_XFACT - 1,
-                                    ATP_FUZZ, 0);
-               input_set_abs_params(input_dev, ABS_Y, 0,
-                                    (ATP_YSENSORS - 1) * ATP_YFACT - 1,
-                                    ATP_FUZZ, 0);
-       }
+       input_set_abs_params(input_dev, ABS_X, 0,
+                            (dev->info->xsensors - 1) * dev->info->xfact - 1,
+                            ATP_FUZZ, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0,
+                            (dev->info->ysensors - 1) * dev->info->yfact - 1,
+                            ATP_FUZZ, 0);
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
        set_bit(EV_KEY, input_dev->evbit);
@@ -852,7 +850,7 @@ static int atp_probe(struct usb_interface *iface,
        return 0;
 
  err_free_buffer:
-       usb_buffer_free(dev->udev, dev->datalen,
+       usb_buffer_free(dev->udev, dev->info->datalen,
                        dev->data, dev->urb->transfer_dma);
  err_free_urb:
        usb_free_urb(dev->urb);
@@ -871,7 +869,7 @@ static void atp_disconnect(struct usb_interface *iface)
        if (dev) {
                usb_kill_urb(dev->urb);
                input_unregister_device(dev->input);
-               usb_buffer_free(dev->udev, dev->datalen,
+               usb_buffer_free(dev->udev, dev->info->datalen,
                                dev->data, dev->urb->transfer_dma);
                usb_free_urb(dev->urb);
                kfree(dev);