Commit 1acd2de5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull more input updates from Dmitry Torokhov:
 "The second round of updates for the input subsystem.

  Updates to ALPS an bfin_roraty drivers and a couple oother fixups"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: psmouse - use IS_ENABLED instead of homegrown code
  Input: bfin_rotary - introduce open and close methods
  Input: bfin_rotary - convert to use managed resources
  Input: bfin_rotary - use generic IO functions
  Input: bfin_rotary - move pin lists into into platform data
  Input: bfin_rotary - move platform header to linux/platform_data
  Input: bfin_rotary - mark suspend and resume code as __maybe_unused
  Input: bfin_rotary - fix potential oops in interrupt handler
  Input: ALPS - move v7 packet info to Documentation and v6 packet info
  Input: ALPS - fix confusing comment in protocol data
  Input: ALPS - do not mix trackstick and external PS/2 mouse data
  Input: ALPS - fix trackstick detection on some Dell Latitudes
  Input: ALPS - consolidate setting protocol parameters
  Input: ALPS - split protocol data from model info
  Input: ALPS - make Rushmore a separate protocol
  Input: ALPS - renumber protocol numbers
  Input: adi - remove an unnecessary check
  Input: pxa27x_keypad - remove an unneeded NULL check
  Input: soc_button_array - use "Windows" key for "Home"
