]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/input/mouse/alps.c
Merge branch 'release' of ssh://master.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / input / mouse / alps.c
index 070d75330afd335de4dcf1691477aeb1bc8593e9..64d70a9b714c9d84572f5c39d5f98b7a60f9d5b9 100644 (file)
@@ -36,7 +36,7 @@
 #define ALPS_PASS      0x20
 #define ALPS_FW_BK_2   0x40
 
-static struct alps_model_info alps_model_data[] = {
+static const struct alps_model_info alps_model_data[] = {
        { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO },            /* UMAX-530T */
        { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
        { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
@@ -48,11 +48,13 @@ static struct alps_model_info alps_model_data[] = {
        { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 },             /* NEC Versa L320 */
        { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
        { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS },                /* Dell Latitude D800 */
+       { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT },           /* ThinkPad R61 8918-5QG */
        { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
        { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 },             /* Ahtec Laptop */
        { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
        { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
        { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
+       { { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
 };
 
 /*
@@ -76,7 +78,7 @@ static struct alps_model_info alps_model_data[] = {
  * on a dualpoint, etc.
  */
 
-static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
+static void alps_process_packet(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
        unsigned char *packet = psmouse->packet;
@@ -85,8 +87,6 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
        int x, y, z, ges, fin, left, right, middle;
        int back = 0, forward = 0;
 
-       input_regs(dev, regs);
-
        if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
                input_report_key(dev2, BTN_LEFT,   packet[0] & 1);
                input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
@@ -181,13 +181,13 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
        input_sync(dev);
 }
 
-static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
 
        if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
                if (psmouse->pktcnt == 3) {
-                       alps_process_packet(psmouse, regs);
+                       alps_process_packet(psmouse);
                        return PSMOUSE_FULL_PACKET;
                }
                return PSMOUSE_GOOD_DATA;
@@ -202,17 +202,17 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *
                return PSMOUSE_BAD_DATA;
 
        if (psmouse->pktcnt == 6) {
-               alps_process_packet(psmouse, regs);
+               alps_process_packet(psmouse);
                return PSMOUSE_FULL_PACKET;
        }
 
        return PSMOUSE_GOOD_DATA;
 }
 
-static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
+static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
 {
        struct ps2dev *ps2dev = &psmouse->ps2dev;
-       unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
+       static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
        unsigned char param[4];
        int i;
 
@@ -253,11 +253,15 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers
 
        dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
 
-       for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++);
-       *version = (param[0] << 8) | (param[1] << 4) | i;
+       if (version) {
+               for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
+                       /* empty */;
+               *version = (param[0] << 8) | (param[1] << 4) | i;
+       }
 
        for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
-               if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
+               if (!memcmp(param, alps_model_data[i].signature,
+                           sizeof(alps_model_data[i].signature)))
                        return alps_model_data + i;
 
        return NULL;
@@ -382,32 +386,46 @@ static int alps_poll(struct psmouse *psmouse)
        return 0;
 }
 
-static int alps_reconnect(struct psmouse *psmouse)
+static int alps_hw_init(struct psmouse *psmouse, int *version)
 {
        struct alps_data *priv = psmouse->private;
-       int version;
 
-       psmouse_reset(psmouse);
-
-       if (!(priv->i = alps_get_model(psmouse, &version)))
+       priv->i = alps_get_model(psmouse, version);
+       if (!priv->i)
                return -1;
 
        if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
                return -1;
 
        if (alps_tap_mode(psmouse, 1)) {
-               printk(KERN_WARNING "alps.c: Failed to reenable hardware tapping\n");
+               printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
                return -1;
        }
 
        if (alps_absolute_mode(psmouse)) {
-               printk(KERN_ERR "alps.c: Failed to reenable absolute mode\n");
+               printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
                return -1;
        }
 
        if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
                return -1;
 
+       /* ALPS needs stream mode, otherwise it won't report any data */
+       if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
+               printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int alps_reconnect(struct psmouse *psmouse)
+{
+       psmouse_reset(psmouse);
+
+       if (alps_hw_init(psmouse, NULL))
+               return -1;
+
        return 0;
 }
 
@@ -426,28 +444,15 @@ int alps_init(struct psmouse *psmouse)
        struct input_dev *dev1 = psmouse->dev, *dev2;
        int version;
 
-       psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+       priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
        dev2 = input_allocate_device();
        if (!priv || !dev2)
                goto init_fail;
 
        priv->dev2 = dev2;
+       psmouse->private = priv;
 
-       if (!(priv->i = alps_get_model(psmouse, &version)))
-               goto init_fail;
-
-       if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
-               goto init_fail;
-
-       if (alps_tap_mode(psmouse, 1))
-               printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
-
-       if (alps_absolute_mode(psmouse)) {
-               printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
-               goto init_fail;
-       }
-
-       if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
+       if (alps_hw_init(psmouse, &version))
                goto init_fail;
 
        dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
@@ -482,7 +487,8 @@ int alps_init(struct psmouse *psmouse)
        dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
        dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-       input_register_device(priv->dev2);
+       if (input_register_device(priv->dev2))
+               goto init_fail;
 
        psmouse->protocol_handler = alps_process_byte;
        psmouse->poll = alps_poll;
@@ -496,17 +502,20 @@ int alps_init(struct psmouse *psmouse)
        return 0;
 
 init_fail:
+       psmouse_reset(psmouse);
        input_free_device(dev2);
        kfree(priv);
+       psmouse->private = NULL;
        return -1;
 }
 
 int alps_detect(struct psmouse *psmouse, int set_properties)
 {
        int version;
-       struct alps_model_info *model;
+       const struct alps_model_info *model;
 
-       if (!(model = alps_get_model(psmouse, &version)))
+       model = alps_get_model(psmouse, &version);
+       if (!model)
                return -1;
 
        if (set_properties) {