parents b5ccb078 4c971aa7
...@@ -3,8 +3,8 @@ ALPS Touchpad Protocol ...@@ -3,8 +3,8 @@ ALPS Touchpad Protocol
Introduction Introduction
------------ ------------
Currently the ALPS touchpad driver supports five protocol versions in use by Currently the ALPS touchpad driver supports seven protocol versions in use by
ALPS touchpads, called versions 1, 2, 3, 4 and 5. ALPS touchpads, called versions 1, 2, 3, 4, 5, 6 and 7.
Since roughly mid-2010 several new ALPS touchpads have been released and Since roughly mid-2010 several new ALPS touchpads have been released and
integrated into a variety of laptops and netbooks. These new touchpads integrated into a variety of laptops and netbooks. These new touchpads
...@@ -240,3 +240,67 @@ For mt, the format is: ...@@ -240,3 +240,67 @@ For mt, the format is:
byte 3: 0 x23 x22 x21 x20 x19 x18 x17 byte 3: 0 x23 x22 x21 x20 x19 x18 x17
byte 4: 0 x9 x8 x7 x6 x5 x4 x3 byte 4: 0 x9 x8 x7 x6 x5 x4 x3
byte 5: 0 x16 x15 x14 x13 x12 x11 x10 byte 5: 0 x16 x15 x14 x13 x12 x11 x10
ALPS Absolute Mode - Protocol Version 6
---------------------------------------
For trackstick packet, the format is:
byte 0: 1 1 1 1 1 1 1 1
byte 1: 0 X6 X5 X4 X3 X2 X1 X0
byte 2: 0 Y6 Y5 Y4 Y3 Y2 Y1 Y0
byte 3: ? Y7 X7 ? ? M R L
byte 4: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
byte 5: 0 1 1 1 1 1 1 1
For touchpad packet, the format is:
byte 0: 1 1 1 1 1 1 1 1
byte 1: 0 0 0 0 x3 x2 x1 x0
byte 2: 0 0 0 0 y3 y2 y1 y0
byte 3: ? x7 x6 x5 x4 ? r l
byte 4: ? y7 y6 y5 y4 ? ? ?
byte 5: z7 z6 z5 z4 z3 z2 z1 z0
(v6 touchpad does not have middle button)
ALPS Absolute Mode - Protocol Version 7
---------------------------------------
For trackstick packet, the format is:
byte 0: 0 1 0 0 1 0 0 0
byte 1: 1 1 * * 1 M R L
byte 2: X7 1 X5 X4 X3 X2 X1 X0
byte 3: Z6 1 Y6 X6 1 Y2 Y1 Y0
byte 4: Y7 0 Y5 Y4 Y3 1 1 0
byte 5: T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
For touchpad packet, the format is:
packet-fmt b7 b6 b5 b4 b3 b2 b1 b0
byte 0: TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0
byte 0: NEW L 1 X1-5 1 1 Y0-2 Y0-1 Y0-0
byte 1: Y0-10 Y0-9 Y0-8 Y0-7 Y0-6 Y0-5 Y0-4 Y0-3
byte 2: X0-11 1 X0-10 X0-9 X0-8 X0-7 X0-6 X0-5
byte 3: X1-11 1 X0-4 X0-3 1 X0-2 X0-1 X0-0
byte 4: TWO X1-10 TWO X1-9 X1-8 X1-7 X1-6 X1-5 X1-4
byte 4: MULTI X1-10 TWO X1-9 X1-8 X1-7 X1-6 Y1-5 1
byte 4: NEW X1-10 TWO X1-9 X1-8 X1-7 X1-6 0 0
byte 5: TWO & NEW Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 Y1-5 Y1-4
byte 5: MULTI Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 F-1 F-0
L: Left button
R / M: Non-clickpads: Right / Middle button
Clickpads: When > 2 fingers are down, and some fingers
are in the button area, then the 2 coordinates reported
are for fingers outside the button area and these report
extra fingers being present in the right / left button
area. Note these fingers are not added to the F field!
so if a TWO packet is received and R = 1 then there are
3 fingers down, etc.
TWO: 1: Two touches present, byte 0/4/5 are in TWO fmt
0: If byte 4 bit 0 is 1, then byte 0/4/5 are in MULTI fmt
otherwise byte 0 bit 4 must be set and byte 0/4/5 are
in NEW fmt
F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ...
...@@ -666,7 +666,14 @@ static struct platform_device bfin_sport1_uart_device = { ...@@ -666,7 +666,14 @@ static struct platform_device bfin_sport1_uart_device = {
#endif #endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY) #if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
#include <asm/bfin_rotary.h> #include <linux/platform_data/bfin_rotary.h>
static const u16 per_cnt[] = {
P_CNT_CUD,
P_CNT_CDG,
P_CNT_CZM,
0
};
static struct bfin_rotary_platform_data bfin_rotary_data = { static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/ /*.rotary_up_key = KEY_UP,*/
...@@ -676,9 +683,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = { ...@@ -676,9 +683,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.debounce = 10, /* 0..17 */ .debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE, .mode = ROT_QUAD_ENC | ROT_DEBE,
.pm_wakeup = 1, .pm_wakeup = 1,
.pin_list = per_cnt,
}; };
static struct resource bfin_rotary_resources[] = { static struct resource bfin_rotary_resources[] = {
{
.start = CNT_CONFIG,
.end = CNT_CONFIG + 0xff,
.flags = IORESOURCE_MEM,
},
{ {
.start = IRQ_CNT, .start = IRQ_CNT,
.end = IRQ_CNT, .end = IRQ_CNT,
......
...@@ -1092,7 +1092,14 @@ static struct platform_device bfin_device_gpiokeys = { ...@@ -1092,7 +1092,14 @@ static struct platform_device bfin_device_gpiokeys = {
#endif #endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY) #if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
#include <asm/bfin_rotary.h> #include <linux/platform_data/bfin_rotary.h>
static const u16 per_cnt[] = {
P_CNT_CUD,
P_CNT_CDG,
P_CNT_CZM,
0
};
static struct bfin_rotary_platform_data bfin_rotary_data = { static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/ /*.rotary_up_key = KEY_UP,*/
...@@ -1102,9 +1109,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = { ...@@ -1102,9 +1109,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.debounce = 10, /* 0..17 */ .debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE, .mode = ROT_QUAD_ENC | ROT_DEBE,
.pm_wakeup = 1, .pm_wakeup = 1,
.pin_list = per_cnt,
}; };
static struct resource bfin_rotary_resources[] = { static struct resource bfin_rotary_resources[] = {
{
.start = CNT_CONFIG,
.end = CNT_CONFIG + 0xff,
.flags = IORESOURCE_MEM,
},
{ {
.start = IRQ_CNT, .start = IRQ_CNT,
.end = IRQ_CNT, .end = IRQ_CNT,
......
...@@ -159,7 +159,7 @@ static struct platform_device bf54x_kpad_device = { ...@@ -159,7 +159,7 @@ static struct platform_device bf54x_kpad_device = {
#endif #endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY) #if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
#include <asm/bfin_rotary.h> #include <linux/platform_data/bfin_rotary.h>
static struct bfin_rotary_platform_data bfin_rotary_data = { static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/ /*.rotary_up_key = KEY_UP,*/
...@@ -172,6 +172,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = { ...@@ -172,6 +172,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
}; };
static struct resource bfin_rotary_resources[] = { static struct resource bfin_rotary_resources[] = {
{
.start = CNT_CONFIG,
.end = CNT_CONFIG + 0xff,
.flags = IORESOURCE_MEM,
},
{ {
.start = IRQ_CNT, .start = IRQ_CNT,
.end = IRQ_CNT, .end = IRQ_CNT,
......
...@@ -75,7 +75,7 @@ static struct platform_device bfin_isp1760_device = { ...@@ -75,7 +75,7 @@ static struct platform_device bfin_isp1760_device = {
#endif #endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY) #if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
#include <asm/bfin_rotary.h> #include <linux/platform_data/bfin_rotary.h>
static struct bfin_rotary_platform_data bfin_rotary_data = { static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/ /*.rotary_up_key = KEY_UP,*/
...@@ -87,6 +87,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = { ...@@ -87,6 +87,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
}; };
static struct resource bfin_rotary_resources[] = { static struct resource bfin_rotary_resources[] = {
{
.start = CNT_CONFIG,
.end = CNT_CONFIG + 0xff,
.flags = IORESOURCE_MEM,
},
{ {
.start = IRQ_CNT, .start = IRQ_CNT,
.end = IRQ_CNT, .end = IRQ_CNT,
......
...@@ -535,8 +535,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -535,8 +535,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
} }
} }
fail2: for (i = 0; i < 2; i++) fail2: for (i = 0; i < 2; i++)
if (port->adi[i].dev) input_free_device(port->adi[i].dev);
input_free_device(port->adi[i].dev);
gameport_close(gameport); gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL); fail1: gameport_set_drvdata(gameport, NULL);
kfree(port); kfree(port);
......
...@@ -345,13 +345,11 @@ static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) ...@@ -345,13 +345,11 @@ static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
{ {
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev; struct input_dev *input_dev = keypad->input_dev;
const struct matrix_keymap_data *keymap_data =
pdata ? pdata->matrix_keymap_data : NULL;
unsigned short keycode; unsigned short keycode;
int i; int i;
int error; int error;
error = matrix_keypad_build_keymap(keymap_data, NULL, error = matrix_keypad_build_keymap(pdata->matrix_keymap_data, NULL,
pdata->matrix_key_rows, pdata->matrix_key_rows,
pdata->matrix_key_cols, pdata->matrix_key_cols,
keypad->keycodes, input_dev); keypad->keycodes, input_dev);
......
...@@ -7,29 +7,37 @@ ...@@ -7,29 +7,37 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_data/bfin_rotary.h>
#include <asm/portmux.h> #include <asm/portmux.h>
#include <asm/bfin_rotary.h>
static const u16 per_cnt[] = { #define CNT_CONFIG_OFF 0 /* CNT Config Offset */
P_CNT_CUD, #define CNT_IMASK_OFF 4 /* CNT Interrupt Mask Offset */
P_CNT_CDG, #define CNT_STATUS_OFF 8 /* CNT Status Offset */
P_CNT_CZM, #define CNT_COMMAND_OFF 12 /* CNT Command Offset */
0 #define CNT_DEBOUNCE_OFF 16 /* CNT Debounce Offset */
}; #define CNT_COUNTER_OFF 20 /* CNT Counter Offset */
#define CNT_MAX_OFF 24 /* CNT Maximum Count Offset */
#define CNT_MIN_OFF 28 /* CNT Minimum Count Offset */
struct bfin_rot { struct bfin_rot {
struct input_dev *input; struct input_dev *input;
void __iomem *base;
int irq; int irq;
unsigned int up_key; unsigned int up_key;
unsigned int down_key; unsigned int down_key;
unsigned int button_key; unsigned int button_key;
unsigned int rel_code; unsigned int rel_code;
unsigned short mode;
unsigned short debounce;
unsigned short cnt_config; unsigned short cnt_config;
unsigned short cnt_imask; unsigned short cnt_imask;
unsigned short cnt_debounce; unsigned short cnt_debounce;
...@@ -59,18 +67,17 @@ static void report_rotary_event(struct bfin_rot *rotary, int delta) ...@@ -59,18 +67,17 @@ static void report_rotary_event(struct bfin_rot *rotary, int delta)
static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
{ {
struct platform_device *pdev = dev_id; struct bfin_rot *rotary = dev_id;
struct bfin_rot *rotary = platform_get_drvdata(pdev);
int delta; int delta;
switch (bfin_read_CNT_STATUS()) { switch (readw(rotary->base + CNT_STATUS_OFF)) {
case ICII: case ICII:
break; break;
case UCII: case UCII:
case DCII: case DCII:
delta = bfin_read_CNT_COUNTER(); delta = readl(rotary->base + CNT_COUNTER_OFF);
if (delta) if (delta)
report_rotary_event(rotary, delta); report_rotary_event(rotary, delta);
break; break;
...@@ -83,16 +90,52 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) ...@@ -83,16 +90,52 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
break; break;
} }
bfin_write_CNT_COMMAND(W1LCNT_ZERO); /* Clear COUNTER */ writew(W1LCNT_ZERO, rotary->base + CNT_COMMAND_OFF); /* Clear COUNTER */
bfin_write_CNT_STATUS(-1); /* Clear STATUS */ writew(-1, rotary->base + CNT_STATUS_OFF); /* Clear STATUS */
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int bfin_rotary_open(struct input_dev *input)
{
struct bfin_rot *rotary = input_get_drvdata(input);
unsigned short val;
if (rotary->mode & ROT_DEBE)
writew(rotary->debounce & DPRESCALE,
rotary->base + CNT_DEBOUNCE_OFF);
writew(rotary->mode & ~CNTE, rotary->base + CNT_CONFIG_OFF);
val = UCIE | DCIE;
if (rotary->button_key)
val |= CZMIE;
writew(val, rotary->base + CNT_IMASK_OFF);
writew(rotary->mode | CNTE, rotary->base + CNT_CONFIG_OFF);
return 0;
}
static void bfin_rotary_close(struct input_dev *input)
{
struct bfin_rot *rotary = input_get_drvdata(input);
writew(0, rotary->base + CNT_CONFIG_OFF);
writew(0, rotary->base + CNT_IMASK_OFF);
}
static void bfin_rotary_free_action(void *data)
{
peripheral_free_list(data);
}
static int bfin_rotary_probe(struct platform_device *pdev) static int bfin_rotary_probe(struct platform_device *pdev)
{ {
struct bfin_rotary_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev;
const struct bfin_rotary_platform_data *pdata = dev_get_platdata(dev);
struct bfin_rot *rotary; struct bfin_rot *rotary;
struct resource *res;
struct input_dev *input; struct input_dev *input;
int error; int error;
...@@ -102,18 +145,37 @@ static int bfin_rotary_probe(struct platform_device *pdev) ...@@ -102,18 +145,37 @@ static int bfin_rotary_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
error = peripheral_request_list(per_cnt, dev_name(&pdev->dev)); if (pdata->pin_list) {
if (error) { error = peripheral_request_list(pdata->pin_list,
dev_err(&pdev->dev, "requesting peripherals failed\n"); dev_name(&pdev->dev));
return error; if (error) {
dev_err(dev, "requesting peripherals failed: %d\n",
error);
return error;
}
error = devm_add_action(dev, bfin_rotary_free_action,
pdata->pin_list);
if (error) {
dev_err(dev, "setting cleanup action failed: %d\n",
error);
peripheral_free_list(pdata->pin_list);
return error;
}
} }
rotary = kzalloc(sizeof(struct bfin_rot), GFP_KERNEL); rotary = devm_kzalloc(dev, sizeof(struct bfin_rot), GFP_KERNEL);
input = input_allocate_device(); if (!rotary)
if (!rotary || !input) { return -ENOMEM;
error = -ENOMEM;
goto out1; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
} rotary->base = devm_ioremap_resource(dev, res);
if (IS_ERR(rotary->base))
return PTR_ERR(rotary->base);
input = devm_input_allocate_device(dev);
if (!input)
return -ENOMEM;
rotary->input = input; rotary->input = input;
...@@ -122,9 +184,8 @@ static int bfin_rotary_probe(struct platform_device *pdev) ...@@ -122,9 +184,8 @@ static int bfin_rotary_probe(struct platform_device *pdev)
rotary->button_key = pdata->rotary_button_key; rotary->button_key = pdata->rotary_button_key;
rotary->rel_code = pdata->rotary_rel_code; rotary->rel_code = pdata->rotary_rel_code;
error = rotary->irq = platform_get_irq(pdev, 0); rotary->mode = pdata->mode;
if (error < 0) rotary->debounce = pdata->debounce;
goto out1;
input->name = pdev->name; input->name = pdev->name;
input->phys = "bfin-rotary/input0"; input->phys = "bfin-rotary/input0";
...@@ -137,6 +198,9 @@ static int bfin_rotary_probe(struct platform_device *pdev) ...@@ -137,6 +198,9 @@ static int bfin_rotary_probe(struct platform_device *pdev)
input->id.product = 0x0001; input->id.product = 0x0001;
input->id.version = 0x0100; input->id.version = 0x0100;
input->open = bfin_rotary_open;
input->close = bfin_rotary_close;
if (rotary->up_key) { if (rotary->up_key) {
__set_bit(EV_KEY, input->evbit); __set_bit(EV_KEY, input->evbit);
__set_bit(rotary->up_key, input->keybit); __set_bit(rotary->up_key, input->keybit);
...@@ -151,75 +215,43 @@ static int bfin_rotary_probe(struct platform_device *pdev) ...@@ -151,75 +215,43 @@ static int bfin_rotary_probe(struct platform_device *pdev)
__set_bit(rotary->button_key, input->keybit); __set_bit(rotary->button_key, input->keybit);
} }
error = request_irq(rotary->irq, bfin_rotary_isr, /* Quiesce the device before requesting irq */
0, dev_name(&pdev->dev), pdev); bfin_rotary_close(input);
rotary->irq = platform_get_irq(pdev, 0);
if (rotary->irq < 0) {
dev_err(dev, "No rotary IRQ specified\n");
return -ENOENT;
}
error = devm_request_irq(dev, rotary->irq, bfin_rotary_isr,
0, dev_name(dev), rotary);
if (error) { if (error) {
dev_err(&pdev->dev, dev_err(dev, "unable to claim irq %d; error %d\n",
"unable to claim irq %d; error %d\n",
rotary->irq, error); rotary->irq, error);
goto out1; return error;
} }
error = input_register_device(input); error = input_register_device(input);
if (error) { if (error) {
dev_err(&pdev->dev, dev_err(dev, "unable to register input device (%d)\n", error);
"unable to register input device (%d)\n", error); return error;
goto out2;
} }
if (pdata->rotary_button_key)
bfin_write_CNT_IMASK(CZMIE);
if (pdata->mode & ROT_DEBE)
bfin_write_CNT_DEBOUNCE(pdata->debounce & DPRESCALE);
if (pdata->mode)
bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() |
(pdata->mode & ~CNTE));
bfin_write_CNT_IMASK(bfin_read_CNT_IMASK() | UCIE | DCIE);
bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | CNTE);
platform_set_drvdata(pdev, rotary); platform_set_drvdata(pdev, rotary);
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
return 0; return 0;
out2:
free_irq(rotary->irq, pdev);
out1:
input_free_device(input);
kfree(rotary);
peripheral_free_list(per_cnt);
return error;
} }
static int bfin_rotary_remove(struct platform_device *pdev) static int __maybe_unused bfin_rotary_suspend(struct device *dev)
{
struct bfin_rot *rotary = platform_get_drvdata(pdev);
bfin_write_CNT_CONFIG(0);
bfin_write_CNT_IMASK(0);
free_irq(rotary->irq, pdev);
input_unregister_device(rotary->input);
peripheral_free_list(per_cnt);
kfree(rotary);
return 0;
}
#ifdef CONFIG_PM
static int bfin_rotary_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct bfin_rot *rotary = platform_get_drvdata(pdev); struct bfin_rot *rotary = platform_get_drvdata(pdev);
rotary->cnt_config = bfin_read_CNT_CONFIG(); rotary->cnt_config = readw(rotary->base + CNT_CONFIG_OFF);
rotary->cnt_imask = bfin_read_CNT_IMASK(); rotary->cnt_imask = readw(rotary->base + CNT_IMASK_OFF);
rotary->cnt_debounce = bfin_read_CNT_DEBOUNCE(); rotary->cnt_debounce = readw(rotary->base + CNT_DEBOUNCE_OFF);
if (device_may_wakeup(&pdev->dev)) if (device_may_wakeup(&pdev->dev))
enable_irq_wake(rotary->irq); enable_irq_wake(rotary->irq);
...@@ -227,38 +259,32 @@ static int bfin_rotary_suspend(struct device *dev) ...@@ -227,38 +259,32 @@ static int bfin_rotary_suspend(struct device *dev)
return 0; return 0;
} }
static int bfin_rotary_resume(struct device *dev) static int __maybe_unused bfin_rotary_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct bfin_rot *rotary = platform_get_drvdata(pdev); struct bfin_rot *rotary = platform_get_drvdata(pdev);
bfin_write_CNT_DEBOUNCE(rotary->cnt_debounce); writew(rotary->cnt_debounce, rotary->base + CNT_DEBOUNCE_OFF);
bfin_write_CNT_IMASK(rotary->cnt_imask); writew(rotary->cnt_imask, rotary->base + CNT_IMASK_OFF);
bfin_write_CNT_CONFIG(rotary->cnt_config & ~CNTE); writew(rotary->cnt_config & ~CNTE, rotary->base + CNT_CONFIG_OFF);
if (device_may_wakeup(&pdev->dev)) if (device_may_wakeup(&pdev->dev))
disable_irq_wake(rotary->irq); disable_irq_wake(rotary->irq);
if (rotary->cnt_config & CNTE) if (rotary->cnt_config & CNTE)
bfin_write_CNT_CONFIG(rotary->cnt_config); writew(rotary->cnt_config, rotary->base + CNT_CONFIG_OFF);
return 0; return 0;
} }
static const struct dev_pm_ops bfin_rotary_pm_ops = { static SIMPLE_DEV_PM_OPS(bfin_rotary_pm_ops,
.suspend = bfin_rotary_suspend, bfin_rotary_suspend, bfin_rotary_resume);
.resume = bfin_rotary_resume,
};
#endif
static struct platform_driver bfin_rotary_device_driver = { static struct platform_driver bfin_rotary_device_driver = {
.probe = bfin_rotary_probe, .probe = bfin_rotary_probe,
.remove = bfin_rotary_remove,
.driver = { .driver = {
.name = "bfin-rotary", .name = "bfin-rotary",
#ifdef CONFIG_PM
.pm = &bfin_rotary_pm_ops, .pm = &bfin_rotary_pm_ops,
#endif
}, },
}; };
module_platform_driver(bfin_rotary_device_driver); module_platform_driver(bfin_rotary_device_driver);
......
...@@ -195,7 +195,7 @@ static int soc_button_probe(struct platform_device *pdev) ...@@ -195,7 +195,7 @@ static int soc_button_probe(struct platform_device *pdev)
static struct soc_button_info soc_button_PNP0C40[] = { static struct soc_button_info soc_button_PNP0C40[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true }, { "power", 0, EV_KEY, KEY_POWER, false, true },
{ "home", 1, EV_KEY, KEY_HOME, false, true }, { "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false },
{ "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false }, { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false },
......
...@@ -99,36 +99,58 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = { ...@@ -99,36 +99,58 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */ 6-byte ALPS packet */
#define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */
#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = { static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ { { 0x32, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
{ { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ { { 0x33, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ { { 0x60, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ { { 0x63, 0x02, 0x28 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Fujitsu Siemens S6010 */
{ { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ { { 0x63, 0x02, 0x3c }, 0x00, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } }, /* Toshiba Satellite S2400-103 */
{ { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ { { 0x63, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x64 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ { { 0x63, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D800 */
{ { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ { { 0x73, 0x00, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, { { 0x73, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ { { 0x73, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Ahtec Laptop */
{ { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /*
{ { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ * XXX This entry is suspicious. First byte has zero lower nibble,
* which is what a normal mouse would report. Also, the value 0x0e
* isn't valid per PS/2 spec.
*/
{ { 0x20, 0x02, 0x0e }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
{ { 0x22, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
{ { 0x22, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D600 */
/* Dell Latitude E5500, E6400, E6500, Precision M4400 */ /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
{ { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, { { 0x62, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } },
{ { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT }, /* Dell XT2 */ { { 0x73, 0x00, 0x14 }, 0x00, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } }, /* Dell XT2 */
{ { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x73, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } }, /* Dell Vostro 1400 */
{ { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, { { 0x52, 0x01, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Toshiba Tecra A11-11L */
{ { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, { { 0x73, 0x02, 0x64 }, 0x8a, { ALPS_PROTO_V4, 0x8f, 0x8f, 0 } },
};
static const struct alps_protocol_info alps_v3_protocol_data = {
ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT
};
static const struct alps_protocol_info alps_v3_rushmore_data = {
ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT
};
static const struct alps_protocol_info alps_v5_protocol_data = {
ALPS_PROTO_V5, 0xc8, 0xd8, 0
};
static const struct alps_protocol_info alps_v7_protocol_data = {
ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT
}; };
static void alps_set_abs_params_st(struct alps_data *priv, static void alps_set_abs_params_st(struct alps_data *priv,
...@@ -136,12 +158,6 @@ static void alps_set_abs_params_st(struct alps_data *priv, ...@@ -136,12 +158,6 @@ static void alps_set_abs_params_st(struct alps_data *priv,
static void alps_set_abs_params_mt(struct alps_data *priv, static void alps_set_abs_params_mt(struct alps_data *priv,
struct input_dev *dev1); struct input_dev *dev1);
/*
* XXX - this entry is suspicious. First byte has zero lower nibble,
* which is what a normal mouse would report. Also, the value 0x0e
* isn't valid per PS/2 spec.
*/
/* Packet formats are described in Documentation/input/alps.txt */ /* Packet formats are described in Documentation/input/alps.txt */
static bool alps_is_valid_first_byte(struct alps_data *priv, static bool alps_is_valid_first_byte(struct alps_data *priv,
...@@ -150,8 +166,7 @@ static bool alps_is_valid_first_byte(struct alps_data *priv, ...@@ -150,8 +166,7 @@ static bool alps_is_valid_first_byte(struct alps_data *priv,
return (data & priv->mask0) == priv->byte0; return (data & priv->mask0) == priv->byte0;
} }
static void alps_report_buttons(struct psmouse *psmouse, static void alps_report_buttons(struct input_dev *dev1, struct input_dev *dev2,
struct input_dev *dev1, struct input_dev *dev2,
int left, int right, int middle) int left, int right, int middle)
{ {
struct input_dev *dev; struct input_dev *dev;
...@@ -161,20 +176,21 @@ static void alps_report_buttons(struct psmouse *psmouse, ...@@ -161,20 +176,21 @@ static void alps_report_buttons(struct psmouse *psmouse,
* other device (dev2) then this event should be also * other device (dev2) then this event should be also
* sent through that device. * sent through that device.
*/ */
dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; dev = (dev2 && test_bit(BTN_LEFT, dev2->key)) ? dev2 : dev1;
input_report_key(dev, BTN_LEFT, left); input_report_key(dev, BTN_LEFT, left);
dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; dev = (dev2 && test_bit(BTN_RIGHT, dev2->key)) ? dev2 : dev1;
input_report_key(dev, BTN_RIGHT, right); input_report_key(dev, BTN_RIGHT, right);
dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; dev = (dev2 && test_bit(BTN_MIDDLE, dev2->key)) ? dev2 : dev1;
input_report_key(dev, BTN_MIDDLE, middle); input_report_key(dev, BTN_MIDDLE, middle);
/* /*
* Sync the _other_ device now, we'll do the first * Sync the _other_ device now, we'll do the first
* device later once we report the rest of the events. * device later once we report the rest of the events.
*/ */
input_sync(dev2); if (dev2)
input_sync(dev2);
} }
static void alps_process_packet_v1_v2(struct psmouse *psmouse) static void alps_process_packet_v1_v2(struct psmouse *psmouse)
...@@ -221,13 +237,13 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) ...@@ -221,13 +237,13 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
alps_report_buttons(psmouse, dev2, dev, left, right, middle); alps_report_buttons(dev2, dev, left, right, middle);
input_sync(dev2); input_sync(dev2);
return; return;
} }
alps_report_buttons(psmouse, dev, dev2, left, right, middle); alps_report_buttons(dev, dev2, left, right, middle);
/* Convert hardware tap to a reasonable Z value */ /* Convert hardware tap to a reasonable Z value */
if (ges && !fin) if (ges && !fin)
...@@ -412,7 +428,7 @@ static int alps_process_bitmap(struct alps_data *priv, ...@@ -412,7 +428,7 @@ static int alps_process_bitmap(struct alps_data *priv,
(2 * (priv->y_bits - 1)); (2 * (priv->y_bits - 1));
/* y-bitmap order is reversed, except on rushmore */ /* y-bitmap order is reversed, except on rushmore */
if (!(priv->flags & ALPS_IS_RUSHMORE)) { if (priv->proto_version != ALPS_PROTO_V3_RUSHMORE) {
fields->mt[0].y = priv->y_max - fields->mt[0].y; fields->mt[0].y = priv->y_max - fields->mt[0].y;
fields->mt[1].y = priv->y_max - fields->mt[1].y; fields->mt[1].y = priv->y_max - fields->mt[1].y;
} }
...@@ -648,7 +664,8 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) ...@@ -648,7 +664,8 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
*/ */
if (f->is_mp) { if (f->is_mp) {
fingers = f->fingers; fingers = f->fingers;
if (priv->proto_version == ALPS_PROTO_V3) { if (priv->proto_version == ALPS_PROTO_V3 ||
priv->proto_version == ALPS_PROTO_V3_RUSHMORE) {
if (alps_process_bitmap(priv, f) == 0) if (alps_process_bitmap(priv, f) == 0)
fingers = 0; /* Use st data */ fingers = 0; /* Use st data */
...@@ -892,34 +909,6 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, ...@@ -892,34 +909,6 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
unsigned char *pkt, unsigned char *pkt,
unsigned char pkt_id) unsigned char pkt_id)
{ {
/*
* packet-fmt b7 b6 b5 b4 b3 b2 b1 b0
* Byte0 TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0
* Byte0 NEW L 1 X1-5 1 1 Y0-2 Y0-1 Y0-0
* Byte1 Y0-10 Y0-9 Y0-8 Y0-7 Y0-6 Y0-5 Y0-4 Y0-3
* Byte2 X0-11 1 X0-10 X0-9 X0-8 X0-7 X0-6 X0-5
* Byte3 X1-11 1 X0-4 X0-3 1 X0-2 X0-1 X0-0
* Byte4 TWO X1-10 TWO X1-9 X1-8 X1-7 X1-6 X1-5 X1-4
* Byte4 MULTI X1-10 TWO X1-9 X1-8 X1-7 X1-6 Y1-5 1
* Byte4 NEW X1-10 TWO X1-9 X1-8 X1-7 X1-6 0 0
* Byte5 TWO & NEW Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 Y1-5 Y1-4
* Byte5 MULTI Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 F-1 F-0
* L: Left button
* R / M: Non-clickpads: Right / Middle button
* Clickpads: When > 2 fingers are down, and some fingers
* are in the button area, then the 2 coordinates reported
* are for fingers outside the button area and these report
* extra fingers being present in the right / left button
* area. Note these fingers are not added to the F field!
* so if a TWO packet is received and R = 1 then there are
* 3 fingers down, etc.
* TWO: 1: Two touches present, byte 0/4/5 are in TWO fmt
* 0: If byte 4 bit 0 is 1, then byte 0/4/5 are in MULTI fmt
* otherwise byte 0 bit 4 must be set and byte 0/4/5 are
* in NEW fmt
* F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ...
*/
mt[0].x = ((pkt[2] & 0x80) << 4); mt[0].x = ((pkt[2] & 0x80) << 4);
mt[0].x |= ((pkt[2] & 0x3F) << 5); mt[0].x |= ((pkt[2] & 0x3F) << 5);
mt[0].x |= ((pkt[3] & 0x30) >> 1); mt[0].x |= ((pkt[3] & 0x30) >> 1);
...@@ -1044,17 +1033,6 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse) ...@@ -1044,17 +1033,6 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
return; return;
} }
/*
* b7 b6 b5 b4 b3 b2 b1 b0
* Byte0 0 1 0 0 1 0 0 0
* Byte1 1 1 * * 1 M R L
* Byte2 X7 1 X5 X4 X3 X2 X1 X0
* Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0
* Byte4 Y7 0 Y5 Y4 Y3 1 1 0
* Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
* M / R / L: Middle / Right / Left button
*/
x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2); x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
y = (packet[3] & 0x07) | (packet[4] & 0xb8) | y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
((packet[3] & 0x20) << 1); ((packet[3] & 0x20) << 1);
...@@ -1107,23 +1085,89 @@ static void alps_process_packet_v7(struct psmouse *psmouse) ...@@ -1107,23 +1085,89 @@ static void alps_process_packet_v7(struct psmouse *psmouse)
alps_process_touchpad_packet_v7(psmouse); alps_process_touchpad_packet_v7(psmouse);
} }
static void alps_report_bare_ps2_packet(struct psmouse *psmouse, static DEFINE_MUTEX(alps_mutex);
static void alps_register_bare_ps2_mouse(struct work_struct *work)
{
struct alps_data *priv =
container_of(work, struct alps_data, dev3_register_work.work);
struct psmouse *psmouse = priv->psmouse;
struct input_dev *dev3;
int error = 0;
mutex_lock(&alps_mutex);
if (priv->dev3)
goto out;
dev3 = input_allocate_device();
if (!dev3) {
psmouse_err(psmouse, "failed to allocate secondary device\n");
error = -ENOMEM;
goto out;
}
snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s",
psmouse->ps2dev.serio->phys,
(priv->dev2 ? "input2" : "input1"));
dev3->phys = priv->phys3;
/*
* format of input device name is: "protocol vendor name"
* see function psmouse_switch_protocol() in psmouse-base.c
*/
dev3->name = "PS/2 ALPS Mouse";
dev3->id.bustype = BUS_I8042;
dev3->id.vendor = 0x0002;
dev3->id.product = PSMOUSE_PS2;
dev3->id.version = 0x0000;
dev3->dev.parent = &psmouse->ps2dev.serio->dev;
input_set_capability(dev3, EV_REL, REL_X);
input_set_capability(dev3, EV_REL, REL_Y);
input_set_capability(dev3, EV_KEY, BTN_LEFT);
input_set_capability(dev3, EV_KEY, BTN_RIGHT);
input_set_capability(dev3, EV_KEY, BTN_MIDDLE);
__set_bit(INPUT_PROP_POINTER, dev3->propbit);
error = input_register_device(dev3);
if (error) {
psmouse_err(psmouse,
"failed to register secondary device: %d\n",
error);
input_free_device(dev3);
goto out;
}
priv->dev3 = dev3;
out:
/*
* Save the error code so that we can detect that we
* already tried to create the device.
*/
if (error)
priv->dev3 = ERR_PTR(error);
mutex_unlock(&alps_mutex);
}
static void alps_report_bare_ps2_packet(struct input_dev *dev,
unsigned char packet[], unsigned char packet[],
bool report_buttons) bool report_buttons)
{ {
struct alps_data *priv = psmouse->private;
struct input_dev *dev2 = priv->dev2;
if (report_buttons) if (report_buttons)
alps_report_buttons(psmouse, dev2, psmouse->dev, alps_report_buttons(dev, NULL,
packet[0] & 1, packet[0] & 2, packet[0] & 4); packet[0] & 1, packet[0] & 2, packet[0] & 4);
input_report_rel(dev2, REL_X, input_report_rel(dev, REL_X,
packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
input_report_rel(dev2, REL_Y, input_report_rel(dev, REL_Y,
packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
input_sync(dev2); input_sync(dev);
} }
static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
...@@ -1188,8 +1232,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) ...@@ -1188,8 +1232,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
* de-synchronization. * de-synchronization.
*/ */
alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], alps_report_bare_ps2_packet(priv->dev2,
false); &psmouse->packet[3], false);
/* /*
* Continue with the standard ALPS protocol handling, * Continue with the standard ALPS protocol handling,
...@@ -1245,9 +1289,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) ...@@ -1245,9 +1289,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
* properly we only do this if the device is fully synchronized. * properly we only do this if the device is fully synchronized.
*/ */
if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
/* Register dev3 mouse if we received PS/2 packet first time */
if (unlikely(!priv->dev3))
psmouse_queue_work(psmouse,
&priv->dev3_register_work, 0);
if (psmouse->pktcnt == 3) { if (psmouse->pktcnt == 3) {
alps_report_bare_ps2_packet(psmouse, psmouse->packet, /* Once dev3 mouse device is registered report data */
true); if (likely(!IS_ERR_OR_NULL(priv->dev3)))
alps_report_bare_ps2_packet(priv->dev3,
psmouse->packet,
true);
return PSMOUSE_FULL_PACKET; return PSMOUSE_FULL_PACKET;
} }
return PSMOUSE_GOOD_DATA; return PSMOUSE_GOOD_DATA;
...@@ -1275,7 +1328,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) ...@@ -1275,7 +1328,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
psmouse->pktcnt - 1, psmouse->pktcnt - 1,
psmouse->packet[psmouse->pktcnt - 1]); psmouse->packet[psmouse->pktcnt - 1]);
if (priv->proto_version == ALPS_PROTO_V3 && if (priv->proto_version == ALPS_PROTO_V3_RUSHMORE &&
psmouse->pktcnt == psmouse->pktsize) { psmouse->pktcnt == psmouse->pktsize) {
/* /*
* Some Dell boxes, such as Latitude E6440 or E7440 * Some Dell boxes, such as Latitude E6440 or E7440
...@@ -1780,7 +1833,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) ...@@ -1780,7 +1833,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
* all. * all.
*/ */
if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
psmouse_warn(psmouse, "trackstick E7 report failed\n"); psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
ret = -ENODEV; ret = -ENODEV;
} else { } else {
psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
...@@ -1945,8 +1998,6 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) ...@@ -1945,8 +1998,6 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
ALPS_REG_BASE_RUSHMORE); ALPS_REG_BASE_RUSHMORE);
if (reg_val == -EIO) if (reg_val == -EIO)
goto error; goto error;
if (reg_val == -ENODEV)
priv->flags &= ~ALPS_DUALPOINT;
} }
if (alps_enter_command_mode(psmouse) || if (alps_enter_command_mode(psmouse) ||
...@@ -2162,11 +2213,18 @@ static int alps_hw_init_v7(struct psmouse *psmouse) ...@@ -2162,11 +2213,18 @@ static int alps_hw_init_v7(struct psmouse *psmouse)
return ret; return ret;
} }
static void alps_set_defaults(struct alps_data *priv) static int alps_set_protocol(struct psmouse *psmouse,
struct alps_data *priv,
const struct alps_protocol_info *protocol)
{ {
priv->byte0 = 0x8f; psmouse->private = priv;
priv->mask0 = 0x8f;
priv->flags = ALPS_DUALPOINT; setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
priv->proto_version = protocol->version;
priv->byte0 = protocol->byte0;
priv->mask0 = protocol->mask0;
priv->flags = protocol->flags;
priv->x_max = 2000; priv->x_max = 2000;
priv->y_max = 1400; priv->y_max = 1400;
...@@ -2182,6 +2240,7 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2182,6 +2240,7 @@ static void alps_set_defaults(struct alps_data *priv)
priv->x_max = 1023; priv->x_max = 1023;
priv->y_max = 767; priv->y_max = 767;
break; break;
case ALPS_PROTO_V3: case ALPS_PROTO_V3:
priv->hw_init = alps_hw_init_v3; priv->hw_init = alps_hw_init_v3;
priv->process_packet = alps_process_packet_v3; priv->process_packet = alps_process_packet_v3;
...@@ -2190,6 +2249,23 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2190,6 +2249,23 @@ static void alps_set_defaults(struct alps_data *priv)
priv->nibble_commands = alps_v3_nibble_commands; priv->nibble_commands = alps_v3_nibble_commands;
priv->addr_command = PSMOUSE_CMD_RESET_WRAP; priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
break; break;
case ALPS_PROTO_V3_RUSHMORE:
priv->hw_init = alps_hw_init_rushmore_v3;
priv->process_packet = alps_process_packet_v3;
priv->set_abs_params = alps_set_abs_params_mt;
priv->decode_fields = alps_decode_rushmore;
priv->nibble_commands = alps_v3_nibble_commands;
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
priv->x_bits = 16;
priv->y_bits = 12;
if (alps_probe_trackstick_v3(psmouse,
ALPS_REG_BASE_RUSHMORE) < 0)
priv->flags &= ~ALPS_DUALPOINT;
break;
case ALPS_PROTO_V4: case ALPS_PROTO_V4:
priv->hw_init = alps_hw_init_v4; priv->hw_init = alps_hw_init_v4;
priv->process_packet = alps_process_packet_v4; priv->process_packet = alps_process_packet_v4;
...@@ -2197,6 +2273,7 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2197,6 +2273,7 @@ static void alps_set_defaults(struct alps_data *priv)
priv->nibble_commands = alps_v4_nibble_commands; priv->nibble_commands = alps_v4_nibble_commands;
priv->addr_command = PSMOUSE_CMD_DISABLE; priv->addr_command = PSMOUSE_CMD_DISABLE;
break; break;
case ALPS_PROTO_V5: case ALPS_PROTO_V5:
priv->hw_init = alps_hw_init_dolphin_v1; priv->hw_init = alps_hw_init_dolphin_v1;
priv->process_packet = alps_process_touchpad_packet_v3_v5; priv->process_packet = alps_process_touchpad_packet_v3_v5;
...@@ -2204,14 +2281,12 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2204,14 +2281,12 @@ static void alps_set_defaults(struct alps_data *priv)
priv->set_abs_params = alps_set_abs_params_mt; priv->set_abs_params = alps_set_abs_params_mt;
priv->nibble_commands = alps_v3_nibble_commands; priv->nibble_commands = alps_v3_nibble_commands;
priv->addr_command = PSMOUSE_CMD_RESET_WRAP; priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
priv->byte0 = 0xc8;
priv->mask0 = 0xd8;
priv->flags = 0;
priv->x_max = 1360; priv->x_max = 1360;
priv->y_max = 660; priv->y_max = 660;
priv->x_bits = 23; priv->x_bits = 23;
priv->y_bits = 12; priv->y_bits = 12;
break; break;
case ALPS_PROTO_V6: case ALPS_PROTO_V6:
priv->hw_init = alps_hw_init_v6; priv->hw_init = alps_hw_init_v6;
priv->process_packet = alps_process_packet_v6; priv->process_packet = alps_process_packet_v6;
...@@ -2220,6 +2295,7 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2220,6 +2295,7 @@ static void alps_set_defaults(struct alps_data *priv)
priv->x_max = 2047; priv->x_max = 2047;
priv->y_max = 1535; priv->y_max = 1535;
break; break;
case ALPS_PROTO_V7: case ALPS_PROTO_V7:
priv->hw_init = alps_hw_init_v7; priv->hw_init = alps_hw_init_v7;
priv->process_packet = alps_process_packet_v7; priv->process_packet = alps_process_packet_v7;
...@@ -2227,19 +2303,21 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -2227,19 +2303,21 @@ static void alps_set_defaults(struct alps_data *priv)
priv->set_abs_params = alps_set_abs_params_mt; priv->set_abs_params = alps_set_abs_params_mt;
priv->nibble_commands = alps_v3_nibble_commands; priv->nibble_commands = alps_v3_nibble_commands;
priv->addr_command = PSMOUSE_CMD_RESET_WRAP; priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
priv->x_max = 0xfff;
priv->y_max = 0x7ff; if (alps_dolphin_get_device_area(psmouse, priv))
priv->byte0 = 0x48; return -EIO;
priv->mask0 = 0x48;
if (priv->fw_ver[1] != 0xba) if (priv->fw_ver[1] != 0xba)
priv->flags |= ALPS_BUTTONPAD; priv->flags |= ALPS_BUTTONPAD;
break; break;
} }
return 0;
} }
static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, static const struct alps_protocol_info *alps_match_table(unsigned char *e7,
unsigned char *e7, unsigned char *ec) unsigned char *ec)
{ {
const struct alps_model_info *model; const struct alps_model_info *model;
int i; int i;
...@@ -2251,23 +2329,18 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, ...@@ -2251,23 +2329,18 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv,
(!model->command_mode_resp || (!model->command_mode_resp ||
model->command_mode_resp == ec[2])) { model->command_mode_resp == ec[2])) {
priv->proto_version = model->proto_version; return &model->protocol_info;
alps_set_defaults(priv);
priv->flags = model->flags;
priv->byte0 = model->byte0;
priv->mask0 = model->mask0;
return 0;
} }
} }
return -EINVAL; return NULL;
} }
static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
{ {
const struct alps_protocol_info *protocol;
unsigned char e6[4], e7[4], ec[4]; unsigned char e6[4], e7[4], ec[4];
int error;
/* /*
* First try "E6 report". * First try "E6 report".
...@@ -2293,54 +2366,35 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ...@@ -2293,54 +2366,35 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
alps_exit_command_mode(psmouse)) alps_exit_command_mode(psmouse))
return -EIO; return -EIO;
/* Save the Firmware version */ protocol = alps_match_table(e7, ec);
memcpy(priv->fw_ver, ec, 3); if (!protocol) {
if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
if (alps_match_table(psmouse, priv, e7, ec) == 0) { ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
return 0; protocol = &alps_v5_protocol_data;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && } else if (ec[0] == 0x88 &&
ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
priv->proto_version = ALPS_PROTO_V5; protocol = &alps_v7_protocol_data;
alps_set_defaults(priv); } else if (ec[0] == 0x88 && ec[1] == 0x08) {
if (alps_dolphin_get_device_area(psmouse, priv)) protocol = &alps_v3_rushmore_data;
return -EIO; } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
else ec[2] >= 0x90 && ec[2] <= 0x9d) {
return 0; protocol = &alps_v3_protocol_data;
} else if (ec[0] == 0x88 && } else {
((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) { psmouse_dbg(psmouse,
priv->proto_version = ALPS_PROTO_V7; "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
alps_set_defaults(priv); return -EINVAL;
}
return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
priv->proto_version = ALPS_PROTO_V3;
alps_set_defaults(priv);
priv->hw_init = alps_hw_init_rushmore_v3;
priv->decode_fields = alps_decode_rushmore;
priv->x_bits = 16;
priv->y_bits = 12;
priv->flags |= ALPS_IS_RUSHMORE;
/* hack to make addr_command, nibble_command available */
psmouse->private = priv;
if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE))
priv->flags &= ~ALPS_DUALPOINT;
return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x07 &&
ec[2] >= 0x90 && ec[2] <= 0x9d) {
priv->proto_version = ALPS_PROTO_V3;
alps_set_defaults(priv);
return 0;
} }
psmouse_dbg(psmouse, if (priv) {
"Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); /* Save the Firmware version */
memcpy(priv->fw_ver, ec, 3);
error = alps_set_protocol(psmouse, priv, protocol);
if (error)
return error;
}
return -EINVAL; return 0;
} }
static int alps_reconnect(struct psmouse *psmouse) static int alps_reconnect(struct psmouse *psmouse)
...@@ -2361,7 +2415,10 @@ static void alps_disconnect(struct psmouse *psmouse) ...@@ -2361,7 +2415,10 @@ static void alps_disconnect(struct psmouse *psmouse)
psmouse_reset(psmouse); psmouse_reset(psmouse);
del_timer_sync(&priv->timer); del_timer_sync(&priv->timer);
input_unregister_device(priv->dev2); if (priv->dev2)
input_unregister_device(priv->dev2);
if (!IS_ERR_OR_NULL(priv->dev3))
input_unregister_device(priv->dev3);
kfree(priv); kfree(priv);
} }
...@@ -2394,25 +2451,12 @@ static void alps_set_abs_params_mt(struct alps_data *priv, ...@@ -2394,25 +2451,12 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
int alps_init(struct psmouse *psmouse) int alps_init(struct psmouse *psmouse)
{ {
struct alps_data *priv; struct alps_data *priv = psmouse->private;
struct input_dev *dev1 = psmouse->dev, *dev2; struct input_dev *dev1 = psmouse->dev;
int error;
priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
dev2 = input_allocate_device();
if (!priv || !dev2)
goto init_fail;
priv->dev2 = dev2;
setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
psmouse->private = priv;
psmouse_reset(psmouse);
if (alps_identify(psmouse, priv) < 0)
goto init_fail;
if (priv->hw_init(psmouse)) error = priv->hw_init(psmouse);
if (error)
goto init_fail; goto init_fail;
/* /*
...@@ -2462,36 +2506,57 @@ int alps_init(struct psmouse *psmouse) ...@@ -2462,36 +2506,57 @@ int alps_init(struct psmouse *psmouse)
} }
if (priv->flags & ALPS_DUALPOINT) { if (priv->flags & ALPS_DUALPOINT) {
struct input_dev *dev2;
dev2 = input_allocate_device();
if (!dev2) {
psmouse_err(psmouse,
"failed to allocate trackstick device\n");
error = -ENOMEM;
goto init_fail;
}
snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1",
psmouse->ps2dev.serio->phys);
dev2->phys = priv->phys2;
/* /*
* format of input device name is: "protocol vendor name" * format of input device name is: "protocol vendor name"
* see function psmouse_switch_protocol() in psmouse-base.c * see function psmouse_switch_protocol() in psmouse-base.c
*/ */
dev2->name = "AlpsPS/2 ALPS DualPoint Stick"; dev2->name = "AlpsPS/2 ALPS DualPoint Stick";
dev2->id.bustype = BUS_I8042;
dev2->id.vendor = 0x0002;
dev2->id.product = PSMOUSE_ALPS; dev2->id.product = PSMOUSE_ALPS;
dev2->id.version = priv->proto_version; dev2->id.version = priv->proto_version;
} else { dev2->dev.parent = &psmouse->ps2dev.serio->dev;
dev2->name = "PS/2 ALPS Mouse";
dev2->id.product = PSMOUSE_PS2;
dev2->id.version = 0x0000;
}
snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); input_set_capability(dev2, EV_REL, REL_X);
dev2->phys = priv->phys; input_set_capability(dev2, EV_REL, REL_Y);
dev2->id.bustype = BUS_I8042; input_set_capability(dev2, EV_KEY, BTN_LEFT);
dev2->id.vendor = 0x0002; input_set_capability(dev2, EV_KEY, BTN_RIGHT);
dev2->dev.parent = &psmouse->ps2dev.serio->dev; input_set_capability(dev2, EV_KEY, BTN_MIDDLE);
dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); __set_bit(INPUT_PROP_POINTER, dev2->propbit);
dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
dev2->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
__set_bit(INPUT_PROP_POINTER, dev2->propbit);
if (priv->flags & ALPS_DUALPOINT)
__set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
if (input_register_device(priv->dev2)) error = input_register_device(dev2);
goto init_fail; if (error) {
psmouse_err(psmouse,
"failed to register trackstick device: %d\n",
error);
input_free_device(dev2);
goto init_fail;
}
priv->dev2 = dev2;
}
priv->psmouse = psmouse;
INIT_DELAYED_WORK(&priv->dev3_register_work,
alps_register_bare_ps2_mouse);
psmouse->protocol_handler = alps_process_byte; psmouse->protocol_handler = alps_process_byte;
psmouse->poll = alps_poll; psmouse->poll = alps_poll;
...@@ -2509,25 +2574,56 @@ int alps_init(struct psmouse *psmouse) ...@@ -2509,25 +2574,56 @@ int alps_init(struct psmouse *psmouse)
init_fail: init_fail:
psmouse_reset(psmouse); psmouse_reset(psmouse);
input_free_device(dev2); /*
kfree(priv); * Even though we did not allocate psmouse->private we do free
* it here.
*/
kfree(psmouse->private);
psmouse->private = NULL; psmouse->private = NULL;
return -1; return error;
} }
int alps_detect(struct psmouse *psmouse, bool set_properties) int alps_detect(struct psmouse *psmouse, bool set_properties)
{ {
struct alps_data dummy; struct alps_data *priv;
int error;
if (alps_identify(psmouse, &dummy) < 0) error = alps_identify(psmouse, NULL);
return -1; if (error)
return error;
/*
* Reset the device to make sure it is fully operational:
* on some laptops, like certain Dell Latitudes, we may
* fail to properly detect presence of trackstick if device
* has not been reset.
*/
psmouse_reset(psmouse);
priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
if (!priv)
return -ENOMEM;
error = alps_identify(psmouse, priv);
if (error)
return error;
if (set_properties) { if (set_properties) {
psmouse->vendor = "ALPS"; psmouse->vendor = "ALPS";
psmouse->name = dummy.flags & ALPS_DUALPOINT ? psmouse->name = priv->flags & ALPS_DUALPOINT ?
"DualPoint TouchPad" : "GlidePoint"; "DualPoint TouchPad" : "GlidePoint";
psmouse->model = dummy.proto_version << 8; psmouse->model = priv->proto_version;
} else {
/*
* Destroy alps_data structure we allocated earlier since
* this was just a "trial run". Otherwise we'll keep it
* to be used by alps_init() which has to be called if
* we succeed and set_properties is true.
*/
kfree(priv);
psmouse->private = NULL;
} }
return 0; return 0;
} }
...@@ -14,13 +14,14 @@ ...@@ -14,13 +14,14 @@
#include <linux/input/mt.h> #include <linux/input/mt.h>
#define ALPS_PROTO_V1 1 #define ALPS_PROTO_V1 0x100
#define ALPS_PROTO_V2 2 #define ALPS_PROTO_V2 0x200
#define ALPS_PROTO_V3 3 #define ALPS_PROTO_V3 0x300
#define ALPS_PROTO_V4 4 #define ALPS_PROTO_V3_RUSHMORE 0x310
#define ALPS_PROTO_V5 5 #define ALPS_PROTO_V4 0x400
#define ALPS_PROTO_V6 6 #define ALPS_PROTO_V5 0x500
#define ALPS_PROTO_V7 7 /* t3btl t4s */ #define ALPS_PROTO_V6 0x600
#define ALPS_PROTO_V7 0x700 /* t3btl t4s */
#define MAX_TOUCHES 2 #define MAX_TOUCHES 2
...@@ -45,6 +46,21 @@ enum V7_PACKET_ID { ...@@ -45,6 +46,21 @@ enum V7_PACKET_ID {
V7_PACKET_ID_UNKNOWN, V7_PACKET_ID_UNKNOWN,
}; };
/**
* struct alps_protocol_info - information about protocol used by a device
* @version: Indicates V1/V2/V3/...
* @byte0: Helps figure out whether a position report packet matches the
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
*/
struct alps_protocol_info {
u16 version;
u8 byte0, mask0;
unsigned int flags;
};
/** /**
* struct alps_model_info - touchpad ID table * struct alps_model_info - touchpad ID table
* @signature: E7 response string to match. * @signature: E7 response string to match.
...@@ -52,23 +68,16 @@ enum V7_PACKET_ID { ...@@ -52,23 +68,16 @@ enum V7_PACKET_ID {
* (aka command mode response) identifies the firmware minor version. This * (aka command mode response) identifies the firmware minor version. This
* can be used to distinguish different hardware models which are not * can be used to distinguish different hardware models which are not
* uniquely identifiable through their E7 responses. * uniquely identifiable through their E7 responses.
* @proto_version: Indicates V1/V2/V3/... * @protocol_info: information about protcol used by the device.
* @byte0: Helps figure out whether a position report packet matches the
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
* *
* Many (but not all) ALPS touchpads can be identified by looking at the * Many (but not all) ALPS touchpads can be identified by looking at the
* values returned in the "E7 report" and/or the "EC report." This table * values returned in the "E7 report" and/or the "EC report." This table
* lists a number of such touchpads. * lists a number of such touchpads.
*/ */
struct alps_model_info { struct alps_model_info {
unsigned char signature[3]; u8 signature[3];
unsigned char command_mode_resp; u8 command_mode_resp;
unsigned char proto_version; struct alps_protocol_info protocol_info;
unsigned char byte0, mask0;
int flags;
}; };
/** /**
...@@ -132,8 +141,12 @@ struct alps_fields { ...@@ -132,8 +141,12 @@ struct alps_fields {
/** /**
* struct alps_data - private data structure for the ALPS driver * struct alps_data - private data structure for the ALPS driver
* @dev2: "Relative" device used to report trackstick or mouse activity. * @psmouse: Pointer to parent psmouse device
* @phys: Physical path for the relative device. * @dev2: Trackstick device (can be NULL).
* @dev3: Generic PS/2 mouse (can be NULL, delayed registering).
* @phys2: Physical path for the trackstick device.
* @phys3: Physical path for the generic PS/2 mouse.
* @dev3_register_work: Delayed work for registering PS/2 mouse.
* @nibble_commands: Command mapping used for touchpad register accesses. * @nibble_commands: Command mapping used for touchpad register accesses.
* @addr_command: Command used to tell the touchpad that a register address * @addr_command: Command used to tell the touchpad that a register address
* follows. * follows.
...@@ -160,15 +173,19 @@ struct alps_fields { ...@@ -160,15 +173,19 @@ struct alps_fields {
* @timer: Timer for flushing out the final report packet in the stream. * @timer: Timer for flushing out the final report packet in the stream.
*/ */
struct alps_data { struct alps_data {
struct psmouse *psmouse;
struct input_dev *dev2; struct input_dev *dev2;
char phys[32]; struct input_dev *dev3;
char phys2[32];
char phys3[32];
struct delayed_work dev3_register_work;
/* these are autodetected when the device is identified */ /* these are autodetected when the device is identified */
const struct alps_nibble_commands *nibble_commands; const struct alps_nibble_commands *nibble_commands;
int addr_command; int addr_command;
unsigned char proto_version; u16 proto_version;
unsigned char byte0, mask0; u8 byte0, mask0;
unsigned char fw_ver[3]; u8 fw_ver[3];
int flags; int flags;
int x_max; int x_max;
int y_max; int y_max;
......
...@@ -710,8 +710,3 @@ int cypress_init(struct psmouse *psmouse) ...@@ -710,8 +710,3 @@ int cypress_init(struct psmouse *psmouse)
return -1; return -1;
} }
bool cypress_supported(void)
{
return true;
}
...@@ -172,7 +172,6 @@ struct cytp_data { ...@@ -172,7 +172,6 @@ struct cytp_data {
#ifdef CONFIG_MOUSE_PS2_CYPRESS #ifdef CONFIG_MOUSE_PS2_CYPRESS
int cypress_detect(struct psmouse *psmouse, bool set_properties); int cypress_detect(struct psmouse *psmouse, bool set_properties);
int cypress_init(struct psmouse *psmouse); int cypress_init(struct psmouse *psmouse);
bool cypress_supported(void);
#else #else
inline int cypress_detect(struct psmouse *psmouse, bool set_properties) inline int cypress_detect(struct psmouse *psmouse, bool set_properties)
{ {
...@@ -182,10 +181,6 @@ inline int cypress_init(struct psmouse *psmouse) ...@@ -182,10 +181,6 @@ inline int cypress_init(struct psmouse *psmouse)
{ {
return -ENOSYS; return -ENOSYS;
} }
inline bool cypress_supported(void)
{
return 0;
}
#endif /* CONFIG_MOUSE_PS2_CYPRESS */ #endif /* CONFIG_MOUSE_PS2_CYPRESS */
#endif /* _CYPRESS_PS2_H */ #endif /* _CYPRESS_PS2_H */
...@@ -424,11 +424,6 @@ int focaltech_init(struct psmouse *psmouse) ...@@ -424,11 +424,6 @@ int focaltech_init(struct psmouse *psmouse)
return error; return error;
} }
bool focaltech_supported(void)
{
return true;
}
#else /* CONFIG_MOUSE_PS2_FOCALTECH */ #else /* CONFIG_MOUSE_PS2_FOCALTECH */
int focaltech_init(struct psmouse *psmouse) int focaltech_init(struct psmouse *psmouse)
...@@ -438,9 +433,4 @@ int focaltech_init(struct psmouse *psmouse) ...@@ -438,9 +433,4 @@ int focaltech_init(struct psmouse *psmouse)
return 0; return 0;
} }
bool focaltech_supported(void)
{
return false;
}
#endif /* CONFIG_MOUSE_PS2_FOCALTECH */ #endif /* CONFIG_MOUSE_PS2_FOCALTECH */
...@@ -19,6 +19,5 @@ ...@@ -19,6 +19,5 @@
int focaltech_detect(struct psmouse *psmouse, bool set_properties); int focaltech_detect(struct psmouse *psmouse, bool set_properties);
int focaltech_init(struct psmouse *psmouse); int focaltech_init(struct psmouse *psmouse);
bool focaltech_supported(void);
#endif #endif
...@@ -727,7 +727,7 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -727,7 +727,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) { if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) {
if (max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
if (!set_properties || focaltech_init(psmouse) == 0) { if (!set_properties || focaltech_init(psmouse) == 0) {
if (focaltech_supported()) if (IS_ENABLED(CONFIG_MOUSE_PS2_FOCALTECH))
return PSMOUSE_FOCALTECH; return PSMOUSE_FOCALTECH;
/* /*
* Note that we need to also restrict * Note that we need to also restrict
...@@ -776,7 +776,7 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -776,7 +776,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
* Try activating protocol, but check if support is enabled first, since * Try activating protocol, but check if support is enabled first, since
* we try detecting Synaptics even when protocol is disabled. * we try detecting Synaptics even when protocol is disabled.
*/ */
if (synaptics_supported() && if (IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS) &&
(!set_properties || synaptics_init(psmouse) == 0)) { (!set_properties || synaptics_init(psmouse) == 0)) {
return PSMOUSE_SYNAPTICS; return PSMOUSE_SYNAPTICS;
} }
...@@ -801,7 +801,7 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -801,7 +801,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
*/ */
if (max_proto > PSMOUSE_IMEX && if (max_proto > PSMOUSE_IMEX &&
cypress_detect(psmouse, set_properties) == 0) { cypress_detect(psmouse, set_properties) == 0) {
if (cypress_supported()) { if (IS_ENABLED(CONFIG_MOUSE_PS2_CYPRESS)) {
if (cypress_init(psmouse) == 0) if (cypress_init(psmouse) == 0)
return PSMOUSE_CYPRESS; return PSMOUSE_CYPRESS;
......
...@@ -1454,11 +1454,6 @@ int synaptics_init_relative(struct psmouse *psmouse) ...@@ -1454,11 +1454,6 @@ int synaptics_init_relative(struct psmouse *psmouse)
return __synaptics_init(psmouse, false); return __synaptics_init(psmouse, false);
} }
bool synaptics_supported(void)
{
return true;
}
#else /* CONFIG_MOUSE_PS2_SYNAPTICS */ #else /* CONFIG_MOUSE_PS2_SYNAPTICS */
void __init synaptics_module_init(void) void __init synaptics_module_init(void)
...@@ -1470,9 +1465,4 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -1470,9 +1465,4 @@ int synaptics_init(struct psmouse *psmouse)
return -ENOSYS; return -ENOSYS;
} }
bool synaptics_supported(void)
{
return false;
}
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
...@@ -175,6 +175,5 @@ int synaptics_detect(struct psmouse *psmouse, bool set_properties); ...@@ -175,6 +175,5 @@ int synaptics_detect(struct psmouse *psmouse, bool set_properties);
int synaptics_init(struct psmouse *psmouse); int synaptics_init(struct psmouse *psmouse);
int synaptics_init_relative(struct psmouse *psmouse); int synaptics_init_relative(struct psmouse *psmouse);
void synaptics_reset(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse);
bool synaptics_supported(void);
#endif /* _SYNAPTICS_H */ #endif /* _SYNAPTICS_H */
...@@ -40,6 +40,7 @@ struct bfin_rotary_platform_data { ...@@ -40,6 +40,7 @@ struct bfin_rotary_platform_data {
unsigned short debounce; /* 0..17 */ unsigned short debounce; /* 0..17 */
unsigned short mode; unsigned short mode;
unsigned short pm_wakeup; unsigned short pm_wakeup;
unsigned short *pin_list;
}; };
/* CNT_CONFIG bitmasks */ /* CNT_CONFIG bitmasks */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment