From ced918eb748ce30b3aace549fd17540e40ffdca0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 17 Feb 2010 16:47:10 +0000 Subject: i8253: Convert i8253_lock to raw_spinlock i8253_lock needs to be a real spinlock in preempt-rt, i.e. it can not be converted to a sleeping lock. Convert it to raw_spinlock and fix up all users. Signed-off-by: Thomas Gleixner Acked-by: Ralf Baechle Acked-by: Dmitry Torokhov Acked-by: Takashi Iwai Cc: Jens Axboe LKML-Reference: <20100217163751.030764372@linutronix.de> --- drivers/input/gameport/gameport.c | 4 ++-- drivers/input/joystick/analog.c | 4 ++-- drivers/input/misc/pcspkr.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf05a6..46239e47a26 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -59,11 +59,11 @@ static unsigned int get_time_pit(void) unsigned long flags; unsigned int count; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); outb_p(0x00, 0x43); count = inb_p(0x40); count |= inb_p(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return count; } diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529c06a..4afe0a3b488 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -146,11 +146,11 @@ static unsigned int get_time_pit(void) unsigned long flags; unsigned int count; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); outb_p(0x00, 0x43); count = inb_p(0x40); count |= inb_p(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return count; } diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd1265..f080dd31499 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr"); #include #else #include -static DEFINE_SPINLOCK(i8253_lock); +static DEFINE_RAW_SPINLOCK(i8253_lock); #endif static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) @@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (count) { /* set command for counter 2, 2 byte write */ @@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c outb(inb_p(0x61) & 0xFC, 0x61); } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return 0; } -- cgit v1.2.2 From 38101475f937c5dc0baf43a9e0c7613dbeb94d5a Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 13 Apr 2010 23:07:52 -0700 Subject: Input: wacom - switch mode upon system resume When Wacom devices wake up from a sleep, the switch mode command (wacom_query_tablet_data) is needed before wacom_open is called. wacom_query_tablet_data should not be executed inside wacom_open since wacom_open is called more than once during probe. wacom_retrieve_hid_descriptor is removed from wacom_resume due to the fact that the required descriptors are stored properly upon system resume. Signed-off-by: Ping Cheng Reported-and-tested-by: Anton Anikin Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8b5d2873f0c..f46502589e4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -673,13 +673,15 @@ static int wacom_resume(struct usb_interface *intf) int rv; mutex_lock(&wacom->lock); - if (wacom->open) { + + /* switch to wacom mode first */ + wacom_query_tablet_data(intf, features); + + if (wacom->open) rv = usb_submit_urb(wacom->irq, GFP_NOIO); - /* switch to wacom mode if needed */ - if (!wacom_retrieve_hid_descriptor(intf, features)) - wacom_query_tablet_data(intf, features); - } else + else rv = 0; + mutex_unlock(&wacom->lock); return rv; -- cgit v1.2.2 From 3b57ca0f80c5c8994b5b1e3d3f904cfe727951f2 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Thu, 4 Mar 2010 21:50:59 -0800 Subject: Input: wacom - merge out and in prox events Process out and in prox events for Graphire and Tablet PC devices in the same loop to simplify the data parsing logic. [re-applying after revert since other patches are based on this one] Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 163 ++++++++++++++------------------------- 1 file changed, 59 insertions(+), 104 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4a852d815c6..b3ba3437a2e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -155,19 +155,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - int x, y, rw; - static int penData = 0; + int x, y, prox; + int rw = 0; + int retval = 0; if (data[0] != WACOM_REPORT_PENABLED) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - return 0; + goto exit; } - if (data[1] & 0x80) { - /* in prox and not a pad data */ - penData = 1; - - switch ((data[1] >> 5) & 3) { + prox = data[1] & 0x80; + if (prox || wacom->id[0]) { + if (prox) { + switch ((data[1] >> 5) & 3) { case 0: /* Pen */ wacom->tool[0] = BTN_TOOL_PEN; @@ -181,23 +181,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (features->type == WACOM_G4 || features->type == WACOM_MO) { - rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); - wacom_report_rel(wcombo, REL_WHEEL, -rw); - } else - wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); /* fall through */ case 3: /* Mouse without wheel */ wacom->tool[0] = BTN_TOOL_MOUSE; wacom->id[0] = CURSOR_DEVICE_ID; - wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); - wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (features->type == WACOM_G4 || features->type == WACOM_MO) - wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); - else - wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); break; + } } x = wacom_le16_to_cpu(&data[2]); y = wacom_le16_to_cpu(&data[4]); @@ -208,36 +198,32 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); - } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[0], 1); - } else if (wacom->id[0]) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - if (wacom->tool[0] == BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); + wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); + wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); + if (features->type == WACOM_G4 || + features->type == WACOM_MO) { + wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); + rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); + } else { + wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); + rw = -(signed)data[6]; + } + wacom_report_rel(wcombo, REL_WHEEL, rw); } - wacom->id[0] = 0; - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_report_key(wcombo, wacom->tool[0], 0); + + if (!prox) + wacom->id[0] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ + wacom_report_key(wcombo, wacom->tool[0], prox); + wacom_input_sync(wcombo); /* sync last event */ } /* send pad data */ switch (features->type) { case WACOM_G4: - if (data[7] & 0xf8) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = data[7] & 0xf8; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); @@ -245,29 +231,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_rel(wcombo, REL_WHEEL, rw); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); - wacom_report_rel(wcombo, REL_WHEEL, 0); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); + if (!prox) + wacom->id[1] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; case WACOM_MO: - if ((data[7] & 0xf8) || (data[8] & 0xff)) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = (data[7] & 0xf8) || data[8]; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); @@ -275,27 +248,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); + if (!prox) + wacom->id[1] = 0; wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); - wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); - wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; } - return 1; +exit: + return retval; } static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) @@ -636,9 +598,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) { wacom_report_abs(wcombo, ABS_X, - (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); + data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_Y, - (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); + data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); wacom_report_key(wcombo, wacom->tool[idx], 1); if (idx) @@ -782,31 +744,24 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) touchInProx = 0; - if (prox) { /* in prox */ - if (!wacom->id[0]) { - /* Going into proximity select tool */ - wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - if (wacom->tool[0] == BTN_TOOL_PEN) - wacom->id[0] = STYLUS_DEVICE_ID; - else - wacom->id[0] = ERASER_DEVICE_ID; - } - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); - } else { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); + if (!wacom->id[0]) { /* first in prox */ + /* Going into proximity select tool */ + wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom->tool[0] == BTN_TOOL_PEN) + wacom->id[0] = STYLUS_DEVICE_ID; + else + wacom->id[0] = ERASER_DEVICE_ID; + } + wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); + wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = features->pressure_max + pressure + 1; + wacom_report_abs(wcombo, ABS_PRESSURE, pressure); + wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); + if (!prox) { /* out-prox */ wacom->id[0] = 0; /* pen is out so touch can be enabled now */ touchInProx = 1; -- cgit v1.2.2 From 4492efffffeb88d87e7aa74765f3c53b3a7dd40f Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: wacom - share pen info with touch of the same ID Touch enbaled devices share the same product ID with pen. However, we do not want to post touch events while pen is in prox. To do so, we used to keep a local static variable to keep track of if pen is in prox or not. This works fine for Tablet PC devices since there is only one device attached. With the newer touch enabled regular tablets, we can not make this assumption any more, i.e, one system may have more than one identical tablet plugged in. This patch adds an new entry, shared, into the struct wacom_wac so touch data can access pen data to locally. This solution assumes the two tools (touch and pen) of the same ID will be probed one after the other without interruption in between by another Wacom device of the same ID. --- drivers/input/tablet/wacom_sys.c | 83 +++++++++++++++++++++++++++++++++++++++- drivers/input/tablet/wacom_wac.c | 33 ++++++---------- drivers/input/tablet/wacom_wac.h | 5 +++ 3 files changed, 99 insertions(+), 22 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f46502589e4..a03ca219d49 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -528,6 +528,81 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, return error; } +struct wacom_usbdev_data { + struct list_head list; + struct kref kref; + struct usb_device *dev; + struct wacom_shared shared; +}; + +static LIST_HEAD(wacom_udev_list); +static DEFINE_MUTEX(wacom_udev_list_lock); + +static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) +{ + struct wacom_usbdev_data *data; + + list_for_each_entry(data, &wacom_udev_list, list) { + if (data->dev == dev) { + kref_get(&data->kref); + return data; + } + } + + return NULL; +} + +static int wacom_add_shared_data(struct wacom_wac *wacom, + struct usb_device *dev) +{ + struct wacom_usbdev_data *data; + int retval = 0; + + mutex_lock(&wacom_udev_list_lock); + + data = wacom_get_usbdev_data(dev); + if (!data) { + data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL); + if (!data) { + retval = -ENOMEM; + goto out; + } + + kref_init(&data->kref); + data->dev = dev; + list_add_tail(&data->list, &wacom_udev_list); + } + + wacom->shared = &data->shared; + +out: + mutex_unlock(&wacom_udev_list_lock); + return retval; +} + +static void wacom_release_shared_data(struct kref *kref) +{ + struct wacom_usbdev_data *data = + container_of(kref, struct wacom_usbdev_data, kref); + + mutex_lock(&wacom_udev_list_lock); + list_del(&data->list); + mutex_unlock(&wacom_udev_list_lock); + + kfree(data); +} + +static void wacom_remove_shared_data(struct wacom_wac *wacom) +{ + struct wacom_usbdev_data *data; + + if (wacom->shared) { + data = container_of(wacom->shared, struct wacom_usbdev_data, shared); + kref_put(&data->kref, wacom_release_shared_data); + wacom->shared = NULL; + } +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -600,6 +675,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i features->device_type == BTN_TOOL_PEN ? " Pen" : " Finger", sizeof(wacom_wac->name)); + + error = wacom_add_shared_data(wacom_wac, dev); + if (error) + goto fail3; } input_dev->name = wacom_wac->name; @@ -624,7 +703,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i error = input_register_device(wacom->dev); if (error) - goto fail3; + goto fail4; /* Note that if query fails it is not a hard failure */ wacom_query_tablet_data(intf, features); @@ -632,6 +711,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_set_intfdata(intf, wacom); return 0; + fail4: wacom_remove_shared_data(wacom_wac); fail3: usb_free_urb(wacom->irq); fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: input_free_device(input_dev); @@ -651,6 +731,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, wacom->wacom_wac->data, wacom->data_dma); + wacom_remove_shared_data(wacom->wacom_wac); kfree(wacom->wacom_wac); kfree(wacom); } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b3ba3437a2e..428144af865 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -688,7 +688,6 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) struct wacom_features *features = &wacom->features; char *data = wacom->data; int prox = 0, pressure, idx = -1; - static int stylusInProx, touchInProx = 1, touchOut; struct urb *urb = ((struct wacom_combo *)wcombo)->urb; dbg("wacom_tpc_irq: received report #%d", data[0]); @@ -707,16 +706,12 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) prox = data[1] & 0x03; } - if (!stylusInProx) { /* stylus not in prox */ + if (!wacom->shared->stylus_in_proximity) { if (prox) { - if (touchInProx) { - wacom_tpc_touch_in(wacom, wcombo); - touchOut = 1; - return 1; - } + wacom_tpc_touch_in(wacom, wcombo); } else { - /* 2FGT out-prox */ if (data[0] == WACOM_REPORT_TPC2FG) { + /* 2FGT out-prox */ idx = (wacom->id[1] & 0x01) - 1; if (idx == 0) { wacom_tpc_touch_out(wacom, wcombo, idx); @@ -727,23 +722,19 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) idx = (wacom->id[1] & 0x02) - 1; if (idx == 1) wacom_tpc_touch_out(wacom, wcombo, idx); - } else /* one finger touch */ + } else { + /* one finger touch */ wacom_tpc_touch_out(wacom, wcombo, 0); - touchOut = 0; - touchInProx = 1; - return 1; + } + wacom->id[0] = 0; } - } else if (touchOut || !prox) { /* force touch out-prox */ + } else if (wacom->id[0]) { /* force touch out-prox */ wacom_tpc_touch_out(wacom, wcombo, 0); - touchOut = 0; - touchInProx = 1; - return 1; } + return 1; } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ prox = data[1] & 0x20; - touchInProx = 0; - if (!wacom->id[0]) { /* first in prox */ /* Going into proximity select tool */ wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; @@ -751,6 +742,8 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom->id[0] = STYLUS_DEVICE_ID; else wacom->id[0] = ERASER_DEVICE_ID; + + wacom->shared->stylus_in_proximity = true; } wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); @@ -763,12 +756,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); if (!prox) { /* out-prox */ wacom->id[0] = 0; - /* pen is out so touch can be enabled now */ - touchInProx = 1; + wacom->shared->stylus_in_proximity = false; } wacom_report_key(wcombo, wacom->tool[0], prox); wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - stylusInProx = prox; return 1; } return 0; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index b50cf04e61a..4b55fc7ad8a 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -71,6 +71,10 @@ struct wacom_features { unsigned char unitExpo; }; +struct wacom_shared { + bool stylus_in_proximity; +}; + struct wacom_wac { char name[64]; unsigned char *data; @@ -78,6 +82,7 @@ struct wacom_wac { int id[2]; __u32 serial[2]; struct wacom_features features; + struct wacom_shared *shared; }; #endif -- cgit v1.2.2 From 51269fe86c263ec4fafbafe82970e6d7f6f79102 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: wacom - do not allocate wacom_wac separately There is no reason for allocating struct wacom_wac separately from struct wacom since both have the same lifetime rules and are not shared. Also make 'open' field a boolean. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 4 ++-- drivers/input/tablet/wacom_sys.c | 21 +++++++++------------ drivers/input/tablet/wacom_wac.c | 3 ++- drivers/input/tablet/wacom_wac.h | 2 ++ 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 8fef1b689c6..fdb1d16b947 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -110,9 +110,9 @@ struct wacom { struct usb_device *usbdev; struct usb_interface *intf; struct urb *irq; - struct wacom_wac *wacom_wac; + struct wacom_wac wacom_wac; struct mutex lock; - unsigned int open:1; + bool open; char phys[32]; }; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a03ca219d49..0e5e56cef7f 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -11,8 +11,8 @@ * (at your option) any later version. */ -#include "wacom.h" #include "wacom_wac.h" +#include "wacom.h" /* defines to get HID report descriptor */ #define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) @@ -99,7 +99,7 @@ static void wacom_sys_irq(struct urb *urb) wcombo.wacom = wacom; wcombo.urb = urb; - if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) + if (wacom_wac_irq(&wacom->wacom_wac, (void *)&wcombo)) input_sync(get_input_dev(&wcombo)); exit: @@ -168,7 +168,7 @@ static int wacom_open(struct input_dev *dev) return -EIO; } - wacom->open = 1; + wacom->open = true; wacom->intf->needs_remote_wakeup = 1; mutex_unlock(&wacom->lock); @@ -181,7 +181,7 @@ static void wacom_close(struct input_dev *dev) mutex_lock(&wacom->lock); usb_kill_urb(wacom->irq); - wacom->open = 0; + wacom->open = false; wacom->intf->needs_remote_wakeup = 0; mutex_unlock(&wacom->lock); } @@ -617,13 +617,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i return -EINVAL; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); - wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); input_dev = input_allocate_device(); - if (!wacom || !input_dev || !wacom_wac) { + if (!wacom || !input_dev) { error = -ENOMEM; goto fail1; } + wacom_wac = &wacom->wacom_wac; wacom_wac->features = *((struct wacom_features *)id->driver_info); features = &wacom_wac->features; if (features->pktlen > WACOM_PKGLEN_MAX) { @@ -682,7 +682,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i } input_dev->name = wacom_wac->name; - wacom->wacom_wac = wacom_wac; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); @@ -716,7 +715,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: input_free_device(input_dev); kfree(wacom); - kfree(wacom_wac); return error; } @@ -730,9 +728,8 @@ static void wacom_disconnect(struct usb_interface *intf) input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, - wacom->wacom_wac->data, wacom->data_dma); - wacom_remove_shared_data(wacom->wacom_wac); - kfree(wacom->wacom_wac); + wacom->wacom_wac.data, wacom->data_dma); + wacom_remove_shared_data(&wacom->wacom_wac); kfree(wacom); } @@ -750,7 +747,7 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) static int wacom_resume(struct usb_interface *intf) { struct wacom *wacom = usb_get_intfdata(intf); - struct wacom_features *features = &wacom->wacom_wac->features; + struct wacom_features *features = &wacom->wacom_wac.features; int rv; mutex_lock(&wacom->lock); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 428144af865..2d7aee0bd28 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -11,8 +11,9 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ -#include "wacom.h" + #include "wacom_wac.h" +#include "wacom.h" static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) { diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 4b55fc7ad8a..f190a2bf148 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -9,6 +9,8 @@ #ifndef WACOM_WAC_H #define WACOM_WAC_H +#include + /* maximum packet length for USB devices */ #define WACOM_PKGLEN_MAX 32 -- cgit v1.2.2 From 73a97f4f6e53545b71f5c14ae2cb70a4b8d3cf63 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: wacom - fix some formatting issues Fix identation of switch/case statements so they follow style used by the rest of the kernel. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 4 +- drivers/input/tablet/wacom_wac.c | 419 ++++++++++++++++++++------------------- 2 files changed, 222 insertions(+), 201 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 0e5e56cef7f..ed339e5eca8 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -99,12 +99,12 @@ static void wacom_sys_irq(struct urb *urb) wcombo.wacom = wacom; wcombo.urb = urb; - if (wacom_wac_irq(&wacom->wacom_wac, (void *)&wcombo)) + if (wacom_wac_irq(&wacom->wacom_wac, &wcombo)) input_sync(get_input_dev(&wcombo)); exit: usb_mark_last_busy(wacom->usbdev); - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", __func__, retval); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 2d7aee0bd28..4da32d0159f 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -20,36 +20,36 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) unsigned char *data = wacom->data; switch (data[0]) { - case 1: - if (data[5] & 0x80) { - wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; - wacom_report_key(wcombo, wacom->tool[0], 1); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); - wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); - } else { - wacom_report_key(wcombo, wacom->tool[0], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ - wacom_report_abs(wcombo, ABS_PRESSURE, -1); - wacom_report_key(wcombo, BTN_TOUCH, 0); - } - break; - case 2: - wacom_report_key(wcombo, BTN_TOOL_PEN, 1); - wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ + case 1: + if (data[5] & 0x80) { + wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; + wacom_report_key(wcombo, wacom->tool[0], 1); + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); + wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); - break; - default: - printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); - return 0; + } else { + wacom_report_key(wcombo, wacom->tool[0], 0); + wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ + wacom_report_abs(wcombo, ABS_PRESSURE, -1); + wacom_report_key(wcombo, BTN_TOUCH, 0); + } + break; + case 2: + wacom_report_key(wcombo, BTN_TOOL_PEN, 1); + wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); + wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); + wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); + wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); + break; + default: + printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); + return 0; } return 1; } @@ -222,7 +222,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) /* send pad data */ switch (features->type) { - case WACOM_G4: + case WACOM_G4: prox = data[7] & 0xf8; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; @@ -239,7 +239,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } retval = 1; break; - case WACOM_MO: + + case WACOM_MO: prox = (data[7] & 0xf8) || data[8]; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; @@ -279,64 +280,73 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) (data[6] << 4) + (data[7] >> 4); wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); + switch (wacom->id[idx]) { - case 0x812: /* Inking pen */ - case 0x801: /* Intuos3 Inking pen */ - case 0x20802: /* Intuos4 Classic Pen */ - case 0x012: - wacom->tool[idx] = BTN_TOOL_PENCIL; - break; - case 0x822: /* Pen */ - case 0x842: - case 0x852: - case 0x823: /* Intuos3 Grip Pen */ - case 0x813: /* Intuos3 Classic Pen */ - case 0x885: /* Intuos3 Marker Pen */ - case 0x802: /* Intuos4 Grip Pen Eraser */ - case 0x804: /* Intuos4 Marker Pen */ - case 0x40802: /* Intuos4 Classic Pen */ - case 0x022: - wacom->tool[idx] = BTN_TOOL_PEN; - break; - case 0x832: /* Stroke pen */ - case 0x032: - wacom->tool[idx] = BTN_TOOL_BRUSH; - break; - case 0x007: /* Mouse 4D and 2D */ - case 0x09c: - case 0x094: - case 0x017: /* Intuos3 2D Mouse */ - case 0x806: /* Intuos4 Mouse */ - wacom->tool[idx] = BTN_TOOL_MOUSE; - break; - case 0x096: /* Lens cursor */ - case 0x097: /* Intuos3 Lens cursor */ - case 0x006: /* Intuos4 Lens cursor */ - wacom->tool[idx] = BTN_TOOL_LENS; - break; - case 0x82a: /* Eraser */ - case 0x85a: - case 0x91a: - case 0xd1a: - case 0x0fa: - case 0x82b: /* Intuos3 Grip Pen Eraser */ - case 0x81b: /* Intuos3 Classic Pen Eraser */ - case 0x91b: /* Intuos3 Airbrush Eraser */ - case 0x80c: /* Intuos4 Marker Pen Eraser */ - case 0x80a: /* Intuos4 Grip Pen Eraser */ - case 0x4080a: /* Intuos4 Classic Pen Eraser */ - case 0x90a: /* Intuos4 Airbrush Eraser */ - wacom->tool[idx] = BTN_TOOL_RUBBER; - break; - case 0xd12: - case 0x912: - case 0x112: - case 0x913: /* Intuos3 Airbrush */ - case 0x902: /* Intuos4 Airbrush */ - wacom->tool[idx] = BTN_TOOL_AIRBRUSH; - break; - default: /* Unknown tool */ - wacom->tool[idx] = BTN_TOOL_PEN; + case 0x812: /* Inking pen */ + case 0x801: /* Intuos3 Inking pen */ + case 0x20802: /* Intuos4 Classic Pen */ + case 0x012: + wacom->tool[idx] = BTN_TOOL_PENCIL; + break; + + case 0x822: /* Pen */ + case 0x842: + case 0x852: + case 0x823: /* Intuos3 Grip Pen */ + case 0x813: /* Intuos3 Classic Pen */ + case 0x885: /* Intuos3 Marker Pen */ + case 0x802: /* Intuos4 Grip Pen Eraser */ + case 0x804: /* Intuos4 Marker Pen */ + case 0x40802: /* Intuos4 Classic Pen */ + case 0x022: + wacom->tool[idx] = BTN_TOOL_PEN; + break; + + case 0x832: /* Stroke pen */ + case 0x032: + wacom->tool[idx] = BTN_TOOL_BRUSH; + break; + + case 0x007: /* Mouse 4D and 2D */ + case 0x09c: + case 0x094: + case 0x017: /* Intuos3 2D Mouse */ + case 0x806: /* Intuos4 Mouse */ + wacom->tool[idx] = BTN_TOOL_MOUSE; + break; + + case 0x096: /* Lens cursor */ + case 0x097: /* Intuos3 Lens cursor */ + case 0x006: /* Intuos4 Lens cursor */ + wacom->tool[idx] = BTN_TOOL_LENS; + break; + + case 0x82a: /* Eraser */ + case 0x85a: + case 0x91a: + case 0xd1a: + case 0x0fa: + case 0x82b: /* Intuos3 Grip Pen Eraser */ + case 0x81b: /* Intuos3 Classic Pen Eraser */ + case 0x91b: /* Intuos3 Airbrush Eraser */ + case 0x80c: /* Intuos4 Marker Pen Eraser */ + case 0x80a: /* Intuos4 Grip Pen Eraser */ + case 0x4080a: /* Intuos4 Classic Pen Eraser */ + case 0x90a: /* Intuos4 Airbrush Eraser */ + wacom->tool[idx] = BTN_TOOL_RUBBER; + break; + + case 0xd12: + case 0x912: + case 0x112: + case 0x913: /* Intuos3 Airbrush */ + case 0x902: /* Intuos4 Airbrush */ + wacom->tool[idx] = BTN_TOOL_AIRBRUSH; + break; + + default: /* Unknown tool */ + wacom->tool[idx] = BTN_TOOL_PEN; + break; } return 1; } @@ -406,7 +416,6 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) ((data[7] << 1) & 0x7e) | (data[8] >> 7)); wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); } - return; } static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) @@ -487,7 +496,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) /* process in/out prox events */ result = wacom_intuos_inout(wacom, wcombo); if (result) - return result-1; + return result - 1; /* don't proceed if we don't know the ID */ if (!wacom->id[idx]) @@ -635,44 +644,47 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) wacom->tool[1] = BTN_TOOL_TRIPLETAP; if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { + switch (data[0]) { - case WACOM_REPORT_TPC1FG: - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); - break; - case WACOM_REPORT_TPC2FG: - /* keep this byte to send proper out-prox event */ - wacom->id[1] = data[1] & 0x03; - - if (data[1] & 0x01) { - wacom_tpc_finger_in(wacom, wcombo, data, 0); - firstFinger = 1; - } else if (firstFinger) { - wacom_tpc_touch_out(wacom, wcombo, 0); - } - if (data[1] & 0x02) { - /* sync first finger data */ - if (firstFinger) - wacom_input_sync(wcombo); + case WACOM_REPORT_TPC1FG: + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); + wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + wacom_report_key(wcombo, wacom->tool[0], 1); + break; - wacom_tpc_finger_in(wacom, wcombo, data, 1); - secondFinger = 1; - } else if (secondFinger) { - /* sync first finger data */ - if (firstFinger) - wacom_input_sync(wcombo); + case WACOM_REPORT_TPC2FG: + /* keep this byte to send proper out-prox event */ + wacom->id[1] = data[1] & 0x03; - wacom_tpc_touch_out(wacom, wcombo, 1); - secondFinger = 0; - } - if (!(data[1] & 0x01)) - firstFinger = 0; - break; + if (data[1] & 0x01) { + wacom_tpc_finger_in(wacom, wcombo, data, 0); + firstFinger = 1; + } else if (firstFinger) { + wacom_tpc_touch_out(wacom, wcombo, 0); + } + + if (data[1] & 0x02) { + /* sync first finger data */ + if (firstFinger) + wacom_input_sync(wcombo); + + wacom_tpc_finger_in(wacom, wcombo, data, 1); + secondFinger = 1; + } else if (secondFinger) { + /* sync first finger data */ + if (firstFinger) + wacom_input_sync(wcombo); + + wacom_tpc_touch_out(wacom, wcombo, 1); + secondFinger = 0; + } + if (!(data[1] & 0x01)) + firstFinger = 0; + break; } } else { wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); @@ -681,7 +693,6 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); wacom_report_key(wcombo, wacom->tool[0], 1); } - return; } static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) @@ -769,37 +780,37 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) { switch (wacom_wac->features.type) { - case PENPARTNER: - return wacom_penpartner_irq(wacom_wac, wcombo); - - case PL: - return wacom_pl_irq(wacom_wac, wcombo); - - case WACOM_G4: - case GRAPHIRE: - case WACOM_MO: - return wacom_graphire_irq(wacom_wac, wcombo); - - case PTU: - return wacom_ptu_irq(wacom_wac, wcombo); - - case INTUOS: - case INTUOS3S: - case INTUOS3: - case INTUOS3L: - case INTUOS4S: - case INTUOS4: - case INTUOS4L: - case CINTIQ: - case WACOM_BEE: - return wacom_intuos_irq(wacom_wac, wcombo); - - case TABLETPC: - case TABLETPC2FG: - return wacom_tpc_irq(wacom_wac, wcombo); - - default: - return 0; + case PENPARTNER: + return wacom_penpartner_irq(wacom_wac, wcombo); + + case PL: + return wacom_pl_irq(wacom_wac, wcombo); + + case WACOM_G4: + case GRAPHIRE: + case WACOM_MO: + return wacom_graphire_irq(wacom_wac, wcombo); + + case PTU: + return wacom_ptu_irq(wacom_wac, wcombo); + + case INTUOS: + case INTUOS3S: + case INTUOS3: + case INTUOS3L: + case INTUOS4S: + case INTUOS4: + case INTUOS4L: + case CINTIQ: + case WACOM_BEE: + return wacom_intuos_irq(wacom_wac, wcombo); + + case TABLETPC: + case TABLETPC2FG: + return wacom_tpc_irq(wacom_wac, wcombo); + + default: + return 0; } return 0; } @@ -807,53 +818,63 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { switch (wacom_wac->features.type) { - case WACOM_MO: - input_dev_mo(input_dev, wacom_wac); - case WACOM_G4: - input_dev_g4(input_dev, wacom_wac); - /* fall through */ - case GRAPHIRE: - input_dev_g(input_dev, wacom_wac); - break; - case WACOM_BEE: - input_dev_bee(input_dev, wacom_wac); - case INTUOS3: - case INTUOS3L: - case CINTIQ: - input_dev_i3(input_dev, wacom_wac); - /* fall through */ - case INTUOS3S: - input_dev_i3s(input_dev, wacom_wac); - /* fall through */ - case INTUOS: - input_dev_i(input_dev, wacom_wac); - break; - case INTUOS4: - case INTUOS4L: - input_dev_i4(input_dev, wacom_wac); - /* fall through */ - case INTUOS4S: - input_dev_i4s(input_dev, wacom_wac); - input_dev_i(input_dev, wacom_wac); - break; - case TABLETPC2FG: - input_dev_tpc2fg(input_dev, wacom_wac); - /* fall through */ - case TABLETPC: - input_dev_tpc(input_dev, wacom_wac); - if (wacom_wac->features.device_type != BTN_TOOL_PEN) - break; /* no need to process stylus stuff */ - - /* fall through */ - case PL: - case PTU: - input_dev_pl(input_dev, wacom_wac); - /* fall through */ - case PENPARTNER: - input_dev_pt(input_dev, wacom_wac); - break; + case WACOM_MO: + input_dev_mo(input_dev, wacom_wac); + + case WACOM_G4: + input_dev_g4(input_dev, wacom_wac); + /* fall through */ + + case GRAPHIRE: + input_dev_g(input_dev, wacom_wac); + break; + + case WACOM_BEE: + input_dev_bee(input_dev, wacom_wac); + + case INTUOS3: + case INTUOS3L: + case CINTIQ: + input_dev_i3(input_dev, wacom_wac); + /* fall through */ + + case INTUOS3S: + input_dev_i3s(input_dev, wacom_wac); + /* fall through */ + + case INTUOS: + input_dev_i(input_dev, wacom_wac); + break; + + case INTUOS4: + case INTUOS4L: + input_dev_i4(input_dev, wacom_wac); + /* fall through */ + + case INTUOS4S: + input_dev_i4s(input_dev, wacom_wac); + input_dev_i(input_dev, wacom_wac); + break; + + case TABLETPC2FG: + input_dev_tpc2fg(input_dev, wacom_wac); + /* fall through */ + + case TABLETPC: + input_dev_tpc(input_dev, wacom_wac); + if (wacom_wac->features.device_type != BTN_TOOL_PEN) + break; /* no need to process stylus stuff */ + /* fall through */ + + case PL: + case PTU: + input_dev_pl(input_dev, wacom_wac); + /* fall through */ + + case PENPARTNER: + input_dev_pt(input_dev, wacom_wac); + break; } - return; } static const struct wacom_features wacom_features_0x00 = -- cgit v1.2.2 From 8da23fc113e8bdaf813545ec935a6c60254ac439 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: wacom - get rid of input event wrappers Input event interface is pretty stable so let's get rig of wrappers for input_event() and fiends and call them directly. This will simplify and speed up code a bit. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 28 +- drivers/input/tablet/wacom_sys.c | 174 +------------ drivers/input/tablet/wacom_wac.c | 549 +++++++++++++++++++++++---------------- drivers/input/tablet/wacom_wac.h | 1 + 4 files changed, 347 insertions(+), 405 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index fdb1d16b947..103a8cc2944 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -106,7 +106,6 @@ MODULE_LICENSE(DRIVER_LICENSE); struct wacom { dma_addr_t data_dma; - struct input_dev *dev; struct usb_device *usbdev; struct usb_interface *intf; struct urb *irq; @@ -123,27 +122,10 @@ struct wacom_combo { extern const struct usb_device_id wacom_ids[]; -extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); -extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); -extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); -extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); -extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); -extern void wacom_input_sync(void *wcombo); -extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern __u16 wacom_le16_to_cpu(unsigned char *data); -extern __u16 wacom_be16_to_cpu(unsigned char *data); +int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); +void wacom_setup_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac); +__u16 wacom_le16_to_cpu(unsigned char *data); +__u16 wacom_be16_to_cpu(unsigned char *data); #endif diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ed339e5eca8..58bb763b60d 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -72,7 +72,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, static struct input_dev * get_input_dev(struct wacom_combo *wcombo) { - return wcombo->wacom->dev; + return wcombo->wacom->wacom_wac.input; } static void wacom_sys_irq(struct urb *urb) @@ -110,26 +110,6 @@ static void wacom_sys_irq(struct urb *urb) __func__, retval); } -void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) -{ - input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); -} - -void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) -{ - input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); -} - -void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) -{ - input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); -} - -void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) -{ - input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); -} - __u16 wacom_be16_to_cpu(unsigned char *data) { __u16 value; @@ -144,11 +124,6 @@ __u16 wacom_le16_to_cpu(unsigned char *data) return value; } -void wacom_input_sync(void *wcombo) -{ - input_sync(get_input_dev((struct wacom_combo *)wcombo)); -} - static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); @@ -186,123 +161,6 @@ static void wacom_close(struct input_dev *dev) mutex_unlock(&wacom->lock); } -void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) | - BIT_MASK(BTN_5); - input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); -} - -void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->evbit[0] |= BIT_MASK(EV_MSC); - input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | - BIT_MASK(BTN_4); -} - -void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->evbit[0] |= BIT_MASK(EV_REL); - input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | - BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | - BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, - 0, wacom_wac->features.distance_max, 0, 0); -} - -void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | - BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); -} - -void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | - BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7); - input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); -} - -void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6); - input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); -} - -void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8); -} - -void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); -} - -void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL); - input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); - input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | - BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | - BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | - BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | - BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | - BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, - 0, wacom_wac->features.distance_max, 0, 0); - input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); - input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); - input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); - input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); - input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); -} - -void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | - BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); -} - -void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); -} - -void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - struct wacom_features *features = &wacom_wac->features; - - if (features->device_type == BTN_TOOL_DOUBLETAP || - features->device_type == BTN_TOOL_TRIPLETAP) { - input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - } -} - -void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); - input_dev->evbit[0] |= BIT_MASK(EV_MSC); - input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); - } -} - static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, struct wacom_features *features) { @@ -645,20 +503,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i } wacom->usbdev = dev; - wacom->dev = input_dev; wacom->intf = intf; mutex_init(&wacom->lock); usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - usb_to_input_id(dev, &input_dev->id); - - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, wacom); - - input_dev->open = wacom_open; - input_dev->close = wacom_close; + wacom_wac->input = input_dev; endpoint = &intf->cur_altsetting->endpoint[0].desc; @@ -682,16 +532,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i } input_dev->name = wacom_wac->name; + input_dev->name = wacom_wac->name; + input_dev->dev.parent = &intf->dev; + input_dev->open = wacom_open; + input_dev->close = wacom_close; + usb_to_input_id(dev, &input_dev->id); + input_set_drvdata(input_dev, wacom); - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); - input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); - input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); - - wacom_init_input_dev(input_dev, wacom_wac); + wacom_setup_input_capabilities(input_dev, wacom_wac); usb_fill_int_urb(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), @@ -700,7 +548,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = input_register_device(wacom->dev); + error = input_register_device(input_dev); if (error) goto fail4; @@ -725,7 +573,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); usb_kill_urb(wacom->irq); - input_unregister_device(wacom->dev); + input_unregister_device(wacom->wacom_wac.input); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, wacom->wacom_wac.data, wacom->data_dma); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4da32d0159f..9cf4854a981 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -18,39 +18,43 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) { unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; switch (data[0]) { case 1: if (data[5] & 0x80) { wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; - wacom_report_key(wcombo, wacom->tool[0], 1); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); - wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); + input_report_key(input, wacom->tool[0], 1); + input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); + input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127)); + input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); } else { - wacom_report_key(wcombo, wacom->tool[0], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ - wacom_report_abs(wcombo, ABS_PRESSURE, -1); - wacom_report_key(wcombo, BTN_TOUCH, 0); + input_report_key(input, wacom->tool[0], 0); + input_report_abs(input, ABS_MISC, 0); /* report tool id */ + input_report_abs(input, ABS_PRESSURE, -1); + input_report_key(input, BTN_TOUCH, 0); } break; + case 2: - wacom_report_key(wcombo, BTN_TOOL_PEN, 1); - wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); - wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); + input_report_key(input, BTN_TOOL_PEN, 1); + input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); + input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); + input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); break; + default: printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); return 0; } + return 1; } @@ -58,6 +62,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; int prox, pressure; if (data[0] != WACOM_REPORT_PENABLED) { @@ -91,8 +96,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) /* was entered with stylus2 pressed */ if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { /* report out proximity for previous tool */ - wacom_report_key(wcombo, wacom->tool[1], 0); - wacom_input_sync(wcombo); + input_report_key(input, wacom->tool[1], 0); + input_sync(input); wacom->tool[1] = BTN_TOOL_PEN; return 0; } @@ -102,23 +107,23 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) wacom->tool[1] = BTN_TOOL_PEN; wacom->id[0] = STYLUS_DEVICE_ID; } - wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); - wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - - wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); - wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); + input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */ + input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ + input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); + input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); + input_report_abs(input, ABS_PRESSURE, pressure); + + input_report_key(input, BTN_TOUCH, data[4] & 0x08); + input_report_key(input, BTN_STYLUS, data[4] & 0x10); /* Only allow the stylus2 button to be reported for the pen tool. */ - wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); + input_report_key(input, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); } else { /* report proximity-out of a (valid) tool */ if (wacom->tool[1] != BTN_TOOL_RUBBER) { /* Unknown tool selected default to pen tool */ wacom->tool[1] = BTN_TOOL_PEN; } - wacom_report_key(wcombo, wacom->tool[1], prox); + input_report_key(input, wacom->tool[1], prox); } wacom->tool[0] = prox; /* Save proximity state */ @@ -128,6 +133,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) { unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; if (data[0] != WACOM_REPORT_PENABLED) { printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); @@ -135,20 +141,20 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) } if (data[1] & 0x04) { - wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); + input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20); + input_report_key(input, BTN_TOUCH, data[1] & 0x08); wacom->id[0] = ERASER_DEVICE_ID; } else { - wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); + input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20); + input_report_key(input, BTN_TOUCH, data[1] & 0x01); wacom->id[0] = STYLUS_DEVICE_ID; } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); + input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); + input_report_abs(input, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, data[1] & 0x10); return 1; } @@ -156,6 +162,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; int x, y, prox; int rw = 0; int retval = 0; @@ -181,7 +188,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) break; case 2: /* Mouse with wheel */ - wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); + input_report_key(input, BTN_MIDDLE, data[1] & 0x04); /* fall through */ case 3: /* Mouse without wheel */ @@ -192,32 +199,32 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } x = wacom_le16_to_cpu(&data[2]); y = wacom_le16_to_cpu(&data[4]); - wacom_report_abs(wcombo, ABS_X, x); - wacom_report_abs(wcombo, ABS_Y, y); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); if (wacom->tool[0] != BTN_TOOL_MOUSE) { - wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); + input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); + input_report_key(input, BTN_TOUCH, data[1] & 0x01); + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, data[1] & 0x04); } else { - wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); - wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); + input_report_key(input, BTN_LEFT, data[1] & 0x01); + input_report_key(input, BTN_RIGHT, data[1] & 0x02); if (features->type == WACOM_G4 || features->type == WACOM_MO) { - wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); + input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f); rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); } else { - wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); + input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f); rw = -(signed)data[6]; } - wacom_report_rel(wcombo, REL_WHEEL, rw); + input_report_rel(input, REL_WHEEL, rw); } if (!prox) wacom->id[0] = 0; - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[0], prox); - wacom_input_sync(wcombo); /* sync last event */ + input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ + input_report_key(input, wacom->tool[0], prox); + input_sync(input); /* sync last event */ } /* send pad data */ @@ -226,16 +233,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) prox = data[7] & 0xf8; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); + input_report_key(input, BTN_0, (data[7] & 0x40)); + input_report_key(input, BTN_4, (data[7] & 0x80)); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); - wacom_report_rel(wcombo, REL_WHEEL, rw); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); + input_report_rel(input, REL_WHEEL, rw); + input_report_key(input, BTN_TOOL_FINGER, 0xf0); + input_report_abs(input, ABS_MISC, wacom->id[1]); if (!prox) wacom->id[1] = 0; - wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + input_report_abs(input, ABS_MISC, wacom->id[1]); + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); } retval = 1; break; @@ -244,16 +251,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) prox = (data[7] & 0xf8) || data[8]; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); - wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); - wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); + input_report_key(input, BTN_0, (data[7] & 0x08)); + input_report_key(input, BTN_1, (data[7] & 0x20)); + input_report_key(input, BTN_4, (data[7] & 0x10)); + input_report_key(input, BTN_5, (data[7] & 0x40)); + input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); + input_report_key(input, BTN_TOOL_FINGER, 0xf0); if (!prox) wacom->id[1] = 0; - wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + input_report_abs(input, ABS_MISC, wacom->id[1]); + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); } retval = 1; break; @@ -266,6 +273,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; int idx = 0; /* tool number */ @@ -357,31 +365,31 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) * Reset all states otherwise we lose the initial states * when in-prox next time */ - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); - wacom_report_abs(wcombo, ABS_TILT_X, 0); - wacom_report_abs(wcombo, ABS_TILT_Y, 0); + input_report_abs(input, ABS_X, 0); + input_report_abs(input, ABS_Y, 0); + input_report_abs(input, ABS_DISTANCE, 0); + input_report_abs(input, ABS_TILT_X, 0); + input_report_abs(input, ABS_TILT_Y, 0); if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_MIDDLE, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_key(wcombo, BTN_SIDE, 0); - wacom_report_key(wcombo, BTN_EXTRA, 0); - wacom_report_abs(wcombo, ABS_THROTTLE, 0); - wacom_report_abs(wcombo, ABS_RZ, 0); + input_report_key(input, BTN_LEFT, 0); + input_report_key(input, BTN_MIDDLE, 0); + input_report_key(input, BTN_RIGHT, 0); + input_report_key(input, BTN_SIDE, 0); + input_report_key(input, BTN_EXTRA, 0); + input_report_abs(input, ABS_THROTTLE, 0); + input_report_abs(input, ABS_RZ, 0); } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_abs(wcombo, ABS_WHEEL, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_report_key(input, BTN_STYLUS, 0); + input_report_key(input, BTN_STYLUS2, 0); + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_WHEEL, 0); if (features->type >= INTUOS3S) - wacom_report_abs(wcombo, ABS_Z, 0); + input_report_abs(input, ABS_Z, 0); } - wacom_report_key(wcombo, wacom->tool[idx], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); + input_report_key(input, wacom->tool[idx], 0); + input_report_abs(input, ABS_MISC, 0); /* reset tool id */ + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); wacom->id[idx] = 0; return 2; } @@ -392,6 +400,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; unsigned int t; /* general pen packet */ @@ -399,22 +408,22 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) t = (data[6] << 2) | ((data[7] >> 6) & 3); if (features->type >= INTUOS4S && features->type <= INTUOS4L) t = (t << 1) | (data[1] & 1); - wacom_report_abs(wcombo, ABS_PRESSURE, t); - wacom_report_abs(wcombo, ABS_TILT_X, + input_report_abs(input, ABS_PRESSURE, t); + input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); - wacom_report_key(wcombo, BTN_TOUCH, t > 10); + input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); + input_report_key(input, BTN_STYLUS, data[1] & 2); + input_report_key(input, BTN_STYLUS2, data[1] & 4); + input_report_key(input, BTN_TOUCH, t > 10); } /* airbrush second packet */ if ((data[1] & 0xbc) == 0xb4) { - wacom_report_abs(wcombo, ABS_WHEEL, + input_report_abs(input, ABS_WHEEL, (data[6] << 2) | ((data[7] >> 6) & 3)); - wacom_report_abs(wcombo, ABS_TILT_X, + input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); + input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); } } @@ -422,6 +431,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; unsigned int t; int idx = 0, result; @@ -442,54 +452,54 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) wacom->tool[1] = BTN_TOOL_FINGER; if (features->type >= INTUOS4S && features->type <= INTUOS4L) { - wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); - wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); - wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); - wacom_report_key(wcombo, BTN_3, (data[3] & 0x04)); - wacom_report_key(wcombo, BTN_4, (data[3] & 0x08)); - wacom_report_key(wcombo, BTN_5, (data[3] & 0x10)); - wacom_report_key(wcombo, BTN_6, (data[3] & 0x20)); + input_report_key(input, BTN_0, (data[2] & 0x01)); + input_report_key(input, BTN_1, (data[3] & 0x01)); + input_report_key(input, BTN_2, (data[3] & 0x02)); + input_report_key(input, BTN_3, (data[3] & 0x04)); + input_report_key(input, BTN_4, (data[3] & 0x08)); + input_report_key(input, BTN_5, (data[3] & 0x10)); + input_report_key(input, BTN_6, (data[3] & 0x20)); if (data[1] & 0x80) { - wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f)); + input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f)); } else { /* Out of proximity, clear wheel value. */ - wacom_report_abs(wcombo, ABS_WHEEL, 0); + input_report_abs(input, ABS_WHEEL, 0); } if (features->type != INTUOS4S) { - wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); - wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); + input_report_key(input, BTN_7, (data[3] & 0x40)); + input_report_key(input, BTN_8, (data[3] & 0x80)); } if (data[1] | (data[2] & 0x01) | data[3]) { - wacom_report_key(wcombo, wacom->tool[1], 1); - wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); + input_report_key(input, wacom->tool[1], 1); + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); } else { - wacom_report_key(wcombo, wacom->tool[1], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); + input_report_key(input, wacom->tool[1], 0); + input_report_abs(input, ABS_MISC, 0); } } else { - wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); - wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); - wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); - wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); - wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); - wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); - wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); - wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); - wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); - wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); - wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); - wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); + input_report_key(input, BTN_0, (data[5] & 0x01)); + input_report_key(input, BTN_1, (data[5] & 0x02)); + input_report_key(input, BTN_2, (data[5] & 0x04)); + input_report_key(input, BTN_3, (data[5] & 0x08)); + input_report_key(input, BTN_4, (data[6] & 0x01)); + input_report_key(input, BTN_5, (data[6] & 0x02)); + input_report_key(input, BTN_6, (data[6] & 0x04)); + input_report_key(input, BTN_7, (data[6] & 0x08)); + input_report_key(input, BTN_8, (data[5] & 0x10)); + input_report_key(input, BTN_9, (data[6] & 0x10)); + input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); + input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | data[2] | (data[3] & 0x1f) | data[4]) { - wacom_report_key(wcombo, wacom->tool[1], 1); - wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); + input_report_key(input, wacom->tool[1], 1); + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); } else { - wacom_report_key(wcombo, wacom->tool[1], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); + input_report_key(input, wacom->tool[1], 0); + input_report_abs(input, ABS_MISC, 0); } } - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); + input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); return 1; } @@ -517,13 +527,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) return 0; if (features->type >= INTUOS3S) { - wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); - wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); - wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); + input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); + input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); + input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); } else { - wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); + input_report_abs(input, ABS_X, wacom_be16_to_cpu(&data[2])); + input_report_abs(input, ABS_Y, wacom_be16_to_cpu(&data[4])); + input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); } /* process general packets */ @@ -539,102 +549,106 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) t = (data[6] << 3) | ((data[7] >> 5) & 7); t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : ((t-1) / 2 + 450)) : (450 - t / 2) ; - wacom_report_abs(wcombo, ABS_Z, t); + input_report_abs(input, ABS_Z, t); } else { /* 4D mouse rotation packet */ t = (data[6] << 3) | ((data[7] >> 5) & 7); - wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? + input_report_abs(input, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); } } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { /* 4D mouse packet */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); + input_report_key(input, BTN_LEFT, data[8] & 0x01); + input_report_key(input, BTN_MIDDLE, data[8] & 0x02); + input_report_key(input, BTN_RIGHT, data[8] & 0x04); - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x20); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x10); + input_report_key(input, BTN_SIDE, data[8] & 0x20); + input_report_key(input, BTN_EXTRA, data[8] & 0x10); t = (data[6] << 2) | ((data[7] >> 6) & 3); - wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); + input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ if (features->type >= INTUOS4S && features->type <= INTUOS4L) { - wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); - wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); - wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); - wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7) + input_report_key(input, BTN_LEFT, data[6] & 0x01); + input_report_key(input, BTN_MIDDLE, data[6] & 0x02); + input_report_key(input, BTN_RIGHT, data[6] & 0x04); + input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7) - ((data[7] & 0x40) >> 6)); - wacom_report_key(wcombo, BTN_SIDE, data[6] & 0x08); - wacom_report_key(wcombo, BTN_EXTRA, data[6] & 0x10); + input_report_key(input, BTN_SIDE, data[6] & 0x08); + input_report_key(input, BTN_EXTRA, data[6] & 0x10); - wacom_report_abs(wcombo, ABS_TILT_X, + input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); + input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); } else { /* 2D mouse packet */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); - wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) + input_report_key(input, BTN_LEFT, data[8] & 0x04); + input_report_key(input, BTN_MIDDLE, data[8] & 0x08); + input_report_key(input, BTN_RIGHT, data[8] & 0x10); + input_report_rel(input, REL_WHEEL, (data[8] & 0x01) - ((data[8] & 0x02) >> 1)); /* I3 2D mouse side buttons */ if (features->type >= INTUOS3S && features->type <= INTUOS3L) { - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); + input_report_key(input, BTN_SIDE, data[8] & 0x40); + input_report_key(input, BTN_EXTRA, data[8] & 0x20); } } } else if ((features->type < INTUOS3S || features->type == INTUOS3L || features->type == INTUOS4L) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x10); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x08); + input_report_key(input, BTN_LEFT, data[8] & 0x01); + input_report_key(input, BTN_MIDDLE, data[8] & 0x02); + input_report_key(input, BTN_RIGHT, data[8] & 0x04); + input_report_key(input, BTN_SIDE, data[8] & 0x10); + input_report_key(input, BTN_EXTRA, data[8] & 0x08); } } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[idx], 1); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); + input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */ + input_report_key(input, wacom->tool[idx], 1); + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); return 1; } static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) { - wacom_report_abs(wcombo, ABS_X, + struct input_dev *input = wacom->input; + + input_report_abs(input, ABS_X, data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_Y, + input_report_abs(input, ABS_Y, data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[idx], 1); + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_report_key(input, wacom->tool[idx], 1); if (idx) - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); else - wacom_report_key(wcombo, BTN_TOUCH, 1); + input_report_key(input, BTN_TOUCH, 1); } static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_report_key(wcombo, wacom->tool[idx], 0); + struct input_dev *input = wacom->input; + + input_report_abs(input, ABS_X, 0); + input_report_abs(input, ABS_Y, 0); + input_report_abs(input, ABS_MISC, 0); + input_report_key(input, wacom->tool[idx], 0); if (idx) - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + input_event(input, EV_MSC, MSC_SERIAL, 0xf0); else - wacom_report_key(wcombo, BTN_TOUCH, 0); - return; + input_report_key(input, BTN_TOUCH, 0); } static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) { char *data = wacom->data; + struct input_dev *input = wacom->input; struct urb *urb = ((struct wacom_combo *)wcombo)->urb; static int firstFinger = 0; static int secondFinger = 0; @@ -648,12 +662,12 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) switch (data[0]) { case WACOM_REPORT_TPC1FG: - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); + input_report_abs(input, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); + input_report_key(input, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_report_key(input, wacom->tool[0], 1); break; case WACOM_REPORT_TPC2FG: @@ -670,14 +684,14 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) if (data[1] & 0x02) { /* sync first finger data */ if (firstFinger) - wacom_input_sync(wcombo); + input_sync(input); wacom_tpc_finger_in(wacom, wcombo, data, 1); secondFinger = 1; } else if (secondFinger) { /* sync first finger data */ if (firstFinger) - wacom_input_sync(wcombo); + input_sync(input); wacom_tpc_touch_out(wacom, wcombo, 1); secondFinger = 0; @@ -687,11 +701,11 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) break; } } else { - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_key(wcombo, BTN_TOUCH, 1); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_key(input, BTN_TOUCH, 1); + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_report_key(input, wacom->tool[0], 1); } } @@ -699,6 +713,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; char *data = wacom->data; + struct input_dev *input = wacom->input; int prox = 0, pressure, idx = -1; struct urb *urb = ((struct wacom_combo *)wcombo)->urb; @@ -729,7 +744,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom_tpc_touch_out(wacom, wcombo, idx); /* sync first finger event */ if (wacom->id[1] & 0x02) - wacom_input_sync(wcombo); + input_sync(input); } idx = (wacom->id[1] & 0x02) - 1; if (idx == 1) @@ -757,21 +772,21 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom->shared->stylus_in_proximity = true; } - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + input_report_key(input, BTN_STYLUS, data[1] & 0x02); + input_report_key(input, BTN_STYLUS2, data[1] & 0x10); + input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); + input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); pressure = ((data[7] & 0x01) << 8) | data[6]; if (pressure < 0) pressure = features->pressure_max + pressure + 1; - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_key(input, BTN_TOUCH, data[1] & 0x05); if (!prox) { /* out-prox */ wacom->id[0] = 0; wacom->shared->stylus_in_proximity = false; } - wacom_report_key(wcombo, wacom->tool[0], prox); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + input_report_key(input, wacom->tool[0], prox); + input_report_abs(input, ABS_MISC, wacom->id[0]); return 1; } return 0; @@ -815,64 +830,160 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) return 0; } -void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) +static void wacom_setup_intuos(struct wacom_wac *wacom_wac) +{ + struct input_dev *input_dev = wacom_wac->input; + + input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + input_set_capability(input_dev, EV_REL, REL_WHEEL); + + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + __set_bit(BTN_MIDDLE, input_dev->keybit); + __set_bit(BTN_SIDE, input_dev->keybit); + __set_bit(BTN_EXTRA, input_dev->keybit); + + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); + __set_bit(BTN_TOOL_PEN, input_dev->keybit); + __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); + __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); + __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); + __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); + __set_bit(BTN_TOOL_LENS, input_dev->keybit); + __set_bit(BTN_STYLUS, input_dev->keybit); + __set_bit(BTN_STYLUS2, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_DISTANCE, + 0, wacom_wac->features.distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); + input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); +} + +void wacom_setup_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) { + struct wacom_features *features = &wacom_wac->features; + int i; + + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + __set_bit(BTN_TOUCH, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); + + __set_bit(ABS_MISC, input_dev->absbit); + switch (wacom_wac->features.type) { case WACOM_MO: - input_dev_mo(input_dev, wacom_wac); + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_5, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); + /* fall through */ case WACOM_G4: - input_dev_g4(input_dev, wacom_wac); + input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_0, input_dev->keybit); + __set_bit(BTN_4, input_dev->keybit); /* fall through */ case GRAPHIRE: - input_dev_g(input_dev, wacom_wac); + input_set_capability(input_dev, EV_REL, REL_WHEEL); + + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + __set_bit(BTN_MIDDLE, input_dev->keybit); + + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); + __set_bit(BTN_TOOL_PEN, input_dev->keybit); + __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); + __set_bit(BTN_STYLUS, input_dev->keybit); + __set_bit(BTN_STYLUS2, input_dev->keybit); break; case WACOM_BEE: - input_dev_bee(input_dev, wacom_wac); + __set_bit(BTN_8, input_dev->keybit); + __set_bit(BTN_9, input_dev->keybit); + /* fall through */ case INTUOS3: case INTUOS3L: case CINTIQ: - input_dev_i3(input_dev, wacom_wac); + __set_bit(BTN_4, input_dev->keybit); + __set_bit(BTN_5, input_dev->keybit); + __set_bit(BTN_6, input_dev->keybit); + __set_bit(BTN_7, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); /* fall through */ case INTUOS3S: - input_dev_i3s(input_dev, wacom_wac); + __set_bit(BTN_0, input_dev->keybit); + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_2, input_dev->keybit); + __set_bit(BTN_3, input_dev->keybit); + + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); /* fall through */ case INTUOS: - input_dev_i(input_dev, wacom_wac); + wacom_setup_intuos(wacom_wac); break; case INTUOS4: case INTUOS4L: - input_dev_i4(input_dev, wacom_wac); + __set_bit(BTN_7, input_dev->keybit); + __set_bit(BTN_8, input_dev->keybit); /* fall through */ case INTUOS4S: - input_dev_i4s(input_dev, wacom_wac); - input_dev_i(input_dev, wacom_wac); + for (i = 0; i < 7; i++) + __set_bit(BTN_0 + i, input_dev->keybit); + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + wacom_setup_intuos(wacom_wac); break; case TABLETPC2FG: - input_dev_tpc2fg(input_dev, wacom_wac); + if (features->device_type == BTN_TOOL_TRIPLETAP) { + __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + input_set_capability(input_dev, EV_MSC, MSC_SERIAL); + } /* fall through */ case TABLETPC: - input_dev_tpc(input_dev, wacom_wac); - if (wacom_wac->features.device_type != BTN_TOOL_PEN) + if (features->device_type == BTN_TOOL_DOUBLETAP || + features->device_type == BTN_TOOL_TRIPLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + } + + if (features->device_type != BTN_TOOL_PEN) break; /* no need to process stylus stuff */ + /* fall through */ case PL: case PTU: - input_dev_pl(input_dev, wacom_wac); + __set_bit(BTN_TOOL_PEN, input_dev->keybit); + __set_bit(BTN_STYLUS, input_dev->keybit); + __set_bit(BTN_STYLUS2, input_dev->keybit); /* fall through */ case PENPARTNER: - input_dev_pt(input_dev, wacom_wac); + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); break; } } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index f190a2bf148..69098a2aa69 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -85,6 +85,7 @@ struct wacom_wac { __u32 serial[2]; struct wacom_features features; struct wacom_shared *shared; + struct input_dev *input; }; #endif -- cgit v1.2.2 From 95dd3b30ced3ee740e5dd92fc44515a5a6a350d4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: wacom - get rid of wacom_combo structure Now that we moved input device from struct wacom to struct wacom_wac, presence of wacom_combo just complicats things for no good reason. Let's get rid of it and simply pass URB length to wacom_wac_irq(). Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 7 +--- drivers/input/tablet/wacom_sys.c | 12 +----- drivers/input/tablet/wacom_wac.c | 81 ++++++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 53 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 103a8cc2944..56a37074e0d 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -115,14 +115,9 @@ struct wacom { char phys[32]; }; -struct wacom_combo { - struct wacom *wacom; - struct urb *urb; -}; - extern const struct usb_device_id wacom_ids[]; -int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); +void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac); __u16 wacom_le16_to_cpu(unsigned char *data); diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 58bb763b60d..c37e22b968d 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -70,15 +70,9 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, buf, size, 1000); } -static struct input_dev * get_input_dev(struct wacom_combo *wcombo) -{ - return wcombo->wacom->wacom_wac.input; -} - static void wacom_sys_irq(struct urb *urb) { struct wacom *wacom = urb->context; - struct wacom_combo wcombo; int retval; switch (urb->status) { @@ -96,11 +90,7 @@ static void wacom_sys_irq(struct urb *urb) goto exit; } - wcombo.wacom = wacom; - wcombo.urb = urb; - - if (wacom_wac_irq(&wacom->wacom_wac, &wcombo)) - input_sync(get_input_dev(&wcombo)); + wacom_wac_irq(&wacom->wacom_wac, urb->actual_length); exit: usb_mark_last_busy(wacom->usbdev); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 9cf4854a981..8163e8f06f2 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -15,7 +15,7 @@ #include "wacom_wac.h" #include "wacom.h" -static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; struct input_dev *input = wacom->input; @@ -58,7 +58,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) return 1; } -static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_pl_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; @@ -130,7 +130,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) return 1; } -static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_ptu_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; struct input_dev *input = wacom->input; @@ -158,7 +158,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) return 1; } -static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_graphire_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; @@ -269,7 +269,7 @@ exit: return retval; } -static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) +static int wacom_intuos_inout(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; @@ -396,7 +396,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) return 0; } -static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) +static void wacom_intuos_general(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; @@ -427,7 +427,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) } } -static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_intuos_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; @@ -504,7 +504,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } /* process in/out prox events */ - result = wacom_intuos_inout(wacom, wcombo); + result = wacom_intuos_inout(wacom); if (result) return result - 1; @@ -537,7 +537,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } /* process general packets */ - wacom_intuos_general(wacom, wcombo); + wacom_intuos_general(wacom); /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */ if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) { @@ -615,7 +615,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } -static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) +static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) { struct input_dev *input = wacom->input; @@ -631,7 +631,7 @@ static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *dat input_report_key(input, BTN_TOUCH, 1); } -static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) +static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) { struct input_dev *input = wacom->input; @@ -645,11 +645,10 @@ static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) input_report_key(input, BTN_TOUCH, 0); } -static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) +static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) { char *data = wacom->data; struct input_dev *input = wacom->input; - struct urb *urb = ((struct wacom_combo *)wcombo)->urb; static int firstFinger = 0; static int secondFinger = 0; @@ -657,7 +656,7 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) wacom->id[0] = TOUCH_DEVICE_ID; wacom->tool[1] = BTN_TOOL_TRIPLETAP; - if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { + if (len != WACOM_PKGLEN_TPC1FG) { switch (data[0]) { @@ -675,10 +674,10 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) wacom->id[1] = data[1] & 0x03; if (data[1] & 0x01) { - wacom_tpc_finger_in(wacom, wcombo, data, 0); + wacom_tpc_finger_in(wacom, data, 0); firstFinger = 1; } else if (firstFinger) { - wacom_tpc_touch_out(wacom, wcombo, 0); + wacom_tpc_touch_out(wacom, 0); } if (data[1] & 0x02) { @@ -686,14 +685,14 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) if (firstFinger) input_sync(input); - wacom_tpc_finger_in(wacom, wcombo, data, 1); + wacom_tpc_finger_in(wacom, data, 1); secondFinger = 1; } else if (secondFinger) { /* sync first finger data */ if (firstFinger) input_sync(input); - wacom_tpc_touch_out(wacom, wcombo, 1); + wacom_tpc_touch_out(wacom, 1); secondFinger = 0; } if (!(data[1] & 0x01)) @@ -709,20 +708,19 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) } } -static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) +static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) { struct wacom_features *features = &wacom->features; char *data = wacom->data; struct input_dev *input = wacom->input; int prox = 0, pressure, idx = -1; - struct urb *urb = ((struct wacom_combo *)wcombo)->urb; dbg("wacom_tpc_irq: received report #%d", data[0]); - if (urb->actual_length == WACOM_PKGLEN_TPC1FG || /* single touch */ + if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ data[0] == WACOM_REPORT_TPC1FG || /* single touch */ data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ - if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ + if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ prox = data[0] & 0x01; } else { /* with capacity */ if (data[0] == WACOM_REPORT_TPC1FG) @@ -735,28 +733,28 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) if (!wacom->shared->stylus_in_proximity) { if (prox) { - wacom_tpc_touch_in(wacom, wcombo); + wacom_tpc_touch_in(wacom, len); } else { if (data[0] == WACOM_REPORT_TPC2FG) { /* 2FGT out-prox */ idx = (wacom->id[1] & 0x01) - 1; if (idx == 0) { - wacom_tpc_touch_out(wacom, wcombo, idx); + wacom_tpc_touch_out(wacom, idx); /* sync first finger event */ if (wacom->id[1] & 0x02) input_sync(input); } idx = (wacom->id[1] & 0x02) - 1; if (idx == 1) - wacom_tpc_touch_out(wacom, wcombo, idx); + wacom_tpc_touch_out(wacom, idx); } else { /* one finger touch */ - wacom_tpc_touch_out(wacom, wcombo, 0); + wacom_tpc_touch_out(wacom, 0); } wacom->id[0] = 0; } } else if (wacom->id[0]) { /* force touch out-prox */ - wacom_tpc_touch_out(wacom, wcombo, 0); + wacom_tpc_touch_out(wacom, 0); } return 1; } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ @@ -792,22 +790,28 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) return 0; } -int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) +void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) { + bool sync; + switch (wacom_wac->features.type) { case PENPARTNER: - return wacom_penpartner_irq(wacom_wac, wcombo); + sync = wacom_penpartner_irq(wacom_wac); + break; case PL: - return wacom_pl_irq(wacom_wac, wcombo); + sync = wacom_pl_irq(wacom_wac); + break; case WACOM_G4: case GRAPHIRE: case WACOM_MO: - return wacom_graphire_irq(wacom_wac, wcombo); + sync = wacom_graphire_irq(wacom_wac); + break; case PTU: - return wacom_ptu_irq(wacom_wac, wcombo); + sync = wacom_ptu_irq(wacom_wac); + break; case INTUOS: case INTUOS3S: @@ -818,16 +822,21 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) case INTUOS4L: case CINTIQ: case WACOM_BEE: - return wacom_intuos_irq(wacom_wac, wcombo); + sync = wacom_intuos_irq(wacom_wac); + break; case TABLETPC: case TABLETPC2FG: - return wacom_tpc_irq(wacom_wac, wcombo); + sync = wacom_tpc_irq(wacom_wac, len); + break; default: - return 0; + sync = false; + break; } - return 0; + + if (sync) + input_sync(wacom_wac->input); } static void wacom_setup_intuos(struct wacom_wac *wacom_wac) -- cgit v1.2.2 From 252f77698fe37bdd784e514820852a3ea9827fd0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Mar 2010 22:33:38 -0700 Subject: Input: wacom - use get_unaligned to access unaligned data Also get rid of wacom_le16_to_cpu() and wacom_be16_to_cpu() helpers and ise le16_to_cpup() and be16_to_cpup() directly. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 3 --- drivers/input/tablet/wacom_sys.c | 30 ++++++++-------------------- drivers/input/tablet/wacom_wac.c | 42 +++++++++++++++++++--------------------- 3 files changed, 28 insertions(+), 47 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 56a37074e0d..284dfaab6b8 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -120,7 +120,4 @@ extern const struct usb_device_id wacom_ids[]; void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -__u16 wacom_le16_to_cpu(unsigned char *data); -__u16 wacom_be16_to_cpu(unsigned char *data); - #endif diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index c37e22b968d..d90f4e00e51 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -100,20 +100,6 @@ static void wacom_sys_irq(struct urb *urb) __func__, retval); } -__u16 wacom_be16_to_cpu(unsigned char *data) -{ - __u16 value; - value = be16_to_cpu(*(__be16 *) data); - return value; -} - -__u16 wacom_le16_to_cpu(unsigned char *data) -{ - __u16 value; - value = le16_to_cpu(*(__le16 *) data); - return value; -} - static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); @@ -210,9 +196,9 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->device_type = BTN_TOOL_TRIPLETAP; } features->x_max = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); features->x_phy = - wacom_le16_to_cpu(&report[i + 6]); + get_unaligned_le16(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; @@ -222,7 +208,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); i += 4; } } else if (usage == WCM_DIGITIZER) { @@ -244,15 +230,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->pktlen = WACOM_PKGLEN_TPC2FG; features->device_type = BTN_TOOL_TRIPLETAP; features->y_max = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); features->y_phy = - wacom_le16_to_cpu(&report[i + 6]); + get_unaligned_le16(&report[i + 6]); i += 7; } else { features->y_max = features->x_max; features->y_phy = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); i += 4; } } else if (pen) { @@ -261,7 +247,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); i += 4; } } @@ -280,7 +266,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_UNDEFINED: if (usage == WCM_DESKTOP && finger) /* capacity */ features->pressure_max = - wacom_le16_to_cpu(&report[i + 3]); + get_unaligned_le16(&report[i + 3]); i += 4; break; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 8163e8f06f2..950a81d7a67 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -27,8 +27,8 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom) wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; input_report_key(input, wacom->tool[0], 1); input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); + input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127)); input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); @@ -43,8 +43,8 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom) case 2: input_report_key(input, BTN_TOOL_PEN, 1); input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); + input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); @@ -150,9 +150,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) wacom->id[0] = STYLUS_DEVICE_ID; } input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); - input_report_abs(input, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); + input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x10); return 1; @@ -163,7 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; struct input_dev *input = wacom->input; - int x, y, prox; + int prox; int rw = 0; int retval = 0; @@ -197,10 +197,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) break; } } - x = wacom_le16_to_cpu(&data[2]); - y = wacom_le16_to_cpu(&data[4]); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); if (wacom->tool[0] != BTN_TOOL_MOUSE) { input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); input_report_key(input, BTN_TOUCH, data[1] & 0x01); @@ -531,8 +529,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); } else { - input_report_abs(input, ABS_X, wacom_be16_to_cpu(&data[2])); - input_report_abs(input, ABS_Y, wacom_be16_to_cpu(&data[4])); + input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2])); + input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4])); input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); } @@ -661,10 +659,10 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) switch (data[0]) { case WACOM_REPORT_TPC1FG: - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); - input_report_abs(input, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - input_report_key(input, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); + input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); + input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); input_report_abs(input, ABS_MISC, wacom->id[0]); input_report_key(input, wacom->tool[0], 1); break; @@ -700,8 +698,8 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) break; } } else { - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[1])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[3])); + input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); + input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); input_report_key(input, BTN_TOUCH, 1); input_report_abs(input, ABS_MISC, wacom->id[0]); input_report_key(input, wacom->tool[0], 1); @@ -772,8 +770,8 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) } input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x10); - input_report_abs(input, ABS_X, wacom_le16_to_cpu(&data[2])); - input_report_abs(input, ABS_Y, wacom_le16_to_cpu(&data[4])); + input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); + input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); pressure = ((data[7] & 0x01) << 8) | data[6]; if (pressure < 0) pressure = features->pressure_max + pressure + 1; -- cgit v1.2.2 From ab687b18aa77aeda5472d9ea054bf92c45c49c0c Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 5 Apr 2010 23:07:41 -0700 Subject: Input: wacom - streamline 2-finger touch support Clean up 2-finger touch support. This still needs to be converted to proper multi-touch protocol. Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 148 ++++++++++++++++++++------------------- drivers/input/tablet/wacom_wac.h | 5 +- 2 files changed, 80 insertions(+), 73 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 950a81d7a67..847fd0135bc 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -236,13 +236,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); input_report_rel(input, REL_WHEEL, rw); input_report_key(input, BTN_TOOL_FINGER, 0xf0); - input_report_abs(input, ABS_MISC, wacom->id[1]); if (!prox) wacom->id[1] = 0; input_report_abs(input, ABS_MISC, wacom->id[1]); input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + retval = 1; } - retval = 1; break; case WACOM_MO: @@ -616,43 +615,59 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) { struct input_dev *input = wacom->input; + int finger = idx + 1; + int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; + int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; + + /* + * Work around input core suppressing "duplicate" events since + * we are abusing ABS_X/ABS_Y to transmit multi-finger data. + * This should go away once we switch to true multitouch + * protocol. + */ + if (wacom->last_finger != finger) { + if (x == input->abs[ABS_X]) + x++; + + if (y == input->abs[ABS_Y]) + y++; + } - input_report_abs(input, ABS_X, - data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); - input_report_abs(input, ABS_Y, - data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); input_report_abs(input, ABS_MISC, wacom->id[0]); - input_report_key(input, wacom->tool[idx], 1); - if (idx) - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); - else + input_report_key(input, wacom->tool[finger], 1); + if (!idx) input_report_key(input, BTN_TOUCH, 1); + input_event(input, EV_MSC, MSC_SERIAL, finger); + input_sync(wacom->input); + + wacom->last_finger = finger; } static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) { struct input_dev *input = wacom->input; + int finger = idx + 1; input_report_abs(input, ABS_X, 0); input_report_abs(input, ABS_Y, 0); input_report_abs(input, ABS_MISC, 0); - input_report_key(input, wacom->tool[idx], 0); - if (idx) - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); - else + input_report_key(input, wacom->tool[finger], 0); + if (!idx) input_report_key(input, BTN_TOUCH, 0); + input_event(input, EV_MSC, MSC_SERIAL, finger); + input_sync(input); } static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) { char *data = wacom->data; struct input_dev *input = wacom->input; - static int firstFinger = 0; - static int secondFinger = 0; - wacom->tool[0] = BTN_TOOL_DOUBLETAP; + wacom->tool[1] = BTN_TOOL_DOUBLETAP; wacom->id[0] = TOUCH_DEVICE_ID; - wacom->tool[1] = BTN_TOOL_TRIPLETAP; + wacom->tool[2] = BTN_TOOL_TRIPLETAP; if (len != WACOM_PKGLEN_TPC1FG) { @@ -664,45 +679,29 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); input_report_abs(input, ABS_MISC, wacom->id[0]); - input_report_key(input, wacom->tool[0], 1); + input_report_key(input, wacom->tool[1], 1); + input_sync(input); break; case WACOM_REPORT_TPC2FG: - /* keep this byte to send proper out-prox event */ - wacom->id[1] = data[1] & 0x03; - - if (data[1] & 0x01) { + if (data[1] & 0x01) wacom_tpc_finger_in(wacom, data, 0); - firstFinger = 1; - } else if (firstFinger) { + else if (wacom->id[1] & 0x01) wacom_tpc_touch_out(wacom, 0); - } - - if (data[1] & 0x02) { - /* sync first finger data */ - if (firstFinger) - input_sync(input); + if (data[1] & 0x02) wacom_tpc_finger_in(wacom, data, 1); - secondFinger = 1; - } else if (secondFinger) { - /* sync first finger data */ - if (firstFinger) - input_sync(input); - + else if (wacom->id[1] & 0x02) wacom_tpc_touch_out(wacom, 1); - secondFinger = 0; - } - if (!(data[1] & 0x01)) - firstFinger = 0; break; } } else { input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_MISC, wacom->id[0]); - input_report_key(input, wacom->tool[0], 1); + input_report_abs(input, ABS_MISC, wacom->id[1]); + input_report_key(input, wacom->tool[1], 1); + input_sync(input); } } @@ -711,13 +710,26 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) struct wacom_features *features = &wacom->features; char *data = wacom->data; struct input_dev *input = wacom->input; - int prox = 0, pressure, idx = -1; + int prox = 0, pressure; + int retval = 0; dbg("wacom_tpc_irq: received report #%d", data[0]); if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ data[0] == WACOM_REPORT_TPC1FG || /* single touch */ data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ + + if (wacom->shared->stylus_in_proximity) { + if (wacom->id[1] & 0x01) + wacom_tpc_touch_out(wacom, 0); + + if (wacom->id[1] & 0x02) + wacom_tpc_touch_out(wacom, 1); + + wacom->id[1] = 0; + return 0; + } + if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ prox = data[0] & 0x01; } else { /* with capacity */ @@ -729,36 +741,30 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) prox = data[1] & 0x03; } - if (!wacom->shared->stylus_in_proximity) { - if (prox) { - wacom_tpc_touch_in(wacom, len); - } else { - if (data[0] == WACOM_REPORT_TPC2FG) { - /* 2FGT out-prox */ - idx = (wacom->id[1] & 0x01) - 1; - if (idx == 0) { - wacom_tpc_touch_out(wacom, idx); - /* sync first finger event */ - if (wacom->id[1] & 0x02) - input_sync(input); - } - idx = (wacom->id[1] & 0x02) - 1; - if (idx == 1) - wacom_tpc_touch_out(wacom, idx); - } else { - /* one finger touch */ + if (prox) { + if (!wacom->id[1]) + wacom->last_finger = 1; + wacom_tpc_touch_in(wacom, len); + } else { + if (data[0] == WACOM_REPORT_TPC2FG) { + /* 2FGT out-prox */ + if (wacom->id[1] & 0x01) wacom_tpc_touch_out(wacom, 0); - } - wacom->id[0] = 0; - } - } else if (wacom->id[0]) { /* force touch out-prox */ - wacom_tpc_touch_out(wacom, 0); + + if (wacom->id[1] & 0x02) + wacom_tpc_touch_out(wacom, 1); + } else + /* one finger touch */ + wacom_tpc_touch_out(wacom, 0); + + wacom->id[0] = 0; } - return 1; + /* keep prox bit to send proper out-prox event */ + wacom->id[1] = prox; } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ prox = data[1] & 0x20; - if (!wacom->id[0]) { /* first in prox */ + if (!wacom->shared->stylus_in_proximity) { /* first in prox */ /* Going into proximity select tool */ wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; if (wacom->tool[0] == BTN_TOOL_PEN) @@ -783,9 +789,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) } input_report_key(input, wacom->tool[0], prox); input_report_abs(input, ABS_MISC, wacom->id[0]); - return 1; + retval = 1; } - return 0; + return retval; } void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 69098a2aa69..063f1af3204 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -80,9 +80,10 @@ struct wacom_shared { struct wacom_wac { char name[64]; unsigned char *data; - int tool[2]; - int id[2]; + int tool[3]; + int id[3]; __u32 serial[2]; + int last_finger; struct wacom_features features; struct wacom_shared *shared; struct input_dev *input; -- cgit v1.2.2 From 2adaabd47164a0f89364f46172c35613c4d1fbdd Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 19 Mar 2010 22:33:46 -0700 Subject: Input: remove now deprecated corgi_ts.c touchscreen driver The corgi touchscreen is now deprecated in favour of the generic ads7846.c driver. The noise reduction technique used in corgi_ts.c, which is to wait till vsync before ADC sampling, is also integrated into ads7846 driver now. Provided that the original driver is not generic and is difficult to maintain, it will be removed now. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Pavel Machek Cc: Dmitry Torokhov Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 16 -- drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/corgi_ts.c | 385 ----------------------------------- 3 files changed, 402 deletions(-) delete mode 100644 drivers/input/touchscreen/corgi_ts.c (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a..3d1ade2e519 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY To compile this driver as a module, choose M here: the module will be called h3600_ts_input. -config TOUCHSCREEN_CORGI - tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" - depends on PXA_SHARPSL - select CORGI_SSP_DEPRECATED - help - Say Y here to enable the driver for the touchscreen on the - Sharp SL-C7xx and SL-Cxx00 series of PDAs. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called corgi_ts. - - NOTE: this driver is deprecated, try enable SPI and generic - ADS7846-based touchscreen driver. - config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca2..41145d074de 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439..00000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models - * - * Copyright (c) 2004-2005 Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define PWR_MODE_ACTIVE 0 -#define PWR_MODE_SUSPEND 1 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 15000 - -struct ts_event { - short pressure; - short x; - short y; -}; - -struct corgi_ts { - struct input_dev *input; - struct timer_list timer; - struct ts_event tc; - int pendown; - int power_mode; - int irq_gpio; - struct corgits_machinfo *machinfo; -}; - -#ifdef CONFIG_PXA25x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) -#endif -#ifdef CONFIG_PXA27x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) -#endif - -/* ADS7846 Touch Screen Controller bit definitions */ -#define ADSCTRL_PD0 (1u << 0) /* PD0 */ -#define ADSCTRL_PD1 (1u << 1) /* PD1 */ -#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ -#define ADSCTRL_MOD (1u << 3) /* Mode */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS (1u << 7) /* Start Bit */ - -/* External Functions */ -extern unsigned int get_clk_frequency_khz(int info); - -static unsigned long calc_waittime(struct corgi_ts *corgi_ts) -{ - unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); - - if (hsync_invperiod) - return get_clk_frequency_khz(0)*1000/hsync_invperiod; - else - return 0; -} - -static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, - unsigned int address, unsigned long wait_time) -{ - unsigned long timer1 = 0, timer2, pmnc = 0; - int pos = 0; - - if (wait_time && doSend) { - PMNC_GET(pmnc); - if (!(pmnc & 0x01)) - PMNC_SET(0x01); - - /* polling HSync */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - } - - if (doRecive) - pos = corgi_ssp_ads7846_get(); - - if (doSend) { - int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; - /* dummy command */ - corgi_ssp_ads7846_put(cmd); - corgi_ssp_ads7846_get(); - - if (wait_time) { - /* Wait after HSync */ - CCNT(timer2); - if (timer2-timer1 > wait_time) { - /* too slow - timeout, try again */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - /* Wait after HSync */ - CCNT(timer2); - } - while (timer2 - timer1 < wait_time) - CCNT(timer2); - } - corgi_ssp_ads7846_put(cmd); - if (wait_time && !(pmnc & 0x01)) - PMNC_SET(pmnc); - } - return pos; -} - -static int read_xydata(struct corgi_ts *corgi_ts) -{ - unsigned int x, y, z1, z2; - unsigned long flags, wait_time; - - /* critical section */ - local_irq_save(flags); - corgi_ssp_ads7846_lock(); - wait_time = calc_waittime(corgi_ts); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); - - /* X-axis */ - y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); - - /* Z1 */ - x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); - - /* Z2 */ - z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); - z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); - - /* Power-Down Enable */ - corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - corgi_ssp_ads7846_get(); - - corgi_ssp_ads7846_unlock(); - local_irq_restore(flags); - - if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { - corgi_ts->tc.pressure = 0; - return 0; - } - - corgi_ts->tc.x = x; - corgi_ts->tc.y = y; - corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; - return 1; -} - -static void new_data(struct corgi_ts *corgi_ts) -{ - struct input_dev *dev = corgi_ts->input; - - if (corgi_ts->power_mode != PWR_MODE_ACTIVE) - return; - - if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) - return; - - input_report_abs(dev, ABS_X, corgi_ts->tc.x); - input_report_abs(dev, ABS_Y, corgi_ts->tc.y); - input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); - input_sync(dev); -} - -static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) -{ - if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { - /* Disable Interrupt */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); - if (read_xydata(corgi_ts)) { - corgi_ts->pendown = 1; - new_data(corgi_ts); - } - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - } else { - if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - corgi_ts->pendown++; - return; - } - - if (corgi_ts->pendown) { - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - } - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->pendown = 0; - } -} - -static void corgi_ts_timer(unsigned long data) -{ - struct corgi_ts *corgits_data = (struct corgi_ts *) data; - - ts_interrupt_main(corgits_data, 1); -} - -static irqreturn_t ts_interrupt(int irq, void *dev_id) -{ - struct corgi_ts *corgits_data = dev_id; - - ts_interrupt_main(corgits_data, 0); - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM -static int corgits_suspend(struct platform_device *dev, pm_message_t state) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - if (corgi_ts->pendown) { - del_timer_sync(&corgi_ts->timer); - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - corgi_ts->pendown = 0; - } - corgi_ts->power_mode = PWR_MODE_SUSPEND; - - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - - return 0; -} - -static int corgits_resume(struct platform_device *dev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - return 0; -} -#else -#define corgits_suspend NULL -#define corgits_resume NULL -#endif - -static int __devinit corgits_probe(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts; - struct input_dev *input_dev; - int err = -ENOMEM; - - corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgi_ts || !input_dev) - goto fail1; - - platform_set_drvdata(pdev, corgi_ts); - - corgi_ts->machinfo = pdev->dev.platform_data; - corgi_ts->irq_gpio = platform_get_irq(pdev, 0); - - if (corgi_ts->irq_gpio < 0) { - err = -ENODEV; - goto fail1; - } - - corgi_ts->input = input_dev; - - init_timer(&corgi_ts->timer); - corgi_ts->timer.data = (unsigned long) corgi_ts; - corgi_ts->timer.function = corgi_ts_timer; - - input_dev->name = "Corgi Touchscreen"; - input_dev->phys = "corgits/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0002; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); - - pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); - - /* Initiaize ADS7846 Difference Reference mode */ - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - - if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { - err = -EBUSY; - goto fail1; - } - - err = input_register_device(corgi_ts->input); - if (err) - goto fail2; - - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - - return 0; - - fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); - fail1: input_free_device(input_dev); - kfree(corgi_ts); - return err; -} - -static int __devexit corgits_remove(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - - free_irq(corgi_ts->irq_gpio, corgi_ts); - del_timer_sync(&corgi_ts->timer); - corgi_ts->machinfo->put_hsync(); - input_unregister_device(corgi_ts->input); - kfree(corgi_ts); - - return 0; -} - -static struct platform_driver corgits_driver = { - .probe = corgits_probe, - .remove = __devexit_p(corgits_remove), - .suspend = corgits_suspend, - .resume = corgits_resume, - .driver = { - .name = "corgi-ts", - .owner = THIS_MODULE, - }, -}; - -static int __init corgits_init(void) -{ - return platform_driver_register(&corgits_driver); -} - -static void __exit corgits_exit(void) -{ - platform_driver_unregister(&corgits_driver); -} - -module_init(corgits_init); -module_exit(corgits_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:corgi-ts"); -- cgit v1.2.2 From b91c4be730668e801aa6a2ea95f467cd9a1e0983 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Fri, 19 Mar 2010 22:18:15 -0700 Subject: Input: add PCF8574 I2C keypad input device driver Signed-off-by: Bryan Wu Signed-off-by: Mike Frysinger Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 10 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/pcf8574_keypad.c | 227 ++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 drivers/input/misc/pcf8574_keypad.c (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 23140a3bb8e..54a9c2d0ba1 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -277,6 +277,16 @@ config INPUT_PCF50633_PMU Say Y to include support for delivering PMU events via input layer on NXP PCF50633. +config INPUT_PCF8574 + tristate "PCF8574 Keypad input device" + depends on I2C && EXPERIMENTAL + help + Say Y here if you want to support a keypad connetced via I2C + with a PCF8574. + + To compile this driver as a module, choose M here: the + module will be called pcf8574_keypad. + config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" depends on GPIOLIB && GENERIC_GPIO diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 7e95a5d474d..a662df21bf5 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o +obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c new file mode 100644 index 00000000000..5c3ac4e0b05 --- /dev/null +++ b/drivers/input/misc/pcf8574_keypad.c @@ -0,0 +1,227 @@ +/* + * Driver for a keypad w/16 buttons connected to a PCF8574 I2C I/O expander + * + * Copyright 2005-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pcf8574_keypad" + +static const unsigned char pcf8574_kp_btncode[] = { + [0] = KEY_RESERVED, + [1] = KEY_ENTER, + [2] = KEY_BACKSLASH, + [3] = KEY_0, + [4] = KEY_RIGHTBRACE, + [5] = KEY_C, + [6] = KEY_9, + [7] = KEY_8, + [8] = KEY_7, + [9] = KEY_B, + [10] = KEY_6, + [11] = KEY_5, + [12] = KEY_4, + [13] = KEY_A, + [14] = KEY_3, + [15] = KEY_2, + [16] = KEY_1 +}; + +struct kp_data { + unsigned short btncode[ARRAY_SIZE(pcf8574_kp_btncode)]; + struct input_dev *idev; + struct i2c_client *client; + char name[64]; + char phys[32]; + unsigned char laststate; +}; + +static short read_state(struct kp_data *lp) +{ + unsigned char x, y, a, b; + + i2c_smbus_write_byte(lp->client, 240); + x = 0xF & (~(i2c_smbus_read_byte(lp->client) >> 4)); + + i2c_smbus_write_byte(lp->client, 15); + y = 0xF & (~i2c_smbus_read_byte(lp->client)); + + for (a = 0; x > 0; a++) + x = x >> 1; + for (b = 0; y > 0; b++) + y = y >> 1; + + return ((a - 1) * 4) + b; +} + +static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id) +{ + struct kp_data *lp = dev_id; + unsigned char nextstate = read_state(lp); + + if (lp->laststate != nextstate) { + int key_down = nextstate <= ARRAY_SIZE(lp->btncode); + unsigned short keycode = key_down ? + lp->btncode[nextstate] : lp->btncode[lp->laststate]; + + input_report_key(lp->idev, keycode, key_down); + input_sync(lp->idev); + + lp->laststate = nextstate; + } + + return IRQ_HANDLED; +} + +static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i, ret; + struct input_dev *idev; + struct kp_data *lp; + + if (i2c_smbus_write_byte(client, 240) < 0) { + dev_err(&client->dev, "probe: write fail\n"); + return -ENODEV; + } + + lp = kzalloc(sizeof(*lp), GFP_KERNEL); + if (!lp) + return -ENOMEM; + + idev = input_allocate_device(); + if (!idev) { + dev_err(&client->dev, "Can't allocate input device\n"); + ret = -ENOMEM; + goto fail_allocate; + } + + lp->idev = idev; + lp->client = client; + + idev->evbit[0] = BIT_MASK(EV_KEY); + idev->keycode = lp->btncode; + idev->keycodesize = sizeof(lp->btncode[0]); + idev->keycodemax = ARRAY_SIZE(lp->btncode); + + for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) { + lp->btncode[i] = pcf8574_kp_btncode[i]; + __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit); + } + + sprintf(lp->name, DRV_NAME); + sprintf(lp->phys, "kp_data/input0"); + + idev->name = lp->name; + idev->phys = lp->phys; + idev->id.bustype = BUS_I2C; + idev->id.vendor = 0x0001; + idev->id.product = 0x0001; + idev->id.version = 0x0100; + + input_set_drvdata(idev, lp); + + ret = input_register_device(idev); + if (ret) { + dev_err(&client->dev, "input_register_device() failed\n"); + goto fail_register; + } + + lp->laststate = read_state(lp); + + ret = request_threaded_irq(client->irq, NULL, pcf8574_kp_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + DRV_NAME, lp); + if (ret) { + dev_err(&client->dev, "IRQ %d is not free\n", client->irq); + goto fail_irq; + } + + i2c_set_clientdata(client, lp); + return 0; + + fail_irq: + input_unregister_device(idev); + fail_register: + input_set_drvdata(idev, NULL); + input_free_device(idev); + fail_allocate: + kfree(lp); + + return ret; +} + +static int __devexit pcf8574_kp_remove(struct i2c_client *client) +{ + struct kp_data *lp = i2c_get_clientdata(client); + + free_irq(client->irq, lp); + + input_unregister_device(lp->idev); + kfree(lp); + + i2c_set_clientdata(client, NULL); + + return 0; +} + +#ifdef CONFIG_PM +static int pcf8574_kp_resume(struct i2c_client *client) +{ + enable_irq(client->irq); + + return 0; +} + +static int pcf8574_kp_suspend(struct i2c_client *client, pm_message_t mesg) +{ + disable_irq(client->irq); + + return 0; +} +#else +# define pcf8574_kp_resume NULL +# define pcf8574_kp_suspend NULL +#endif + +static const struct i2c_device_id pcf8574_kp_id[] = { + { DRV_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id); + +static struct i2c_driver pcf8574_kp_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = pcf8574_kp_probe, + .remove = __devexit_p(pcf8574_kp_remove), + .suspend = pcf8574_kp_suspend, + .resume = pcf8574_kp_resume, + .id_table = pcf8574_kp_id, +}; + +static int __init pcf8574_kp_init(void) +{ + return i2c_add_driver(&pcf8574_kp_driver); +} +module_init(pcf8574_kp_init); + +static void __exit pcf8574_kp_exit(void) +{ + i2c_del_driver(&pcf8574_kp_driver); +} +module_exit(pcf8574_kp_exit); + +MODULE_AUTHOR("Michael Hennerich"); +MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From d6372b706e83817dfa6c9326d1054b9b95a7de2a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 21 Mar 2010 22:31:26 -0700 Subject: Input: tsc2007 - do not leave dangling clientdata pointer Do not leave dangling client data pointers when unbinding device from the driver. Signed-off-by: Wolfram Sang Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2007.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index be23780e8a3..769b479fcaa 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -347,6 +347,8 @@ static int __devexit tsc2007_remove(struct i2c_client *client) struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; + i2c_set_clientdata(client, NULL); + tsc2007_free_irq(ts); if (pdata->exit_platform_hw) -- cgit v1.2.2 From a5b33e6a207d75120ad9dad0b5401b561991dcce Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 21 Mar 2010 22:31:26 -0700 Subject: Input: lm8323 - do not leave dangling client data pointer Do not leave dangling client data pointers when unbinding device from the driver or when binding fails for some reason. Signed-off-by: Wolfram Sang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lm8323.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 60ac4684f87..bc696931fed 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -670,8 +670,6 @@ static int __devinit lm8323_probe(struct i2c_client *client, goto fail1; } - i2c_set_clientdata(client, lm); - lm->client = client; lm->idev = idev; mutex_init(&lm->lock); @@ -753,6 +751,8 @@ static int __devinit lm8323_probe(struct i2c_client *client, goto fail4; } + i2c_set_clientdata(client, lm); + device_init_wakeup(&client->dev, 1); enable_irq_wake(client->irq); @@ -778,6 +778,8 @@ static int __devexit lm8323_remove(struct i2c_client *client) struct lm8323_chip *lm = i2c_get_clientdata(client); int i; + i2c_set_clientdata(client, NULL); + disable_irq_wake(client->irq); free_irq(client->irq, lm); cancel_work_sync(&lm->work); -- cgit v1.2.2 From 31a6296333b94964e9a073649840bb34d4603369 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Sun, 21 Mar 2010 23:23:24 -0700 Subject: Input: add Analog Devices AD714x captouch input driver AD7142 and AD7147 are integrated capacitance-to-digital converters (CDCs) with on-chip environmental calibration for use in systems requiring a novel user input method. The AD7142 and AD7147 can interface to external capacitance sensors implementing functions such as buttons, scrollwheels, sliders, touchpads and so on. The chips don't restrict the specific usage. Depending on the hardware connection, one special target board can include one or several these components. The platform_data for the device's "struct device" holds these information. The data-struct defined in head file descript the hardware feature of button/scrollwheel/slider/touchpad components on target boards, which need be filled in the arch/mach-/. As the result, the driver is independent of boards. It gets the components layout from the platform_data, registers related devices, fullfills the algorithms and state machines for these components and report related input events to up level. Signed-off-by: Bryan Wu Signed-off-by: Michael Hennerich Signed-off-by: Barry Song <21cnbao@gmail.com> Signed-off-by: Mike Frysinger Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 30 + drivers/input/misc/Makefile | 3 + drivers/input/misc/ad714x-i2c.c | 137 ++++ drivers/input/misc/ad714x-spi.c | 103 +++ drivers/input/misc/ad714x.c | 1331 +++++++++++++++++++++++++++++++++++++++ drivers/input/misc/ad714x.h | 26 + 6 files changed, 1630 insertions(+) create mode 100644 drivers/input/misc/ad714x-i2c.c create mode 100644 drivers/input/misc/ad714x-spi.c create mode 100644 drivers/input/misc/ad714x.c create mode 100644 drivers/input/misc/ad714x.h (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 54a9c2d0ba1..a4b9dc5cf45 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -22,6 +22,36 @@ config INPUT_88PM860X_ONKEY To compile this driver as a module, choose M here: the module will be called 88pm860x_onkey. +config INPUT_AD714X + tristate "Analog Devices AD714x Capacitance Touch Sensor" + help + Say Y here if you want to support an AD7142/AD7147 touch sensor. + + You should select a bus connection too. + + To compile this driver as a module, choose M here: the + module will be called ad714x. + +config INPUT_AD714X_I2C + tristate "support I2C bus connection" + depends on INPUT_AD714X && I2C + default y + help + Say Y here if you have AD7142/AD7147 hooked to an I2C bus. + + To compile this driver as a module, choose M here: the + module will be called ad714x-i2c. + +config INPUT_AD714X_SPI + tristate "support SPI bus connection" + depends on INPUT_AD714X && SPI + default y + help + Say Y here if you have AD7142/AD7147 hooked to a SPI bus. + + To compile this driver as a module, choose M here: the + module will be called ad714x-spi. + config INPUT_PCSPKR tristate "PC Speaker support" depends on PCSPKR_PLATFORM diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index a662df21bf5..f9f577031e0 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -5,6 +5,9 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o +obj-$(CONFIG_INPUT_AD714X) += ad714x.o +obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o +obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o obj-$(CONFIG_INPUT_APANEL) += apanel.o obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c new file mode 100644 index 00000000000..a2cb6b426dc --- /dev/null +++ b/drivers/input/misc/ad714x-i2c.c @@ -0,0 +1,137 @@ +/* + * AD714X CapTouch Programmable Controller driver (I2C bus) + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include /* BUS_I2C */ +#include +#include +#include +#include "ad714x.h" + +#ifdef CONFIG_PM +static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message) +{ + return ad714x_disable(i2c_get_clientdata(client)); +} + +static int ad714x_i2c_resume(struct i2c_client *client) +{ + return ad714x_enable(i2c_get_clientdata(client)); +} +#else +# define ad714x_i2c_suspend NULL +# define ad714x_i2c_resume NULL +#endif + +static int ad714x_i2c_write(struct device *dev, unsigned short reg, + unsigned short data) +{ + struct i2c_client *client = to_i2c_client(dev); + int ret = 0; + u8 *_reg = (u8 *)® + u8 *_data = (u8 *)&data; + + u8 tx[4] = { + _reg[1], + _reg[0], + _data[1], + _data[0] + }; + + ret = i2c_master_send(client, tx, 4); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +static int ad714x_i2c_read(struct device *dev, unsigned short reg, + unsigned short *data) +{ + struct i2c_client *client = to_i2c_client(dev); + int ret = 0; + u8 *_reg = (u8 *)® + u8 *_data = (u8 *)data; + + u8 tx[2] = { + _reg[1], + _reg[0] + }; + u8 rx[2]; + + ret = i2c_master_send(client, tx, 2); + if (ret >= 0) + ret = i2c_master_recv(client, rx, 2); + + if (unlikely(ret < 0)) { + dev_err(&client->dev, "I2C read error\n"); + } else { + _data[0] = rx[1]; + _data[1] = rx[0]; + } + + return ret; +} + +static int __devinit ad714x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ad714x_chip *chip; + + chip = ad714x_probe(&client->dev, BUS_I2C, client->irq, + ad714x_i2c_read, ad714x_i2c_write); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + i2c_set_clientdata(client, chip); + + return 0; +} + +static int __devexit ad714x_i2c_remove(struct i2c_client *client) +{ + struct ad714x_chip *chip = i2c_get_clientdata(client); + + ad714x_remove(chip); + i2c_set_clientdata(client, NULL); + + return 0; +} + +static const struct i2c_device_id ad714x_id[] = { + { "ad7142_captouch", 0 }, + { "ad7147_captouch", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad714x_id); + +static struct i2c_driver ad714x_i2c_driver = { + .driver = { + .name = "ad714x_captouch", + }, + .probe = ad714x_i2c_probe, + .remove = __devexit_p(ad714x_i2c_remove), + .suspend = ad714x_i2c_suspend, + .resume = ad714x_i2c_resume, + .id_table = ad714x_id, +}; + +static __init int ad714x_i2c_init(void) +{ + return i2c_add_driver(&ad714x_i2c_driver); +} +module_init(ad714x_i2c_init); + +static __exit void ad714x_i2c_exit(void) +{ + i2c_del_driver(&ad714x_i2c_driver); +} +module_exit(ad714x_i2c_exit); + +MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c new file mode 100644 index 00000000000..7f8dedfd1bf --- /dev/null +++ b/drivers/input/misc/ad714x-spi.c @@ -0,0 +1,103 @@ +/* + * AD714X CapTouch Programmable Controller driver (SPI bus) + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include /* BUS_I2C */ +#include +#include +#include +#include "ad714x.h" + +#define AD714x_SPI_CMD_PREFIX 0xE000 /* bits 15:11 */ +#define AD714x_SPI_READ BIT(10) + +#ifdef CONFIG_PM +static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message) +{ + return ad714x_disable(spi_get_drvdata(spi)); +} + +static int ad714x_spi_resume(struct spi_device *spi) +{ + return ad714x_enable(spi_get_drvdata(spi)); +} +#else +# define ad714x_spi_suspend NULL +# define ad714x_spi_resume NULL +#endif + +static int ad714x_spi_read(struct device *dev, unsigned short reg, + unsigned short *data) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned short tx = AD714x_SPI_CMD_PREFIX | AD714x_SPI_READ | reg; + + return spi_write_then_read(spi, (u8 *)&tx, 2, (u8 *)data, 2); +} + +static int ad714x_spi_write(struct device *dev, unsigned short reg, + unsigned short data) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned short tx[2] = { + AD714x_SPI_CMD_PREFIX | reg, + data + }; + + return spi_write(spi, (u8 *)tx, 4); +} + +static int __devinit ad714x_spi_probe(struct spi_device *spi) +{ + struct ad714x_chip *chip; + + chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq, + ad714x_spi_read, ad714x_spi_write); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + spi_set_drvdata(spi, chip); + + return 0; +} + +static int __devexit ad714x_spi_remove(struct spi_device *spi) +{ + struct ad714x_chip *chip = spi_get_drvdata(spi); + + ad714x_remove(chip); + spi_set_drvdata(spi, NULL); + + return 0; +} + +static struct spi_driver ad714x_spi_driver = { + .driver = { + .name = "ad714x_captouch", + .owner = THIS_MODULE, + }, + .probe = ad714x_spi_probe, + .remove = __devexit_p(ad714x_spi_remove), + .suspend = ad714x_spi_suspend, + .resume = ad714x_spi_resume, +}; + +static __init int ad714x_spi_init(void) +{ + return spi_register_driver(&ad714x_spi_driver); +} +module_init(ad714x_spi_init); + +static __exit void ad714x_spi_exit(void) +{ + spi_unregister_driver(&ad714x_spi_driver); +} +module_exit(ad714x_spi_exit); + +MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c new file mode 100644 index 00000000000..691b1d37331 --- /dev/null +++ b/drivers/input/misc/ad714x.c @@ -0,0 +1,1331 @@ +/* + * AD714X CapTouch Programmable Controller driver + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include "ad714x.h" + +#define AD714X_PWR_CTRL 0x0 +#define AD714X_STG_CAL_EN_REG 0x1 +#define AD714X_AMB_COMP_CTRL0_REG 0x2 +#define AD714X_PARTID_REG 0x17 +#define AD7147_PARTID 0x1470 +#define AD7142_PARTID 0xE620 +#define AD714X_STAGECFG_REG 0x80 +#define AD714X_SYSCFG_REG 0x0 + +#define STG_LOW_INT_EN_REG 0x5 +#define STG_HIGH_INT_EN_REG 0x6 +#define STG_COM_INT_EN_REG 0x7 +#define STG_LOW_INT_STA_REG 0x8 +#define STG_HIGH_INT_STA_REG 0x9 +#define STG_COM_INT_STA_REG 0xA + +#define CDC_RESULT_S0 0xB +#define CDC_RESULT_S1 0xC +#define CDC_RESULT_S2 0xD +#define CDC_RESULT_S3 0xE +#define CDC_RESULT_S4 0xF +#define CDC_RESULT_S5 0x10 +#define CDC_RESULT_S6 0x11 +#define CDC_RESULT_S7 0x12 +#define CDC_RESULT_S8 0x13 +#define CDC_RESULT_S9 0x14 +#define CDC_RESULT_S10 0x15 +#define CDC_RESULT_S11 0x16 + +#define STAGE0_AMBIENT 0xF1 +#define STAGE1_AMBIENT 0x115 +#define STAGE2_AMBIENT 0x139 +#define STAGE3_AMBIENT 0x15D +#define STAGE4_AMBIENT 0x181 +#define STAGE5_AMBIENT 0x1A5 +#define STAGE6_AMBIENT 0x1C9 +#define STAGE7_AMBIENT 0x1ED +#define STAGE8_AMBIENT 0x211 +#define STAGE9_AMBIENT 0x234 +#define STAGE10_AMBIENT 0x259 +#define STAGE11_AMBIENT 0x27D + +#define PER_STAGE_REG_NUM 36 +#define STAGE_NUM 12 +#define STAGE_CFGREG_NUM 8 +#define SYS_CFGREG_NUM 8 + +/* + * driver information which will be used to maintain the software flow + */ +enum ad714x_device_state { IDLE, JITTER, ACTIVE, SPACE }; + +struct ad714x_slider_drv { + int highest_stage; + int abs_pos; + int flt_pos; + enum ad714x_device_state state; + struct input_dev *input; +}; + +struct ad714x_wheel_drv { + int abs_pos; + int flt_pos; + int pre_mean_value; + int pre_highest_stage; + int pre_mean_value_no_offset; + int mean_value; + int mean_value_no_offset; + int pos_offset; + int pos_ratio; + int highest_stage; + enum ad714x_device_state state; + struct input_dev *input; +}; + +struct ad714x_touchpad_drv { + int x_highest_stage; + int x_flt_pos; + int x_abs_pos; + int y_highest_stage; + int y_flt_pos; + int y_abs_pos; + int left_ep; + int left_ep_val; + int right_ep; + int right_ep_val; + int top_ep; + int top_ep_val; + int bottom_ep; + int bottom_ep_val; + enum ad714x_device_state state; + struct input_dev *input; +}; + +struct ad714x_button_drv { + enum ad714x_device_state state; + /* + * Unlike slider/wheel/touchpad, all buttons point to + * same input_dev instance + */ + struct input_dev *input; +}; + +struct ad714x_driver_data { + struct ad714x_slider_drv *slider; + struct ad714x_wheel_drv *wheel; + struct ad714x_touchpad_drv *touchpad; + struct ad714x_button_drv *button; +}; + +/* + * information to integrate all things which will be private data + * of spi/i2c device + */ +struct ad714x_chip { + unsigned short h_state; + unsigned short l_state; + unsigned short c_state; + unsigned short adc_reg[STAGE_NUM]; + unsigned short amb_reg[STAGE_NUM]; + unsigned short sensor_val[STAGE_NUM]; + + struct ad714x_platform_data *hw; + struct ad714x_driver_data *sw; + + int irq; + struct device *dev; + ad714x_read_t read; + ad714x_write_t write; + + struct mutex mutex; + + unsigned product; + unsigned version; +}; + +static void ad714x_use_com_int(struct ad714x_chip *ad714x, + int start_stage, int end_stage) +{ + unsigned short data; + unsigned short mask; + + mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage); + + ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); + data |= 1 << start_stage; + ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); + + ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); + data &= ~mask; + ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); +} + +static void ad714x_use_thr_int(struct ad714x_chip *ad714x, + int start_stage, int end_stage) +{ + unsigned short data; + unsigned short mask; + + mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage); + + ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); + data &= ~(1 << start_stage); + ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); + + ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); + data |= mask; + ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); +} + +static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x, + int start_stage, int end_stage) +{ + int max_res = 0; + int max_idx = 0; + int i; + + for (i = start_stage; i <= end_stage; i++) { + if (ad714x->sensor_val[i] > max_res) { + max_res = ad714x->sensor_val[i]; + max_idx = i; + } + } + + return max_idx; +} + +static int ad714x_cal_abs_pos(struct ad714x_chip *ad714x, + int start_stage, int end_stage, + int highest_stage, int max_coord) +{ + int a_param, b_param; + + if (highest_stage == start_stage) { + a_param = ad714x->sensor_val[start_stage + 1]; + b_param = ad714x->sensor_val[start_stage] + + ad714x->sensor_val[start_stage + 1]; + } else if (highest_stage == end_stage) { + a_param = ad714x->sensor_val[end_stage] * + (end_stage - start_stage) + + ad714x->sensor_val[end_stage - 1] * + (end_stage - start_stage - 1); + b_param = ad714x->sensor_val[end_stage] + + ad714x->sensor_val[end_stage - 1]; + } else { + a_param = ad714x->sensor_val[highest_stage] * + (highest_stage - start_stage) + + ad714x->sensor_val[highest_stage - 1] * + (highest_stage - start_stage - 1) + + ad714x->sensor_val[highest_stage + 1] * + (highest_stage - start_stage + 1); + b_param = ad714x->sensor_val[highest_stage] + + ad714x->sensor_val[highest_stage - 1] + + ad714x->sensor_val[highest_stage + 1]; + } + + return (max_coord / (end_stage - start_stage)) * a_param / b_param; +} + +/* + * One button can connect to multi positive and negative of CDCs + * Multi-buttons can connect to same positive/negative of one CDC + */ +static void ad714x_button_state_machine(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_button_plat *hw = &ad714x->hw->button[idx]; + struct ad714x_button_drv *sw = &ad714x->sw->button[idx]; + + switch (sw->state) { + case IDLE: + if (((ad714x->h_state & hw->h_mask) == hw->h_mask) && + ((ad714x->l_state & hw->l_mask) == hw->l_mask)) { + dev_dbg(ad714x->dev, "button %d touched\n", idx); + input_report_key(sw->input, hw->keycode, 1); + input_sync(sw->input); + sw->state = ACTIVE; + } + break; + + case ACTIVE: + if (((ad714x->h_state & hw->h_mask) != hw->h_mask) || + ((ad714x->l_state & hw->l_mask) != hw->l_mask)) { + dev_dbg(ad714x->dev, "button %d released\n", idx); + input_report_key(sw->input, hw->keycode, 0); + input_sync(sw->input); + sw->state = IDLE; + } + break; + + default: + break; + } +} + +/* + * The response of a sensor is defined by the absolute number of codes + * between the current CDC value and the ambient value. + */ +static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + int i; + + for (i = hw->start_stage; i <= hw->end_stage; i++) { + ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, + &ad714x->adc_reg[i]); + ad714x->read(ad714x->dev, + STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, + &ad714x->amb_reg[i]); + + ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] - + ad714x->amb_reg[i]); + } +} + +static void ad714x_slider_cal_highest_stage(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; + + sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage, + hw->end_stage); + + dev_dbg(ad714x->dev, "slider %d highest_stage:%d\n", idx, + sw->highest_stage); +} + +/* + * The formulae are very straight forward. It uses the sensor with the + * highest response and the 2 adjacent ones. + * When Sensor 0 has the highest response, only sensor 0 and sensor 1 + * are used in the calculations. Similarly when the last sensor has the + * highest response, only the last sensor and the second last sensors + * are used in the calculations. + * + * For i= idx_of_peak_Sensor-1 to i= idx_of_peak_Sensor+1 + * v += Sensor response(i)*i + * w += Sensor response(i) + * POS=(Number_of_Positions_Wanted/(Number_of_Sensors_Used-1)) *(v/w) + */ +static void ad714x_slider_cal_abs_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; + + sw->abs_pos = ad714x_cal_abs_pos(ad714x, hw->start_stage, hw->end_stage, + sw->highest_stage, hw->max_coord); + + dev_dbg(ad714x->dev, "slider %d absolute position:%d\n", idx, + sw->abs_pos); +} + +/* + * To minimise the Impact of the noise on the algorithm, ADI developed a + * routine that filters the CDC results after they have been read by the + * host processor. + * The filter used is an Infinite Input Response(IIR) filter implemented + * in firmware and attenuates the noise on the CDC results after they've + * been read by the host processor. + * Filtered_CDC_result = (Filtered_CDC_result * (10 - Coefficient) + + * Latest_CDC_result * Coefficient)/10 + */ +static void ad714x_slider_cal_flt_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; + + sw->flt_pos = (sw->flt_pos * (10 - 4) + + sw->abs_pos * 4)/10; + + dev_dbg(ad714x->dev, "slider %d filter position:%d\n", idx, + sw->flt_pos); +} + +static void ad714x_slider_use_com_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + + ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage); +} + +static void ad714x_slider_use_thr_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + + ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage); +} + +static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; + struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; + unsigned short h_state, c_state; + unsigned short mask; + + mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1); + + h_state = ad714x->h_state & mask; + c_state = ad714x->c_state & mask; + + switch (sw->state) { + case IDLE: + if (h_state) { + sw->state = JITTER; + /* In End of Conversion interrupt mode, the AD714X + * continuously generates hardware interrupts. + */ + ad714x_slider_use_com_int(ad714x, idx); + dev_dbg(ad714x->dev, "slider %d touched\n", idx); + } + break; + + case JITTER: + if (c_state == mask) { + ad714x_slider_cal_sensor_val(ad714x, idx); + ad714x_slider_cal_highest_stage(ad714x, idx); + ad714x_slider_cal_abs_pos(ad714x, idx); + sw->flt_pos = sw->abs_pos; + sw->state = ACTIVE; + } + break; + + case ACTIVE: + if (c_state == mask) { + if (h_state) { + ad714x_slider_cal_sensor_val(ad714x, idx); + ad714x_slider_cal_highest_stage(ad714x, idx); + ad714x_slider_cal_abs_pos(ad714x, idx); + ad714x_slider_cal_flt_pos(ad714x, idx); + + input_report_abs(sw->input, ABS_X, sw->flt_pos); + input_report_key(sw->input, BTN_TOUCH, 1); + } else { + /* When the user lifts off the sensor, configure + * the AD714X back to threshold interrupt mode. + */ + ad714x_slider_use_thr_int(ad714x, idx); + sw->state = IDLE; + input_report_key(sw->input, BTN_TOUCH, 0); + dev_dbg(ad714x->dev, "slider %d released\n", + idx); + } + input_sync(sw->input); + } + break; + + default: + break; + } +} + +/* + * When the scroll wheel is activated, we compute the absolute position based + * on the sensor values. To calculate the position, we first determine the + * sensor that has the greatest response among the 8 sensors that constitutes + * the scrollwheel. Then we determined the 2 sensors on either sides of the + * sensor with the highest response and we apply weights to these sensors. + */ +static void ad714x_wheel_cal_highest_stage(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; + + sw->pre_highest_stage = sw->highest_stage; + sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage, + hw->end_stage); + + dev_dbg(ad714x->dev, "wheel %d highest_stage:%d\n", idx, + sw->highest_stage); +} + +static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + int i; + + for (i = hw->start_stage; i <= hw->end_stage; i++) { + ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, + &ad714x->adc_reg[i]); + ad714x->read(ad714x->dev, + STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, + &ad714x->amb_reg[i]); + if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) + ad714x->sensor_val[i] = ad714x->adc_reg[i] - + ad714x->amb_reg[i]; + else + ad714x->sensor_val[i] = 0; + } +} + +/* + * When the scroll wheel is activated, we compute the absolute position based + * on the sensor values. To calculate the position, we first determine the + * sensor that has the greatest response among the 8 sensors that constitutes + * the scrollwheel. Then we determined the 2 sensors on either sides of the + * sensor with the highest response and we apply weights to these sensors. The + * result of this computation gives us the mean value which defined by the + * following formula: + * For i= second_before_highest_stage to i= second_after_highest_stage + * v += Sensor response(i)*WEIGHT*(i+3) + * w += Sensor response(i) + * Mean_Value=v/w + * pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio + */ + +#define WEIGHT_FACTOR 30 +/* This constant prevents the "PositionOffset" from reaching a big value */ +#define OFFSET_POSITION_CLAMP 120 +static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; + int stage_num = hw->end_stage - hw->start_stage + 1; + int second_before, first_before, highest, first_after, second_after; + int a_param, b_param; + + /* Calculate Mean value */ + + second_before = (sw->highest_stage + stage_num - 2) % stage_num; + first_before = (sw->highest_stage + stage_num - 1) % stage_num; + highest = sw->highest_stage; + first_after = (sw->highest_stage + stage_num + 1) % stage_num; + second_after = (sw->highest_stage + stage_num + 2) % stage_num; + + if (((sw->highest_stage - hw->start_stage) > 1) && + ((hw->end_stage - sw->highest_stage) > 1)) { + a_param = ad714x->sensor_val[second_before] * + (second_before - hw->start_stage + 3) + + ad714x->sensor_val[first_before] * + (second_before - hw->start_stage + 3) + + ad714x->sensor_val[highest] * + (second_before - hw->start_stage + 3) + + ad714x->sensor_val[first_after] * + (first_after - hw->start_stage + 3) + + ad714x->sensor_val[second_after] * + (second_after - hw->start_stage + 3); + } else { + a_param = ad714x->sensor_val[second_before] * + (second_before - hw->start_stage + 1) + + ad714x->sensor_val[first_before] * + (second_before - hw->start_stage + 2) + + ad714x->sensor_val[highest] * + (second_before - hw->start_stage + 3) + + ad714x->sensor_val[first_after] * + (first_after - hw->start_stage + 4) + + ad714x->sensor_val[second_after] * + (second_after - hw->start_stage + 5); + } + a_param *= WEIGHT_FACTOR; + + b_param = ad714x->sensor_val[second_before] + + ad714x->sensor_val[first_before] + + ad714x->sensor_val[highest] + + ad714x->sensor_val[first_after] + + ad714x->sensor_val[second_after]; + + sw->pre_mean_value = sw->mean_value; + sw->mean_value = a_param / b_param; + + /* Calculate the offset */ + + if ((sw->pre_highest_stage == hw->end_stage) && + (sw->highest_stage == hw->start_stage)) + sw->pos_offset = sw->mean_value; + else if ((sw->pre_highest_stage == hw->start_stage) && + (sw->highest_stage == hw->end_stage)) + sw->pos_offset = sw->pre_mean_value; + + if (sw->pos_offset > OFFSET_POSITION_CLAMP) + sw->pos_offset = OFFSET_POSITION_CLAMP; + + /* Calculate the mean value without the offset */ + + sw->pre_mean_value_no_offset = sw->mean_value_no_offset; + sw->mean_value_no_offset = sw->mean_value - sw->pos_offset; + if (sw->mean_value_no_offset < 0) + sw->mean_value_no_offset = 0; + + /* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */ + + if ((sw->pre_highest_stage == hw->end_stage) && + (sw->highest_stage == hw->start_stage)) + sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) / + hw->max_coord; + else if ((sw->pre_highest_stage == hw->start_stage) && + (sw->highest_stage == hw->end_stage)) + sw->pos_ratio = (sw->mean_value_no_offset * 100) / + hw->max_coord; + sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio; + if (sw->abs_pos > hw->max_coord) + sw->abs_pos = hw->max_coord; +} + +static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; + if (((sw->pre_highest_stage == hw->end_stage) && + (sw->highest_stage == hw->start_stage)) || + ((sw->pre_highest_stage == hw->start_stage) && + (sw->highest_stage == hw->end_stage))) + sw->flt_pos = sw->abs_pos; + else + sw->flt_pos = ((sw->flt_pos * 30) + (sw->abs_pos * 71)) / 100; + + if (sw->flt_pos > hw->max_coord) + sw->flt_pos = hw->max_coord; +} + +static void ad714x_wheel_use_com_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + + ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage); +} + +static void ad714x_wheel_use_thr_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + + ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage); +} + +static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; + struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; + unsigned short h_state, c_state; + unsigned short mask; + + mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1); + + h_state = ad714x->h_state & mask; + c_state = ad714x->c_state & mask; + + switch (sw->state) { + case IDLE: + if (h_state) { + sw->state = JITTER; + /* In End of Conversion interrupt mode, the AD714X + * continuously generates hardware interrupts. + */ + ad714x_wheel_use_com_int(ad714x, idx); + dev_dbg(ad714x->dev, "wheel %d touched\n", idx); + } + break; + + case JITTER: + if (c_state == mask) { + ad714x_wheel_cal_sensor_val(ad714x, idx); + ad714x_wheel_cal_highest_stage(ad714x, idx); + ad714x_wheel_cal_abs_pos(ad714x, idx); + sw->flt_pos = sw->abs_pos; + sw->state = ACTIVE; + } + break; + + case ACTIVE: + if (c_state == mask) { + if (h_state) { + ad714x_wheel_cal_sensor_val(ad714x, idx); + ad714x_wheel_cal_highest_stage(ad714x, idx); + ad714x_wheel_cal_abs_pos(ad714x, idx); + ad714x_wheel_cal_flt_pos(ad714x, idx); + + input_report_abs(sw->input, ABS_WHEEL, + sw->abs_pos); + input_report_key(sw->input, BTN_TOUCH, 1); + } else { + /* When the user lifts off the sensor, configure + * the AD714X back to threshold interrupt mode. + */ + ad714x_wheel_use_thr_int(ad714x, idx); + sw->state = IDLE; + input_report_key(sw->input, BTN_TOUCH, 0); + + dev_dbg(ad714x->dev, "wheel %d released\n", + idx); + } + input_sync(sw->input); + } + break; + + default: + break; + } +} + +static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + int i; + + for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) { + ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, + &ad714x->adc_reg[i]); + ad714x->read(ad714x->dev, + STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, + &ad714x->amb_reg[i]); + if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) + ad714x->sensor_val[i] = ad714x->adc_reg[i] - + ad714x->amb_reg[i]; + else + ad714x->sensor_val[i] = 0; + } +} + +static void touchpad_cal_highest_stage(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + + sw->x_highest_stage = ad714x_cal_highest_stage(ad714x, + hw->x_start_stage, hw->x_end_stage); + sw->y_highest_stage = ad714x_cal_highest_stage(ad714x, + hw->y_start_stage, hw->y_end_stage); + + dev_dbg(ad714x->dev, + "touchpad %d x_highest_stage:%d, y_highest_stage:%d\n", + idx, sw->x_highest_stage, sw->y_highest_stage); +} + +/* + * If 2 fingers are touching the sensor then 2 peaks can be observed in the + * distribution. + * The arithmetic doesn't support to get absolute coordinates for multi-touch + * yet. + */ +static int touchpad_check_second_peak(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + int i; + + for (i = hw->x_start_stage; i < sw->x_highest_stage; i++) { + if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1]) + > (ad714x->sensor_val[i + 1] / 10)) + return 1; + } + + for (i = sw->x_highest_stage; i < hw->x_end_stage; i++) { + if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i]) + > (ad714x->sensor_val[i] / 10)) + return 1; + } + + for (i = hw->y_start_stage; i < sw->y_highest_stage; i++) { + if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1]) + > (ad714x->sensor_val[i + 1] / 10)) + return 1; + } + + for (i = sw->y_highest_stage; i < hw->y_end_stage; i++) { + if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i]) + > (ad714x->sensor_val[i] / 10)) + return 1; + } + + return 0; +} + +/* + * If only one finger is used to activate the touch pad then only 1 peak will be + * registered in the distribution. This peak and the 2 adjacent sensors will be + * used in the calculation of the absolute position. This will prevent hand + * shadows to affect the absolute position calculation. + */ +static void touchpad_cal_abs_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + + sw->x_abs_pos = ad714x_cal_abs_pos(ad714x, hw->x_start_stage, + hw->x_end_stage, sw->x_highest_stage, hw->x_max_coord); + sw->y_abs_pos = ad714x_cal_abs_pos(ad714x, hw->y_start_stage, + hw->y_end_stage, sw->y_highest_stage, hw->y_max_coord); + + dev_dbg(ad714x->dev, "touchpad %d absolute position:(%d, %d)\n", idx, + sw->x_abs_pos, sw->y_abs_pos); +} + +static void touchpad_cal_flt_pos(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + + sw->x_flt_pos = (sw->x_flt_pos * (10 - 4) + + sw->x_abs_pos * 4)/10; + sw->y_flt_pos = (sw->y_flt_pos * (10 - 4) + + sw->y_abs_pos * 4)/10; + + dev_dbg(ad714x->dev, "touchpad %d filter position:(%d, %d)\n", + idx, sw->x_flt_pos, sw->y_flt_pos); +} + +/* + * To prevent distortion from showing in the absolute position, it is + * necessary to detect the end points. When endpoints are detected, the + * driver stops updating the status variables with absolute positions. + * End points are detected on the 4 edges of the touchpad sensor. The + * method to detect them is the same for all 4. + * To detect the end points, the firmware computes the difference in + * percent between the sensor on the edge and the adjacent one. The + * difference is calculated in percent in order to make the end point + * detection independent of the pressure. + */ + +#define LEFT_END_POINT_DETECTION_LEVEL 550 +#define RIGHT_END_POINT_DETECTION_LEVEL 750 +#define LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL 850 +#define TOP_END_POINT_DETECTION_LEVEL 550 +#define BOTTOM_END_POINT_DETECTION_LEVEL 950 +#define TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL 700 +static int touchpad_check_endpoint(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + int percent_sensor_diff; + + /* left endpoint detect */ + percent_sensor_diff = (ad714x->sensor_val[hw->x_start_stage] - + ad714x->sensor_val[hw->x_start_stage + 1]) * 100 / + ad714x->sensor_val[hw->x_start_stage + 1]; + if (!sw->left_ep) { + if (percent_sensor_diff >= LEFT_END_POINT_DETECTION_LEVEL) { + sw->left_ep = 1; + sw->left_ep_val = + ad714x->sensor_val[hw->x_start_stage + 1]; + } + } else { + if ((percent_sensor_diff < LEFT_END_POINT_DETECTION_LEVEL) && + (ad714x->sensor_val[hw->x_start_stage + 1] > + LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->left_ep_val)) + sw->left_ep = 0; + } + + /* right endpoint detect */ + percent_sensor_diff = (ad714x->sensor_val[hw->x_end_stage] - + ad714x->sensor_val[hw->x_end_stage - 1]) * 100 / + ad714x->sensor_val[hw->x_end_stage - 1]; + if (!sw->right_ep) { + if (percent_sensor_diff >= RIGHT_END_POINT_DETECTION_LEVEL) { + sw->right_ep = 1; + sw->right_ep_val = + ad714x->sensor_val[hw->x_end_stage - 1]; + } + } else { + if ((percent_sensor_diff < RIGHT_END_POINT_DETECTION_LEVEL) && + (ad714x->sensor_val[hw->x_end_stage - 1] > + LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->right_ep_val)) + sw->right_ep = 0; + } + + /* top endpoint detect */ + percent_sensor_diff = (ad714x->sensor_val[hw->y_start_stage] - + ad714x->sensor_val[hw->y_start_stage + 1]) * 100 / + ad714x->sensor_val[hw->y_start_stage + 1]; + if (!sw->top_ep) { + if (percent_sensor_diff >= TOP_END_POINT_DETECTION_LEVEL) { + sw->top_ep = 1; + sw->top_ep_val = + ad714x->sensor_val[hw->y_start_stage + 1]; + } + } else { + if ((percent_sensor_diff < TOP_END_POINT_DETECTION_LEVEL) && + (ad714x->sensor_val[hw->y_start_stage + 1] > + TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->top_ep_val)) + sw->top_ep = 0; + } + + /* bottom endpoint detect */ + percent_sensor_diff = (ad714x->sensor_val[hw->y_end_stage] - + ad714x->sensor_val[hw->y_end_stage - 1]) * 100 / + ad714x->sensor_val[hw->y_end_stage - 1]; + if (!sw->bottom_ep) { + if (percent_sensor_diff >= BOTTOM_END_POINT_DETECTION_LEVEL) { + sw->bottom_ep = 1; + sw->bottom_ep_val = + ad714x->sensor_val[hw->y_end_stage - 1]; + } + } else { + if ((percent_sensor_diff < BOTTOM_END_POINT_DETECTION_LEVEL) && + (ad714x->sensor_val[hw->y_end_stage - 1] > + TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->bottom_ep_val)) + sw->bottom_ep = 0; + } + + return sw->left_ep || sw->right_ep || sw->top_ep || sw->bottom_ep; +} + +static void touchpad_use_com_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + + ad714x_use_com_int(ad714x, hw->x_start_stage, hw->x_end_stage); +} + +static void touchpad_use_thr_int(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + + ad714x_use_thr_int(ad714x, hw->x_start_stage, hw->x_end_stage); + ad714x_use_thr_int(ad714x, hw->y_start_stage, hw->y_end_stage); +} + +static void ad714x_touchpad_state_machine(struct ad714x_chip *ad714x, int idx) +{ + struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; + struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; + unsigned short h_state, c_state; + unsigned short mask; + + mask = (((1 << (hw->x_end_stage + 1)) - 1) - + ((1 << hw->x_start_stage) - 1)) + + (((1 << (hw->y_end_stage + 1)) - 1) - + ((1 << hw->y_start_stage) - 1)); + + h_state = ad714x->h_state & mask; + c_state = ad714x->c_state & mask; + + switch (sw->state) { + case IDLE: + if (h_state) { + sw->state = JITTER; + /* In End of Conversion interrupt mode, the AD714X + * continuously generates hardware interrupts. + */ + touchpad_use_com_int(ad714x, idx); + dev_dbg(ad714x->dev, "touchpad %d touched\n", idx); + } + break; + + case JITTER: + if (c_state == mask) { + touchpad_cal_sensor_val(ad714x, idx); + touchpad_cal_highest_stage(ad714x, idx); + if ((!touchpad_check_second_peak(ad714x, idx)) && + (!touchpad_check_endpoint(ad714x, idx))) { + dev_dbg(ad714x->dev, + "touchpad%d, 2 fingers or endpoint\n", + idx); + touchpad_cal_abs_pos(ad714x, idx); + sw->x_flt_pos = sw->x_abs_pos; + sw->y_flt_pos = sw->y_abs_pos; + sw->state = ACTIVE; + } + } + break; + + case ACTIVE: + if (c_state == mask) { + if (h_state) { + touchpad_cal_sensor_val(ad714x, idx); + touchpad_cal_highest_stage(ad714x, idx); + if ((!touchpad_check_second_peak(ad714x, idx)) + && (!touchpad_check_endpoint(ad714x, idx))) { + touchpad_cal_abs_pos(ad714x, idx); + touchpad_cal_flt_pos(ad714x, idx); + input_report_abs(sw->input, ABS_X, + sw->x_flt_pos); + input_report_abs(sw->input, ABS_Y, + sw->y_flt_pos); + input_report_key(sw->input, BTN_TOUCH, + 1); + } + } else { + /* When the user lifts off the sensor, configure + * the AD714X back to threshold interrupt mode. + */ + touchpad_use_thr_int(ad714x, idx); + sw->state = IDLE; + input_report_key(sw->input, BTN_TOUCH, 0); + dev_dbg(ad714x->dev, "touchpad %d released\n", + idx); + } + input_sync(sw->input); + } + break; + + default: + break; + } +} + +static int ad714x_hw_detect(struct ad714x_chip *ad714x) +{ + unsigned short data; + + ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data); + switch (data & 0xFFF0) { + case AD7147_PARTID: + ad714x->product = 0x7147; + ad714x->version = data & 0xF; + dev_info(ad714x->dev, "found AD7147 captouch, rev:%d\n", + ad714x->version); + return 0; + + case AD7142_PARTID: + ad714x->product = 0x7142; + ad714x->version = data & 0xF; + dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n", + ad714x->version); + return 0; + + default: + dev_err(ad714x->dev, + "fail to detect AD714X captouch, read ID is %04x\n", + data); + return -ENODEV; + } +} + +static void ad714x_hw_init(struct ad714x_chip *ad714x) +{ + int i, j; + unsigned short reg_base; + unsigned short data; + + /* configuration CDC and interrupts */ + + for (i = 0; i < STAGE_NUM; i++) { + reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM; + for (j = 0; j < STAGE_CFGREG_NUM; j++) + ad714x->write(ad714x->dev, reg_base + j, + ad714x->hw->stage_cfg_reg[i][j]); + } + + for (i = 0; i < SYS_CFGREG_NUM; i++) + ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i, + ad714x->hw->sys_cfg_reg[i]); + for (i = 0; i < SYS_CFGREG_NUM; i++) + ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i, + &data); + + ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF); + + /* clear all interrupts */ + ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); + ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); + ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); +} + +static irqreturn_t ad714x_interrupt_thread(int irq, void *data) +{ + struct ad714x_chip *ad714x = data; + int i; + + mutex_lock(&ad714x->mutex); + + ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state); + ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state); + ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state); + + for (i = 0; i < ad714x->hw->button_num; i++) + ad714x_button_state_machine(ad714x, i); + for (i = 0; i < ad714x->hw->slider_num; i++) + ad714x_slider_state_machine(ad714x, i); + for (i = 0; i < ad714x->hw->wheel_num; i++) + ad714x_wheel_state_machine(ad714x, i); + for (i = 0; i < ad714x->hw->touchpad_num; i++) + ad714x_touchpad_state_machine(ad714x, i); + + mutex_unlock(&ad714x->mutex); + + return IRQ_HANDLED; +} + +#define MAX_DEVICE_NUM 8 +struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, + ad714x_read_t read, ad714x_write_t write) +{ + int i, alloc_idx; + int error; + struct input_dev *input[MAX_DEVICE_NUM]; + + struct ad714x_platform_data *plat_data = dev->platform_data; + struct ad714x_chip *ad714x; + void *drv_mem; + + struct ad714x_button_drv *bt_drv; + struct ad714x_slider_drv *sd_drv; + struct ad714x_wheel_drv *wl_drv; + struct ad714x_touchpad_drv *tp_drv; + + + if (irq <= 0) { + dev_err(dev, "IRQ not configured!\n"); + error = -EINVAL; + goto err_out; + } + + if (dev->platform_data == NULL) { + dev_err(dev, "platform data for ad714x doesn't exist\n"); + error = -EINVAL; + goto err_out; + } + + ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) + + sizeof(*sd_drv) * plat_data->slider_num + + sizeof(*wl_drv) * plat_data->wheel_num + + sizeof(*tp_drv) * plat_data->touchpad_num + + sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL); + if (!ad714x) { + error = -ENOMEM; + goto err_out; + } + + ad714x->hw = plat_data; + + drv_mem = ad714x + 1; + ad714x->sw = drv_mem; + drv_mem += sizeof(*ad714x->sw); + ad714x->sw->slider = sd_drv = drv_mem; + drv_mem += sizeof(*sd_drv) * ad714x->hw->slider_num; + ad714x->sw->wheel = wl_drv = drv_mem; + drv_mem += sizeof(*wl_drv) * ad714x->hw->wheel_num; + ad714x->sw->touchpad = tp_drv = drv_mem; + drv_mem += sizeof(*tp_drv) * ad714x->hw->touchpad_num; + ad714x->sw->button = bt_drv = drv_mem; + drv_mem += sizeof(*bt_drv) * ad714x->hw->button_num; + + ad714x->read = read; + ad714x->write = write; + ad714x->irq = irq; + ad714x->dev = dev; + + error = ad714x_hw_detect(ad714x); + if (error) + goto err_free_mem; + + /* initilize and request sw/hw resources */ + + ad714x_hw_init(ad714x); + mutex_init(&ad714x->mutex); + + /* + * Allocate and register AD714X input device + */ + alloc_idx = 0; + + /* a slider uses one input_dev instance */ + if (ad714x->hw->slider_num > 0) { + struct ad714x_slider_plat *sd_plat = ad714x->hw->slider; + + for (i = 0; i < ad714x->hw->slider_num; i++) { + sd_drv[i].input = input[alloc_idx] = input_allocate_device(); + if (!input[alloc_idx]) { + error = -ENOMEM; + goto err_free_dev; + } + + __set_bit(EV_ABS, input[alloc_idx]->evbit); + __set_bit(EV_KEY, input[alloc_idx]->evbit); + __set_bit(ABS_X, input[alloc_idx]->absbit); + __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); + input_set_abs_params(input[alloc_idx], + ABS_X, 0, sd_plat->max_coord, 0, 0); + + input[alloc_idx]->id.bustype = bus_type; + input[alloc_idx]->id.product = ad714x->product; + input[alloc_idx]->id.version = ad714x->version; + + error = input_register_device(input[alloc_idx]); + if (error) + goto err_free_dev; + + alloc_idx++; + } + } + + /* a wheel uses one input_dev instance */ + if (ad714x->hw->wheel_num > 0) { + struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel; + + for (i = 0; i < ad714x->hw->wheel_num; i++) { + wl_drv[i].input = input[alloc_idx] = input_allocate_device(); + if (!input[alloc_idx]) { + error = -ENOMEM; + goto err_free_dev; + } + + __set_bit(EV_KEY, input[alloc_idx]->evbit); + __set_bit(EV_ABS, input[alloc_idx]->evbit); + __set_bit(ABS_WHEEL, input[alloc_idx]->absbit); + __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); + input_set_abs_params(input[alloc_idx], + ABS_WHEEL, 0, wl_plat->max_coord, 0, 0); + + input[alloc_idx]->id.bustype = bus_type; + input[alloc_idx]->id.product = ad714x->product; + input[alloc_idx]->id.version = ad714x->version; + + error = input_register_device(input[alloc_idx]); + if (error) + goto err_free_dev; + + alloc_idx++; + } + } + + /* a touchpad uses one input_dev instance */ + if (ad714x->hw->touchpad_num > 0) { + struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad; + + for (i = 0; i < ad714x->hw->touchpad_num; i++) { + tp_drv[i].input = input[alloc_idx] = input_allocate_device(); + if (!input[alloc_idx]) { + error = -ENOMEM; + goto err_free_dev; + } + + __set_bit(EV_ABS, input[alloc_idx]->evbit); + __set_bit(EV_KEY, input[alloc_idx]->evbit); + __set_bit(ABS_X, input[alloc_idx]->absbit); + __set_bit(ABS_Y, input[alloc_idx]->absbit); + __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); + input_set_abs_params(input[alloc_idx], + ABS_X, 0, tp_plat->x_max_coord, 0, 0); + input_set_abs_params(input[alloc_idx], + ABS_Y, 0, tp_plat->y_max_coord, 0, 0); + + input[alloc_idx]->id.bustype = bus_type; + input[alloc_idx]->id.product = ad714x->product; + input[alloc_idx]->id.version = ad714x->version; + + error = input_register_device(input[alloc_idx]); + if (error) + goto err_free_dev; + + alloc_idx++; + } + } + + /* all buttons use one input node */ + if (ad714x->hw->button_num > 0) { + struct ad714x_button_plat *bt_plat = ad714x->hw->button; + + input[alloc_idx] = input_allocate_device(); + if (!input[alloc_idx]) { + error = -ENOMEM; + goto err_free_dev; + } + + __set_bit(EV_KEY, input[alloc_idx]->evbit); + for (i = 0; i < ad714x->hw->button_num; i++) { + bt_drv[i].input = input[alloc_idx]; + __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit); + } + + input[alloc_idx]->id.bustype = bus_type; + input[alloc_idx]->id.product = ad714x->product; + input[alloc_idx]->id.version = ad714x->version; + + error = input_register_device(input[alloc_idx]); + if (error) + goto err_free_dev; + + alloc_idx++; + } + + error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread, + IRQF_TRIGGER_FALLING, "ad714x_captouch", ad714x); + if (error) { + dev_err(dev, "can't allocate irq %d\n", ad714x->irq); + goto err_unreg_dev; + } + + return ad714x; + + err_free_dev: + dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx); + input_free_device(input[alloc_idx]); + err_unreg_dev: + while (--alloc_idx >= 0) + input_unregister_device(input[alloc_idx]); + err_free_mem: + kfree(ad714x); + err_out: + return ERR_PTR(error); +} +EXPORT_SYMBOL(ad714x_probe); + +void ad714x_remove(struct ad714x_chip *ad714x) +{ + struct ad714x_platform_data *hw = ad714x->hw; + struct ad714x_driver_data *sw = ad714x->sw; + int i; + + free_irq(ad714x->irq, ad714x); + + /* unregister and free all input devices */ + + for (i = 0; i < hw->slider_num; i++) + input_unregister_device(sw->slider[i].input); + + for (i = 0; i < hw->wheel_num; i++) + input_unregister_device(sw->wheel[i].input); + + for (i = 0; i < hw->touchpad_num; i++) + input_unregister_device(sw->touchpad[i].input); + + if (hw->button_num) + input_unregister_device(sw->button[0].input); + + kfree(ad714x); +} +EXPORT_SYMBOL(ad714x_remove); + +#ifdef CONFIG_PM +int ad714x_disable(struct ad714x_chip *ad714x) +{ + unsigned short data; + + dev_dbg(ad714x->dev, "%s enter\n", __func__); + + mutex_lock(&ad714x->mutex); + + data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3; + ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data); + + mutex_unlock(&ad714x->mutex); + + return 0; +} +EXPORT_SYMBOL(ad714x_disable); + +int ad714x_enable(struct ad714x_chip *ad714x) +{ + unsigned short data; + + dev_dbg(ad714x->dev, "%s enter\n", __func__); + + mutex_lock(&ad714x->mutex); + + /* resume to non-shutdown mode */ + + ad714x->write(ad714x->dev, AD714X_PWR_CTRL, + ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]); + + /* make sure the interrupt output line is not low level after resume, + * otherwise we will get no chance to enter falling-edge irq again + */ + + ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); + ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); + ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); + + mutex_unlock(&ad714x->mutex); + + return 0; +} +EXPORT_SYMBOL(ad714x_enable); +#endif + +MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor Driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h new file mode 100644 index 00000000000..45c54fb13f0 --- /dev/null +++ b/drivers/input/misc/ad714x.h @@ -0,0 +1,26 @@ +/* + * AD714X CapTouch Programmable Controller driver (bus interfaces) + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef _AD714X_H_ +#define _AD714X_H_ + +#include + +struct device; +struct ad714x_chip; + +typedef int (*ad714x_read_t)(struct device *, unsigned short, unsigned short *); +typedef int (*ad714x_write_t)(struct device *, unsigned short, unsigned short); + +int ad714x_disable(struct ad714x_chip *ad714x); +int ad714x_enable(struct ad714x_chip *ad714x); +struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, + ad714x_read_t read, ad714x_write_t write); +void ad714x_remove(struct ad714x_chip *ad714x); + +#endif -- cgit v1.2.2 From 6c04d7b3cf50a393f07f22a661d05d15db5dc6f6 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Sun, 21 Mar 2010 23:23:29 -0700 Subject: Input: ad714x - add support for the AD7143/8/7A parts Signed-off-by: Barry Song Signed-off-by: Mike Frysinger Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 2 +- drivers/input/misc/ad714x-i2c.c | 3 +++ drivers/input/misc/ad714x.c | 28 ++++++++++++++++++++++------ 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index a4b9dc5cf45..48cdabec372 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -25,7 +25,7 @@ config INPUT_88PM860X_ONKEY config INPUT_AD714X tristate "Analog Devices AD714x Capacitance Touch Sensor" help - Say Y here if you want to support an AD7142/AD7147 touch sensor. + Say Y here if you want to support an AD7142/3/7/8/7A touch sensor. You should select a bus connection too. diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index a2cb6b426dc..e9adbe49f6a 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -104,7 +104,10 @@ static int __devexit ad714x_i2c_remove(struct i2c_client *client) static const struct i2c_device_id ad714x_id[] = { { "ad7142_captouch", 0 }, + { "ad7143_captouch", 0 }, { "ad7147_captouch", 0 }, + { "ad7147a_captouch", 0 }, + { "ad7148_captouch", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ad714x_id); diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 691b1d37331..0fe27baf5e7 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -1,5 +1,5 @@ /* - * AD714X CapTouch Programmable Controller driver + * AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A * * Copyright 2009 Analog Devices Inc. * @@ -18,8 +18,10 @@ #define AD714X_STG_CAL_EN_REG 0x1 #define AD714X_AMB_COMP_CTRL0_REG 0x2 #define AD714X_PARTID_REG 0x17 -#define AD7147_PARTID 0x1470 #define AD7142_PARTID 0xE620 +#define AD7143_PARTID 0xE630 +#define AD7147_PARTID 0x1470 +#define AD7148_PARTID 0x1480 #define AD714X_STAGECFG_REG 0x80 #define AD714X_SYSCFG_REG 0x0 @@ -962,17 +964,31 @@ static int ad714x_hw_detect(struct ad714x_chip *ad714x) ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data); switch (data & 0xFFF0) { + case AD7142_PARTID: + ad714x->product = 0x7142; + ad714x->version = data & 0xF; + dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n", + ad714x->version); + return 0; + + case AD7143_PARTID: + ad714x->product = 0x7143; + ad714x->version = data & 0xF; + dev_info(ad714x->dev, "found AD7143 captouch, rev:%d\n", + ad714x->version); + return 0; + case AD7147_PARTID: ad714x->product = 0x7147; ad714x->version = data & 0xF; - dev_info(ad714x->dev, "found AD7147 captouch, rev:%d\n", + dev_info(ad714x->dev, "found AD7147(A) captouch, rev:%d\n", ad714x->version); return 0; - case AD7142_PARTID: - ad714x->product = 0x7142; + case AD7148_PARTID: + ad714x->product = 0x7148; ad714x->version = data & 0xF; - dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n", + dev_info(ad714x->dev, "found AD7148 captouch, rev:%d\n", ad714x->version); return 0; -- cgit v1.2.2 From 422dee56b8155e4627f657ee67e962066ca7aff3 Mon Sep 17 00:00:00 2001 From: Adam Bennett Date: Mon, 12 Apr 2010 19:54:38 -0700 Subject: Input: add driver for hampshire serial touchscreens Adds support for Hampshire TSHARC serial touchscreens. Implements Hampshire's 4-byte communication protocol. Signed-off-by: Adam Bennett Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 12 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/hampshire.c | 205 ++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 drivers/input/touchscreen/hampshire.c (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 3d1ade2e519..cc471983ac0 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -119,6 +119,18 @@ config TOUCHSCREEN_DYNAPRO To compile this driver as a module, choose M here: the module will be called dynapro. +config TOUCHSCREEN_HAMPSHIRE + tristate "Hampshire serial touchscreen" + select SERIO + help + Say Y here if you have a Hampshire serial touchscreen connected to + your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called hampshire. + config TOUCHSCREEN_EETI tristate "EETI touchscreen panel support" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 41145d074de..8ad36eef90a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o +obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c new file mode 100644 index 00000000000..2da6cc31bb2 --- /dev/null +++ b/drivers/input/touchscreen/hampshire.c @@ -0,0 +1,205 @@ +/* + * Hampshire serial touchscreen driver + * + * Copyright (c) 2010 Adam Bennett + * Based on the dynapro driver (c) Tias Guns + * + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * 2010/04/08 Adam Bennett + * Copied dynapro.c and edited for Hampshire 4-byte protocol + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESC "Hampshire serial touchscreen driver" + +MODULE_AUTHOR("Adam Bennett "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* + * Definitions & global arrays. + */ + +#define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40 +#define HAMPSHIRE_FORMAT_LENGTH 4 +#define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80 + +#define HAMPSHIRE_MIN_XC 0 +#define HAMPSHIRE_MAX_XC 0x1000 +#define HAMPSHIRE_MIN_YC 0 +#define HAMPSHIRE_MAX_YC 0x1000 + +#define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6)) +#define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9)) +#define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0]) + +/* + * Per-touchscreen data. + */ + +struct hampshire { + struct input_dev *dev; + struct serio *serio; + int idx; + unsigned char data[HAMPSHIRE_FORMAT_LENGTH]; + char phys[32]; +}; + +static void hampshire_process_data(struct hampshire *phampshire) +{ + struct input_dev *dev = phampshire->dev; + + if (HAMPSHIRE_FORMAT_LENGTH == ++phampshire->idx) { + input_report_abs(dev, ABS_X, HAMPSHIRE_GET_XC(phampshire->data)); + input_report_abs(dev, ABS_Y, HAMPSHIRE_GET_YC(phampshire->data)); + input_report_key(dev, BTN_TOUCH, + HAMPSHIRE_GET_TOUCHED(phampshire->data)); + input_sync(dev); + + phampshire->idx = 0; + } +} + +static irqreturn_t hampshire_interrupt(struct serio *serio, + unsigned char data, unsigned int flags) +{ + struct hampshire *phampshire = serio_get_drvdata(serio); + + phampshire->data[phampshire->idx] = data; + + if (HAMPSHIRE_RESPONSE_BEGIN_BYTE & phampshire->data[0]) + hampshire_process_data(phampshire); + else + dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", + phampshire->data[0]); + + return IRQ_HANDLED; +} + +static void hampshire_disconnect(struct serio *serio) +{ + struct hampshire *phampshire = serio_get_drvdata(serio); + + input_get_device(phampshire->dev); + input_unregister_device(phampshire->dev); + serio_close(serio); + serio_set_drvdata(serio, NULL); + input_put_device(phampshire->dev); + kfree(phampshire); +} + +/* + * hampshire_connect() is the routine that is called when someone adds a + * new serio device that supports hampshire protocol and registers it as + * an input device. This is usually accomplished using inputattach. + */ + +static int hampshire_connect(struct serio *serio, struct serio_driver *drv) +{ + struct hampshire *phampshire; + struct input_dev *input_dev; + int err; + + phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!phampshire || !input_dev) { + err = -ENOMEM; + goto fail1; + } + + phampshire->serio = serio; + phampshire->dev = input_dev; + snprintf(phampshire->phys, sizeof(phampshire->phys), + "%s/input0", serio->phys); + + input_dev->name = "Hampshire Serial TouchScreen"; + input_dev->phys = phampshire->phys; + input_dev->id.bustype = BUS_RS232; + input_dev->id.vendor = SERIO_HAMPSHIRE; + input_dev->id.product = 0; + input_dev->id.version = 0x0001; + input_dev->dev.parent = &serio->dev; + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_abs_params(phampshire->dev, ABS_X, + HAMPSHIRE_MIN_XC, HAMPSHIRE_MAX_XC, 0, 0); + input_set_abs_params(phampshire->dev, ABS_Y, + HAMPSHIRE_MIN_YC, HAMPSHIRE_MAX_YC, 0, 0); + + serio_set_drvdata(serio, phampshire); + + err = serio_open(serio, drv); + if (err) + goto fail2; + + err = input_register_device(phampshire->dev); + if (err) + goto fail3; + + return 0; + + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); + kfree(phampshire); + return err; +} + +/* + * The serio driver structure. + */ + +static struct serio_device_id hampshire_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_HAMPSHIRE, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; + +MODULE_DEVICE_TABLE(serio, hampshire_serio_ids); + +static struct serio_driver hampshire_drv = { + .driver = { + .name = "hampshire", + }, + .description = DRIVER_DESC, + .id_table = hampshire_serio_ids, + .interrupt = hampshire_interrupt, + .connect = hampshire_connect, + .disconnect = hampshire_disconnect, +}; + +/* + * The functions for inserting/removing us as a module. + */ + +static int __init hampshire_init(void) +{ + return serio_register_driver(&hampshire_drv); +} + +static void __exit hampshire_exit(void) +{ + serio_unregister_driver(&hampshire_drv); +} + +module_init(hampshire_init); +module_exit(hampshire_exit); -- cgit v1.2.2 From 6b9d363c49d22395d0cf8729c5963f83cfbb6d69 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 19 Apr 2010 00:42:16 -0700 Subject: Input: psmouse - ignore parity error for basic protocols Observing behavior of the other OS it appears that parity errors reported by the keyboard controller are being ignored and the data is processed as usual. Let's do the same for standard PS/2 protocols (bare, Intellimouse and Intellimouse Explorer) to provide better compatibility. Thsi should fix teh following bug: https://bugzilla.kernel.org/show_bug.cgi?id=6105 Thanks for Damjan Jovanovic for locating the source of issue and ideas for the patch. Tested-by: Damjan Jovanovic Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 18 +++++++++++++++--- drivers/input/mouse/psmouse.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992..cbc80726494 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; struct psmouse_protocol { enum psmouse_type type; bool maxproto; + bool ignore_parity; /* Protocol should ignore parity errors from KBC */ const char *name; const char *alias; int (*detect)(struct psmouse *, bool); @@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (psmouse->state == PSMOUSE_IGNORE) goto out; - if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { + if (unlikely((flags & SERIO_TIMEOUT) || + ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { + if (psmouse->state == PSMOUSE_ACTIVATED) printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", @@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "PS/2", .alias = "bare", .maxproto = true, + .ignore_parity = true, .detect = ps2bare_detect, }, #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP @@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImPS/2", .alias = "imps", .maxproto = true, + .ignore_parity = true, .detect = intellimouse_detect, }, { @@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImExPS/2", .alias = "exps", .maxproto = true, + .ignore_parity = true, .detect = im_explorer_detect, }, #ifdef CONFIG_MOUSE_PS2_SYNAPTICS @@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto) { + const struct psmouse_protocol *selected_proto; struct input_dev *input_dev = psmouse->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev; @@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, return -1; psmouse->type = proto->type; - } else + selected_proto = proto; + } else { psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, true); + selected_proto = psmouse_protocol_by_type(psmouse->type); + } + + psmouse->ignore_parity = selected_proto->ignore_parity; /* * If mouse's packet size is 3 there is no point in polling the @@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, psmouse->resync_time = 0; snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", - psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); + selected_proto->name, psmouse->vendor, psmouse->name); input_dev->name = psmouse->devname; input_dev->phys = psmouse->phys; diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd137f..593e910bfc7 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -47,6 +47,7 @@ struct psmouse { unsigned char pktcnt; unsigned char pktsize; unsigned char type; + bool ignore_parity; bool acks_disable_command; unsigned int model; unsigned long last; -- cgit v1.2.2 From 6d327cb03fbc64cac36571c9bc8a1576d2b3ea00 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 00:37:21 -0700 Subject: Revert "Input: ALPS - add signature for HP Pavilion dm3 laptops" This reverts commit 5e28d8eb68c12eab9c4a47b42ba993a6420d71d3 since the magic knock does not work for this model of the touchpad and the device stays in PS/2 compatibility mode. --- drivers/input/mouse/alps.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 2a791e0ef97..7490f1da4a5 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -63,7 +63,6 @@ static const struct alps_model_info alps_model_data[] = { { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ - { { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */ { { 0x52, 0x01, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ }; -- cgit v1.2.2 From 5f57d67da87332a9a1ba8fa7a33bf0680e1c76e7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 19 Apr 2010 10:37:21 -0700 Subject: Input: Add support of Synaptics Clickpad device The new type of touchpads can be detected via a new query command 0x0c. The clickpad flags are in cap[0]:4 and cap[1]:0 bits. When the device is detected, the driver now reports only the left button as the supported buttons so that X11 driver can detect that the device is Clickpad. A Clickpad device gives the button events only as the middle button. The kernel driver morphs to the left button. The real handling of Clickpad is done rather in X driver side. Signed-off-by: Takashi Iwai Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 35 ++++++++++++++++++++++++++++++----- drivers/input/mouse/synaptics.h | 4 ++++ 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d3f5243fa09..9ab9ff07232 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -136,7 +136,8 @@ static int synaptics_capability(struct psmouse *psmouse) if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) return -1; priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; - priv->ext_cap = 0; + priv->ext_cap = priv->ext_cap_0c = 0; + if (!SYN_CAP_VALID(priv->capabilities)) return -1; @@ -149,7 +150,7 @@ static int synaptics_capability(struct psmouse *psmouse) if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { printk(KERN_ERR "Synaptics claims to have extended capabilities," - " but I'm not able to read them."); + " but I'm not able to read them.\n"); } else { priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; @@ -161,6 +162,16 @@ static int synaptics_capability(struct psmouse *psmouse) priv->ext_cap &= 0xff0fff; } } + + if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { + printk(KERN_ERR "Synaptics claims to have extended capability 0x0c," + " but I'm not able to read it.\n"); + } else { + priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; + } + } + return 0; } @@ -347,7 +358,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; - if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { + if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { + /* + * Clickpad's button is transmitted as middle button, + * however, since it is primary button, we will report + * it as BTN_LEFT. + */ + hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; + + } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; if (hw->w == 2) hw->scroll = (signed char)(buf[1]); @@ -592,6 +611,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) dev->absres[ABS_X] = priv->x_res; dev->absres[ABS_Y] = priv->y_res; + + if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { + /* Clickpads report only left button */ + __clear_bit(BTN_RIGHT, dev->keybit); + __clear_bit(BTN_MIDDLE, dev->keybit); + } } static void synaptics_disconnect(struct psmouse *psmouse) @@ -696,10 +721,10 @@ int synaptics_init(struct psmouse *psmouse) priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; - printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", + printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", SYN_ID_MODEL(priv->identity), SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), - priv->model_id, priv->capabilities, priv->ext_cap); + priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); set_input_params(psmouse->dev, priv); diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index f0f40a331dc..ae37c5d162a 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -18,6 +18,7 @@ #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_EXT_CAPAB 0x09 +#define SYN_QUE_EXT_CAPAB_0C 0x0c /* synatics modes */ #define SYN_BIT_ABSOLUTE_MODE (1 << 7) @@ -48,6 +49,8 @@ #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) +#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) +#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -96,6 +99,7 @@ struct synaptics_data { unsigned long int model_id; /* Model-ID */ unsigned long int capabilities; /* Capabilities */ unsigned long int ext_cap; /* Extended Capabilities */ + unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ unsigned long int identity; /* Identification */ int x_res; /* X resolution in units/mm */ int y_res; /* Y resolution in units/mm */ -- cgit v1.2.2 From 7fbef0d1e278a0a8c803a4d2b1e2bd5740bffa52 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 19 Apr 2010 00:42:16 -0700 Subject: Input: eeti_ts - cancel pending work when going to suspend This fixes a race between the suspend code and input events. Signed-off-by: Daniel Mack Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/eeti_ts.c | 56 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 9029bd3f34e..6fb6bd8495e 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -123,14 +123,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int eeti_ts_open(struct input_dev *dev) +static void eeti_ts_start(struct eeti_ts_priv *priv) { - struct eeti_ts_priv *priv = input_get_drvdata(dev); - enable_irq(priv->irq); /* Read the events once to arm the IRQ */ eeti_ts_read(&priv->work); +} + +static void eeti_ts_stop(struct eeti_ts_priv *priv) +{ + disable_irq(priv->irq); + cancel_work_sync(&priv->work); +} + +static int eeti_ts_open(struct input_dev *dev) +{ + struct eeti_ts_priv *priv = input_get_drvdata(dev); + + eeti_ts_start(priv); return 0; } @@ -139,8 +150,7 @@ static void eeti_ts_close(struct input_dev *dev) { struct eeti_ts_priv *priv = input_get_drvdata(dev); - disable_irq(priv->irq); - cancel_work_sync(&priv->work); + eeti_ts_stop(priv); } static int __devinit eeti_ts_probe(struct i2c_client *client, @@ -152,10 +162,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, unsigned int irq_flags; int err = -ENOMEM; - /* In contrast to what's described in the datasheet, there seems + /* + * In contrast to what's described in the datasheet, there seems * to be no way of probing the presence of that device using I2C * commands. So we need to blindly believe it is there, and wait - * for interrupts to occur. */ + * for interrupts to occur. + */ priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { @@ -211,9 +223,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, goto err2; } - /* Disable the irq for now. It will be enabled once the input device - * is opened. */ - disable_irq(priv->irq); + /* + * Disable the device for now. It will be enabled once the + * input device is opened. + */ + eeti_ts_stop(priv); device_init_wakeup(&client->dev, 0); return 0; @@ -234,6 +248,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) struct eeti_ts_priv *priv = i2c_get_clientdata(client); free_irq(priv->irq, priv); + /* + * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it + * so that device still works if we reload the driver. + */ + enable_irq(priv->irq); + input_unregister_device(priv->input); i2c_set_clientdata(client, NULL); kfree(priv); @@ -245,6 +265,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) { struct eeti_ts_priv *priv = i2c_get_clientdata(client); + struct input_dev *input_dev = priv->input; + + mutex_lock(&input_dev->mutex); + + if (input_dev->users) + eeti_ts_stop(priv); + + mutex_unlock(&input_dev->mutex); if (device_may_wakeup(&client->dev)) enable_irq_wake(priv->irq); @@ -255,10 +283,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) static int eeti_ts_resume(struct i2c_client *client) { struct eeti_ts_priv *priv = i2c_get_clientdata(client); + struct input_dev *input_dev = priv->input; if (device_may_wakeup(&client->dev)) disable_irq_wake(priv->irq); + mutex_lock(&input_dev->mutex); + + if (input_dev->users) + eeti_ts_start(priv); + + mutex_unlock(&input_dev->mutex); + return 0; } #else -- cgit v1.2.2 From 2ef2ed597669f5e120d0c51c295f00e34b2f0801 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Apr 2010 21:53:11 -0700 Subject: Input: acecad - fix incorrect size parameter in usb_buffer_free The size allocated by usb_buffer_alloc() is 8, however the size passed to usb_buffer_free() in usb_acecad_disconnect() is 10. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/acecad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 670c61c5a51..265753c7630 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -256,7 +256,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf) usb_kill_urb(acecad->irq); input_unregister_device(acecad->input); usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); + usb_buffer_free(interface_to_usbdev(intf), 8, acecad->data, acecad->data_dma); kfree(acecad); } } -- cgit v1.2.2 From 5492f6f801c81c9663417cd8e48e759775977c83 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 22:20:37 -0700 Subject: Input: acecad - simplify usb_acecad_disconnect() There is no need to check whether acecad structure is attached to the interface; if it isn't and we are called we have much bigger problems. Also no need to call usb_kill_urb() in usb_acecad_disconnect() since it is being called in usb_acecad_close(). Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/acecad.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 265753c7630..1697ec2c308 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -252,13 +252,11 @@ static void usb_acecad_disconnect(struct usb_interface *intf) struct usb_acecad *acecad = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); - if (acecad) { - usb_kill_urb(acecad->irq); - input_unregister_device(acecad->input); - usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 8, acecad->data, acecad->data_dma); - kfree(acecad); - } + + input_unregister_device(acecad->input); + usb_free_urb(acecad->irq); + usb_buffer_free(acecad->usbdev, 8, acecad->data, acecad->data_dma); + kfree(acecad); } static struct usb_device_id usb_acecad_id_table [] = { -- cgit v1.2.2 From b426571ceab9fbdd50be33a4cb379a119c6028a2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 22:30:22 -0700 Subject: Input: acecad - fix some formatting issues Also switch to using input_set_abd_params() helper. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/acecad.c | 76 ++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 40 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 1697ec2c308..214378b05db 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -66,18 +66,18 @@ static void usb_acecad_irq(struct urb *urb) int prox, status; switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __func__, urb->status); - goto resubmit; + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, urb->status); + goto resubmit; } prox = (data[0] & 0x04) >> 2; @@ -135,7 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ struct usb_acecad *acecad; struct input_dev *input_dev; int pipe, maxp; - int err = -ENOMEM; + int err; if (interface->desc.bNumEndpoints != 1) return -ENODEV; @@ -193,40 +193,36 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ input_dev->close = usb_acecad_close; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_PRESSURE); - input_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); + input_dev->keybit[BIT_WORD(BTN_LEFT)] = + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); switch (id->driver_info) { - case 0: - input_dev->absmax[ABS_X] = 5000; - input_dev->absmax[ABS_Y] = 3750; - input_dev->absmax[ABS_PRESSURE] = 512; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad Flair Tablet %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - break; - case 1: - input_dev->absmax[ABS_X] = 3000; - input_dev->absmax[ABS_Y] = 2250; - input_dev->absmax[ABS_PRESSURE] = 1024; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad 302 Tablet %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - break; + case 0: + input_set_abs_params(input_dev, ABS_X, 0, 5000, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 3750, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 512, 0, 0); + if (!strlen(acecad->name)) + snprintf(acecad->name, sizeof(acecad->name), + "USB Acecad Flair Tablet %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + break; + + case 1: + input_set_abs_params(input_dev, ABS_X, 0, 53000, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 2250, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1024, 0, 0); + if (!strlen(acecad->name)) + snprintf(acecad->name, sizeof(acecad->name), + "USB Acecad 302 Tablet %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + break; } - input_dev->absfuzz[ABS_X] = 4; - input_dev->absfuzz[ABS_Y] = 4; - usb_fill_int_urb(acecad->irq, dev, pipe, acecad->data, maxp > 8 ? 8 : maxp, usb_acecad_irq, acecad, endpoint->bInterval); -- cgit v1.2.2 From 893d1cdd53d8a748245dbfab62f4bf220316761d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 22:30:25 -0700 Subject: Input: acecad - don't advertise mouse events The device does not emit events for left/right/middle mouse buttons so it should not mark them as supported in capabilities bitmaps. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/acecad.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 214378b05db..37d0539fefa 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -193,8 +193,6 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ input_dev->close = usb_acecad_close; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_LEFT)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); -- cgit v1.2.2 From ee7aa6ce41e08c68f72b5ca8f14fb61286dc2418 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Apr 2010 21:59:51 -0700 Subject: Input: kbtab - fix incorrect size parameter in usb_buffer_free The size allocated by usb_buffer_alloc() is 8, however the size passed to usb_buffer_free() is 10. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/kbtab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 6682b17bf84..76b5d526cde 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -182,7 +182,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; fail3: usb_free_urb(kbtab->irq); - fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); + fail2: usb_buffer_free(dev, 8, kbtab->data, kbtab->data_dma); fail1: input_free_device(input_dev); kfree(kbtab); return error; @@ -197,7 +197,7 @@ static void kbtab_disconnect(struct usb_interface *intf) usb_kill_urb(kbtab->irq); input_unregister_device(kbtab->dev); usb_free_urb(kbtab->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); + usb_buffer_free(interface_to_usbdev(intf), 8, kbtab->data, kbtab->data_dma); kfree(kbtab); } } -- cgit v1.2.2 From 331cb022d3ac1f85f7842a51495c33c629e947bc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 22:06:53 -0700 Subject: Input: kbtab - simplify kbtab_disconnect() There is no need to check whether kbtab structure is attached to the interface; if it isn't and we are called we have much bigger problems. Also no need to call usb_kill_urb() in kbtab_disconnect() since it is being called in kbtab_close(). Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/kbtab.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 76b5d526cde..3f7d1254b8e 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -193,13 +193,11 @@ static void kbtab_disconnect(struct usb_interface *intf) struct kbtab *kbtab = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); - if (kbtab) { - usb_kill_urb(kbtab->irq); - input_unregister_device(kbtab->dev); - usb_free_urb(kbtab->irq); - usb_buffer_free(interface_to_usbdev(intf), 8, kbtab->data, kbtab->data_dma); - kfree(kbtab); - } + + input_unregister_device(kbtab->dev); + usb_free_urb(kbtab->irq); + usb_buffer_free(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma); + kfree(kbtab); } static struct usb_driver kbtab_driver = { -- cgit v1.2.2 From f3192090df1e17dbd0f7c4b3820d31719422eb96 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Apr 2010 22:15:44 -0700 Subject: Input: kbtab - do not advertise unsupported events The device does not emit EV_MSC/MSC_SERIAL nor EV_KEY/BTN_MIDDLE events so it should not mark them as supported in capabilities bitmaps. This still leaves BTN_TOOL_PEN and BTN_TOUCH events being processed in a funky manner. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/kbtab.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 3f7d1254b8e..b9969f12024 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -34,10 +34,6 @@ struct kbtab { struct input_dev *dev; struct usb_device *usbdev; struct urb *irq; - int x, y; - int button; - int pressure; - __u32 serial[2]; char phys[32]; }; @@ -46,6 +42,7 @@ static void kbtab_irq(struct urb *urb) struct kbtab *kbtab = urb->context; unsigned char *data = kbtab->data; struct input_dev *dev = kbtab->dev; + int pressure; int retval; switch (urb->status) { @@ -63,31 +60,27 @@ static void kbtab_irq(struct urb *urb) goto exit; } - kbtab->x = get_unaligned_le16(&data[1]); - kbtab->y = get_unaligned_le16(&data[3]); - - kbtab->pressure = (data[5]); input_report_key(dev, BTN_TOOL_PEN, 1); - input_report_abs(dev, ABS_X, kbtab->x); - input_report_abs(dev, ABS_Y, kbtab->y); + input_report_abs(dev, ABS_X, get_unaligned_le16(&data[1])); + input_report_abs(dev, ABS_Y, get_unaligned_le16(&data[3])); /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - if (-1 == kb_pressure_click) { - input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); - } else { - input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); - }; + pressure = data[5]; + if (kb_pressure_click == -1) + input_report_abs(dev, ABS_PRESSURE, pressure); + else + input_report_key(dev, BTN_LEFT, pressure > kb_pressure_click ? 1 : 0); input_sync(dev); exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - err ("%s - usb_submit_urb failed with result %d", + err("%s - usb_submit_urb failed with result %d", __func__, retval); } @@ -153,13 +146,11 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i input_dev->open = kbtab_open; input_dev->close = kbtab_close; - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | - BIT_MASK(EV_MSC); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | - BIT_MASK(BTN_TOUCH); - input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_LEFT)] |= + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); -- cgit v1.2.2 From 16b32e0c9eec1bb8d53deedcd9f4704a114d84bb Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 3 May 2010 23:29:58 -0700 Subject: Input: remove obsolete {corgi,spitz,tosa}kbd.c Signed-off-by: Eric Miao Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 48 ---- drivers/input/keyboard/Makefile | 3 - drivers/input/keyboard/corgikbd.c | 414 ------------------------------- drivers/input/keyboard/spitzkbd.c | 496 -------------------------------------- drivers/input/keyboard/tosakbd.c | 431 --------------------------------- 5 files changed, 1392 deletions(-) delete mode 100644 drivers/input/keyboard/corgikbd.c delete mode 100644 drivers/input/keyboard/spitzkbd.c delete mode 100644 drivers/input/keyboard/tosakbd.c (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c102355f5..a8293388d01 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -143,19 +143,6 @@ config KEYBOARD_BFIN To compile this driver as a module, choose M here: the module will be called bf54x-keys. -config KEYBOARD_CORGI - tristate "Corgi keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx - series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called corgikbd. - config KEYBOARD_LKKBD tristate "DECstation/VAXstation LK201/LK401 keyboard" select SERIO @@ -339,19 +326,6 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_SPITZ - tristate "Spitz keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called spitzkbd. - config KEYBOARD_STOWAWAY tristate "Stowaway keyboard" select SERIO @@ -414,28 +388,6 @@ config KEYBOARD_TWL4030 To compile this driver as a module, choose M here: the module will be called twl4030_keypad. -config KEYBOARD_TOSA - tristate "Tosa keyboard (deprecated)" - depends on MACH_TOSA - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called tosakbd. - -config KEYBOARD_TOSA_USE_EXT_KEYCODES - bool "Tosa keyboard: use extended keycodes" - depends on KEYBOARD_TOSA - help - Say Y here to enable the tosa keyboard driver to generate extended - (>= 127) keycodes. Be aware, that they can't be correctly interpreted - by either console keyboard driver or by Kdrive keybd driver. - - Say Y only if you know, what you are doing! - config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5ed5f..9a74127e4d1 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o -obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o @@ -33,10 +32,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o -obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o -obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a8e6b..00000000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Keyboard driver for Sharp Corgi models (SL-C7xx) - * - * Copyright (c) 2004-2005 Richard Purdie - * - * Based on xtkbd.c/locomkbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define KB_ROWS 8 -#define KB_COLS 12 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -/* zero code, 124 scancodes */ -#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (250) /* ms */ - -#define CORGI_KEY_CALENDER KEY_F1 -#define CORGI_KEY_ADDRESS KEY_F2 -#define CORGI_KEY_FN KEY_F3 -#define CORGI_KEY_CANCEL KEY_F4 -#define CORGI_KEY_OFF KEY_SUSPEND -#define CORGI_KEY_EXOK KEY_F5 -#define CORGI_KEY_EXCANCEL KEY_F6 -#define CORGI_KEY_EXJOGDOWN KEY_F7 -#define CORGI_KEY_EXJOGUP KEY_F8 -#define CORGI_KEY_JAP1 KEY_LEFTCTRL -#define CORGI_KEY_JAP2 KEY_LEFTALT -#define CORGI_KEY_MAIL KEY_F10 -#define CORGI_KEY_OK KEY_F11 -#define CORGI_KEY_MENU KEY_F12 - -static unsigned char corgikbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ - CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ - CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ -}; - - -struct corgikbd { - unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; - struct input_dev *input; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void corgikbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; -} - -static inline void corgikbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; - GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; -} - -static inline void corgikbd_activate_col(int col) -{ - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = CORGI_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -static inline void corgikbd_reset_col(int col) -{ - /* STROBE col -> Low */ - GPCR2 = CORGI_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) - -/* - * The corgi keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed; - - if (corgikbd_data->suspended) - return; - - spin_lock_irqsave(&corgikbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - corgikbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - corgikbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - - if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) - && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { - input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); - corgikbd_data->suspend_jiffies=jiffies; - } - } - corgikbd_reset_col(col); - } - - corgikbd_activate_all(); - - input_sync(corgikbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); -} - -/* - * corgi keyboard interrupt handler. - */ -static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) -{ - struct corgikbd *corgikbd_data = dev_id; - - if (!timer_pending(&corgikbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - corgikbd_scankeyboard(corgikbd_data); - } - - return IRQ_HANDLED; -} - -/* - * corgi timer checking for released keys - */ -static void corgikbd_timer_callback(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - corgikbd_scankeyboard(corgikbd_data); -} - -/* - * The hinge switches generate no interrupt so they need to be - * monitored by a timer. - * - * We debounce the switches and pass them to the input system. - * - * gprr == 0x00 - Keyboard with Landscape Screen - * 0x08 - No Keyboard with Portrait Screen - * 0x0c - Keyboard and Screen Closed - */ - -#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void corgikbd_hinge_timer(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - unsigned long gprr; - unsigned long flags; - - gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); - gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); - if (gprr != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = gprr; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&corgikbd_data->lock, flags); - - input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); - input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); - input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); - input_sync(corgikbd_data->input); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); - } - } - mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); -} - -#ifdef CONFIG_PM -static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - corgikbd->suspended = 1; - /* strobe 0 is the power key so this can't be made an input for - powersaving therefore i = 1 */ - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); - - return 0; -} - -static int corgikbd_resume(struct platform_device *dev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - corgikbd->suspend_jiffies=jiffies; - corgikbd->suspended = 0; - - return 0; -} -#else -#define corgikbd_suspend NULL -#define corgikbd_resume NULL -#endif - -static int __devinit corgikbd_probe(struct platform_device *pdev) -{ - struct corgikbd *corgikbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgikbd || !input_dev) - goto fail; - - platform_set_drvdata(pdev, corgikbd); - - corgikbd->input = input_dev; - spin_lock_init(&corgikbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&corgikbd->timer); - corgikbd->timer.function = corgikbd_timer_callback; - corgikbd->timer.data = (unsigned long) corgikbd; - - /* Init Hinge Timer */ - init_timer(&corgikbd->htimer); - corgikbd->htimer.function = corgikbd_hinge_timer; - corgikbd->htimer.data = (unsigned long) corgikbd; - - corgikbd->suspend_jiffies=jiffies; - - memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); - - input_dev->name = "Corgi Keyboard"; - input_dev->phys = "corgikbd/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = corgikbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); - - for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) - set_bit(corgikbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(corgikbd->input); - if (err) - goto fail; - - mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); - if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "corgikbd", corgikbd)) - printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Setup the headphone jack as an input */ - pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); - - return 0; - - fail: input_free_device(input_dev); - kfree(corgikbd); - return err; -} - -static int __devexit corgikbd_remove(struct platform_device *pdev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(pdev); - - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) - free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); - - del_timer_sync(&corgikbd->htimer); - del_timer_sync(&corgikbd->timer); - - input_unregister_device(corgikbd->input); - - kfree(corgikbd); - - return 0; -} - -static struct platform_driver corgikbd_driver = { - .probe = corgikbd_probe, - .remove = __devexit_p(corgikbd_remove), - .suspend = corgikbd_suspend, - .resume = corgikbd_resume, - .driver = { - .name = "corgi-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init corgikbd_init(void) -{ - return platform_driver_register(&corgikbd_driver); -} - -static void __exit corgikbd_exit(void) -{ - platform_driver_unregister(&corgikbd_driver); -} - -module_init(corgikbd_init); -module_exit(corgikbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:corgi-keyboard"); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 13967422658..00000000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) - * - * Copyright (c) 2005 Richard Purdie - * - * Based on corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWS 7 -#define KB_COLS 11 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES ((KB_ROWS<<4) + 1) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (150) /* ms */ - -#define SPITZ_KEY_CALENDER KEY_F1 -#define SPITZ_KEY_ADDRESS KEY_F2 -#define SPITZ_KEY_FN KEY_F3 -#define SPITZ_KEY_CANCEL KEY_F4 -#define SPITZ_KEY_EXOK KEY_F5 -#define SPITZ_KEY_EXCANCEL KEY_F6 -#define SPITZ_KEY_EXJOGDOWN KEY_F7 -#define SPITZ_KEY_EXJOGUP KEY_F8 -#define SPITZ_KEY_JAP1 KEY_LEFTALT -#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL -#define SPITZ_KEY_SYNC KEY_F9 -#define SPITZ_KEY_MAIL KEY_F10 -#define SPITZ_KEY_OK KEY_F11 -#define SPITZ_KEY_MENU KEY_F12 - -static unsigned char spitzkbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ - SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ -}; - -static int spitz_strobes[] = { - SPITZ_GPIO_KEY_STROBE0, - SPITZ_GPIO_KEY_STROBE1, - SPITZ_GPIO_KEY_STROBE2, - SPITZ_GPIO_KEY_STROBE3, - SPITZ_GPIO_KEY_STROBE4, - SPITZ_GPIO_KEY_STROBE5, - SPITZ_GPIO_KEY_STROBE6, - SPITZ_GPIO_KEY_STROBE7, - SPITZ_GPIO_KEY_STROBE8, - SPITZ_GPIO_KEY_STROBE9, - SPITZ_GPIO_KEY_STROBE10, -}; - -static int spitz_senses[] = { - SPITZ_GPIO_KEY_SENSE0, - SPITZ_GPIO_KEY_SENSE1, - SPITZ_GPIO_KEY_SENSE2, - SPITZ_GPIO_KEY_SENSE3, - SPITZ_GPIO_KEY_SENSE4, - SPITZ_GPIO_KEY_SENSE5, - SPITZ_GPIO_KEY_SENSE6, -}; - -struct spitzkbd { - unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; - struct input_dev *input; - char phys[32]; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 11 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void spitzkbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; -} - -static inline void spitzkbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; - GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; - GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; - GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; - GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; - GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; - GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; -} - -static inline void spitzkbd_activate_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPSR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline void spitzkbd_reset_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPCR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline int spitzkbd_get_row_status(int col) -{ - return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) - | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) - | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); -} - -/* - * The spitz keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); - - if (spitzkbd_data->suspended) - return; - - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - spitzkbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - spitzkbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = spitzkbd_get_row_status(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - } - spitzkbd_reset_col(col); - } - - spitzkbd_activate_all(); - - input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); - input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); - - if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { - input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); - spitzkbd_data->suspend_jiffies = jiffies; - } - - input_sync(spitzkbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); -} - -/* - * spitz keyboard interrupt handler. - */ -static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - spitzkbd_scankeyboard(spitzkbd_data); - } - - return IRQ_HANDLED; -} - -/* - * spitz timer checking for released keys - */ -static void spitzkbd_timer_callback(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - - spitzkbd_scankeyboard(spitzkbd_data); -} - -/* - * The hinge switches generate an interrupt. - * We debounce the switches and pass them to the input system. - */ - -static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->htimer)) - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - return IRQ_HANDLED; -} - -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void spitzkbd_hinge_timer(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - unsigned long state; - unsigned long flags; - - state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); - state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); - if (state != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = state; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - } - - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); - input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); - input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); - input_sync(spitzkbd_data->input); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); - } else { - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - } -} - -#ifdef CONFIG_PM -static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - spitzkbd->suspended = 1; - - /* Set Strobe lines as inputs - *except* strobe line 0 leave this - enabled so we can detect a power button press for resume */ - for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); - - return 0; -} - -static int spitzkbd_resume(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - spitzkbd->suspend_jiffies = jiffies; - spitzkbd->suspended = 0; - - return 0; -} -#else -#define spitzkbd_suspend NULL -#define spitzkbd_resume NULL -#endif - -static int __devinit spitzkbd_probe(struct platform_device *dev) -{ - struct spitzkbd *spitzkbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!spitzkbd || !input_dev) - goto fail; - - platform_set_drvdata(dev, spitzkbd); - strcpy(spitzkbd->phys, "spitzkbd/input0"); - - spin_lock_init(&spitzkbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&spitzkbd->timer); - spitzkbd->timer.function = spitzkbd_timer_callback; - spitzkbd->timer.data = (unsigned long) spitzkbd; - - /* Init Hinge Timer */ - init_timer(&spitzkbd->htimer); - spitzkbd->htimer.function = spitzkbd_hinge_timer; - spitzkbd->htimer.data = (unsigned long) spitzkbd; - - spitzkbd->suspend_jiffies = jiffies; - - spitzkbd->input = input_dev; - - input_dev->name = "Spitz Keyboard"; - input_dev->phys = spitzkbd->phys; - input_dev->dev.parent = &dev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = spitzkbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); - - memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); - for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) - set_bit(spitzkbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(KEY_SUSPEND, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(input_dev); - if (err) - goto fail; - - mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(spitz_senses[i] | GPIO_IN); - if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, - IRQF_DISABLED|IRQF_TRIGGER_RISING, - "Spitzkbd Sense", spitzkbd)) - printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); - - request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd Sync", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd PwrOn", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWA", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWB", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd HP", spitzkbd); - - return 0; - - fail: input_free_device(input_dev); - kfree(spitzkbd); - return err; -} - -static int __devexit spitzkbd_remove(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) - free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); - - free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); - - del_timer_sync(&spitzkbd->htimer); - del_timer_sync(&spitzkbd->timer); - - input_unregister_device(spitzkbd->input); - - kfree(spitzkbd); - - return 0; -} - -static struct platform_driver spitzkbd_driver = { - .probe = spitzkbd_probe, - .remove = __devexit_p(spitzkbd_remove), - .suspend = spitzkbd_suspend, - .resume = spitzkbd_resume, - .driver = { - .name = "spitz-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init spitzkbd_init(void) -{ - return platform_driver_register(&spitzkbd_driver); -} - -static void __exit spitzkbd_exit(void) -{ - platform_driver_unregister(&spitzkbd_driver); -} - -module_init(spitzkbd_init); -module_exit(spitzkbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Spitz Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:spitz-keyboard"); diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f269cfc..00000000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Keyboard driver for Sharp Tosa models (SL-6000x) - * - * Copyright (c) 2005 Dirk Opfer - * Copyright (c) 2007 Dmitry Baryshkov - * - * Based on xtkbd.c/locomkbd.c/corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r, c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 - -#define SCAN_INTERVAL (HZ/10) - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -static unsigned short tosakbd_keycode[NR_SCANCODES] = { -0, -0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, -KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, -KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, -0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, -KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, -0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, -KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, -0, 0, 0, -}; - -struct tosakbd { - unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; - struct input_dev *input; - bool suspended; - spinlock_t lock; /* protect kbd scanning */ - struct timer_list timer; -}; - - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) - -static inline void tosakbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; - GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; -} - -static inline void tosakbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; - GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* STATE CLEAR */ - GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; -} - -static inline void tosakbd_activate_col(int col) -{ - if (col <= 5) { - /* STROBE col -> High, not col -> HiZ */ - GPSR1 = TOSA_GPIO_STROBE_BIT(col); - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = TOSA_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} - -static inline void tosakbd_reset_col(int col) -{ - if (col <= 5) { - /* STROBE col -> Low */ - GPCR1 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> Low */ - GPCR2 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} -/* - * The tosa keyboard only generates interrupts when a key is pressed. - * So when a key is pressed, we enable a timer. This timer scans the - * keyboard, and this is how we detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void tosakbd_scankeyboard(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed = 0; - - spin_lock_irqsave(&tosakbd->lock, flags); - - if (tosakbd->suspended) - goto out; - - for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - tosakbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - tosakbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - - for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { - unsigned int scancode, pressed; - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - if (pressed && !tosakbd->keycode[scancode]) - dev_warn(&dev->dev, - "unhandled scancode: 0x%02x\n", - scancode); - - input_report_key(tosakbd->input, - tosakbd->keycode[scancode], - pressed); - if (pressed) - num_pressed++; - } - - tosakbd_reset_col(col); - } - - tosakbd_activate_all(); - - input_sync(tosakbd->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); - - out: - spin_unlock_irqrestore(&tosakbd->lock, flags); -} - -/* - * tosa keyboard interrupt handler. - */ -static irqreturn_t tosakbd_interrupt(int irq, void *__dev) -{ - struct platform_device *dev = __dev; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - if (!timer_pending(&tosakbd->timer)) { - /** wait chattering delay **/ - udelay(20); - tosakbd_scankeyboard(dev); - } - - return IRQ_HANDLED; -} - -/* - * tosa timer checking for released keys - */ -static void tosakbd_timer_callback(unsigned long __dev) -{ - struct platform_device *dev = (struct platform_device *)__dev; - - tosakbd_scankeyboard(dev); -} - -#ifdef CONFIG_PM -static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned long flags; - - spin_lock_irqsave(&tosakbd->lock, flags); - tosakbd->suspended = true; - spin_unlock_irqrestore(&tosakbd->lock, flags); - - del_timer_sync(&tosakbd->timer); - - return 0; -} - -static int tosakbd_resume(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - tosakbd->suspended = false; - tosakbd_scankeyboard(dev); - - return 0; -} -#else -#define tosakbd_suspend NULL -#define tosakbd_resume NULL -#endif - -static int __devinit tosakbd_probe(struct platform_device *pdev) { - - int i; - struct tosakbd *tosakbd; - struct input_dev *input_dev; - int error; - - tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); - if (!tosakbd) - return -ENOMEM; - - input_dev = input_allocate_device(); - if (!input_dev) { - kfree(tosakbd); - return -ENOMEM; - } - - platform_set_drvdata(pdev, tosakbd); - - spin_lock_init(&tosakbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&tosakbd->timer); - tosakbd->timer.function = tosakbd_timer_callback; - tosakbd->timer.data = (unsigned long) pdev; - - tosakbd->input = input_dev; - - input_set_drvdata(input_dev, tosakbd); - input_dev->name = "Tosa Keyboard"; - input_dev->phys = "tosakbd/input0"; - input_dev->dev.parent = &pdev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - input_dev->keycode = tosakbd->keycode; - input_dev->keycodesize = sizeof(tosakbd->keycode[0]); - input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); - - memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); - - for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) - __set_bit(tosakbd->keycode[i], input_dev->keybit); - __clear_bit(KEY_RESERVED, input_dev->keybit); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_SENSE(i); - int irq; - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail; - } - - error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - irq = gpio_to_irq(gpio); - if (irq < 0) { - error = irq; - printk(KERN_ERR "gpio-keys: Unable to get irq number" - " for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - error = request_irq(irq, tosakbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "tosakbd", pdev); - - if (error) { - printk("tosakbd: Can't get IRQ: %d: error %d!\n", - irq, error); - gpio_free(gpio); - goto fail; - } - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_STROBE(i); - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail2; - } - - error = gpio_direction_output(gpio, 1); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail2; - } - - } - - error = input_register_device(input_dev); - if (error) { - printk(KERN_ERR "tosakbd: Unable to register input device, " - "error: %d\n", error); - goto fail2; - } - - printk(KERN_INFO "input: Tosa Keyboard Registered\n"); - - return 0; - -fail2: - while (--i >= 0) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - i = TOSA_KEY_SENSE_NUM; -fail: - while (--i >= 0) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - platform_set_drvdata(pdev, NULL); - input_free_device(input_dev); - kfree(tosakbd); - - return error; -} - -static int __devexit tosakbd_remove(struct platform_device *dev) -{ - int i; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - del_timer_sync(&tosakbd->timer); - - input_unregister_device(tosakbd->input); - - kfree(tosakbd); - - return 0; -} - -static struct platform_driver tosakbd_driver = { - .probe = tosakbd_probe, - .remove = __devexit_p(tosakbd_remove), - .suspend = tosakbd_suspend, - .resume = tosakbd_resume, - .driver = { - .name = "tosa-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __devinit tosakbd_init(void) -{ - return platform_driver_register(&tosakbd_driver); -} - -static void __exit tosakbd_exit(void) -{ - platform_driver_unregister(&tosakbd_driver); -} - -module_init(tosakbd_init); -module_exit(tosakbd_exit); - -MODULE_AUTHOR("Dirk Opfer "); -MODULE_DESCRIPTION("Tosa Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tosa-keyboard"); -- cgit v1.2.2 From 5132088697fbfd1330facf723499091182f6ef91 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 3 May 2010 23:30:32 -0700 Subject: Input: ati_remote - add some missing devices from lirc_atiusb The (out-of-tree) lirc_atiusb driver has a much longer list of devices it supports. Some of them look like they may just be guesses at possible device IDs, but a few are definitely confirmed devices. This adds the nVidia-branded RF receiver and the X10 Lola Wireless Video Sender device (which contains an RF receiver) to the list of devices in ati_remote. Signed-off-by: Jarod Wilson Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ati_remote.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index 614b65d78fe..e8bbc619f6d 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c @@ -98,10 +98,12 @@ * Module and Version Information, Module Parameters */ -#define ATI_REMOTE_VENDOR_ID 0x0bc7 -#define ATI_REMOTE_PRODUCT_ID 0x004 -#define LOLA_REMOTE_PRODUCT_ID 0x002 -#define MEDION_REMOTE_PRODUCT_ID 0x006 +#define ATI_REMOTE_VENDOR_ID 0x0bc7 +#define LOLA_REMOTE_PRODUCT_ID 0x0002 +#define LOLA2_REMOTE_PRODUCT_ID 0x0003 +#define ATI_REMOTE_PRODUCT_ID 0x0004 +#define NVIDIA_REMOTE_PRODUCT_ID 0x0005 +#define MEDION_REMOTE_PRODUCT_ID 0x0006 #define DRIVER_VERSION "2.2.1" #define DRIVER_AUTHOR "Torrey Hoffman " @@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec #define err(format, arg...) printk(KERN_ERR format , ## arg) static struct usb_device_id ati_remote_table[] = { - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, {} /* Terminating entry */ }; -- cgit v1.2.2 From 225c61aad38b12924b3df5f4ef43150c0d6bae8c Mon Sep 17 00:00:00 2001 From: Florian Ragwitz Date: Tue, 27 Apr 2010 00:45:10 -0700 Subject: Input: elantech - fix firmware version check The check determining whether device should use 4- or 6-byte packets was trying to compare firmware with 2.48, but was failing on majors greater than 2. The new check ensures that versions like 4.1 are checked properly. Signed-off-by: Florian Ragwitz Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b27684f267b..28eba48e68f 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -665,7 +665,8 @@ int elantech_init(struct psmouse *psmouse) * Assume every version greater than this is new EeePC style * hardware with 6 byte packets */ - if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { + if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) || + etd->fw_version_maj > 0x02) { etd->hw_version = 2; /* For now show extra debug information */ etd->debug = 1; -- cgit v1.2.2 From f81bc788ff91d4efd4baf88b2c29713838caa8e5 Mon Sep 17 00:00:00 2001 From: Florian Ragwitz Date: Tue, 27 Apr 2010 00:47:04 -0700 Subject: Input: elantech - allow forcing Elantech protocol Apparently hardware vendors now ship elantech touchpads with different version magic. This options allows for them to be tested easier with the current driver in order to add their magic to the whitelist later. Signed-off-by: Florian Ragwitz Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 28eba48e68f..095bd388c6d 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -24,6 +24,10 @@ printk(KERN_DEBUG format, ##arg); \ } while (0) +static bool force_elantech; +module_param_named(force_elantech, force_elantech, bool, 0644); +MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); + /* * Send a Synaptics style sliced query command */ @@ -595,8 +599,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) param[0], param[1], param[2]); if (param[0] == 0 || param[1] != 0) { - pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); - return -1; + if (!force_elantech) { + pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); + return -1; + } + + pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); } if (set_properties) { -- cgit v1.2.2 From e938fbfd4a7ac829d48b767c4dc365535d5c4f97 Mon Sep 17 00:00:00 2001 From: Florian Ragwitz Date: Mon, 3 May 2010 23:29:37 -0700 Subject: Input: elantech - ignore high bits in the position coordinates In older versions of the elantech hardware/firmware those bits always were unset, so it didn't actually matter, but newer versions seem to use those high bits for something else, screwing up the coordinates we report to the input layer for those devices. Signed-off-by: Florian Ragwitz Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 69 +++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 25 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 095bd388c6d..2cbf3fc4729 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -185,13 +185,17 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) static int old_fingers; if (etd->fw_version_maj == 0x01) { - /* byte 0: D U p1 p2 1 p3 R L - byte 1: f 0 th tw x9 x8 y9 y8 */ + /* + * byte 0: D U p1 p2 1 p3 R L + * byte 1: f 0 th tw x9 x8 y9 y8 + */ fingers = ((packet[1] & 0x80) >> 7) + ((packet[1] & 0x30) >> 4); } else { - /* byte 0: n1 n0 p2 p1 1 p3 R L - byte 1: 0 0 0 0 x9 x8 y9 y8 */ + /* + * byte 0: n1 n0 p2 p1 1 p3 R L + * byte 1: 0 0 0 0 x9 x8 y9 y8 + */ fingers = (packet[0] & 0xc0) >> 6; } @@ -205,13 +209,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) input_report_key(dev, BTN_TOUCH, fingers != 0); - /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 - byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ + /* + * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 + * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 + */ if (fingers) { input_report_abs(dev, ABS_X, ((packet[1] & 0x0c) << 6) | packet[2]); - input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - - (((packet[1] & 0x03) << 8) | packet[3])); + input_report_abs(dev, ABS_Y, + ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); } input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); @@ -250,34 +256,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) switch (fingers) { case 1: - /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 - byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ - input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); - /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 - byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ - input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - - ((packet[4] << 8) | packet[5])); + /* + * byte 1: . . . . . x10 x9 x8 + * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 + */ + input_report_abs(dev, ABS_X, + ((packet[1] & 0x07) << 8) | packet[2]); + /* + * byte 4: . . . . . . y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 + */ + input_report_abs(dev, ABS_Y, + ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); break; case 2: - /* The coordinate of each finger is reported separately with - a lower resolution for two finger touches */ - /* byte 0: . . ay8 ax8 . . . . - byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ + /* + * The coordinate of each finger is reported separately + * with a lower resolution for two finger touches: + * byte 0: . . ay8 ax8 . . . . + * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ x1 = ((packet[0] & 0x10) << 4) | packet[1]; /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); - /* byte 3: . . by8 bx8 . . . . - byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ + /* + * byte 3: . . by8 bx8 . . . . + * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 + */ x2 = ((packet[3] & 0x10) << 4) | packet[4]; /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); - /* For compatibility with the X Synaptics driver scale up one - coordinate and report as ordinary mouse movent */ + /* + * For compatibility with the X Synaptics driver scale up + * one coordinate and report as ordinary mouse movent + */ input_report_abs(dev, ABS_X, x1 << 2); input_report_abs(dev, ABS_Y, y1 << 2); - /* For compatibility with the proprietary X Elantech driver - report both coordinates as hat coordinates */ + /* + * For compatibility with the proprietary X Elantech driver + * report both coordinates as hat coordinates + */ input_report_abs(dev, ABS_HAT0X, x1); input_report_abs(dev, ABS_HAT0Y, y1); input_report_abs(dev, ABS_HAT1X, x2); -- cgit v1.2.2 From 30ba3ead05763b172acaa65ae1be71af2a878940 Mon Sep 17 00:00:00 2001 From: Sriramakrishnan Govindarajan Date: Mon, 3 May 2010 23:47:12 -0700 Subject: Input: add keypad driver for keys interfaced to TCA6416 This patch implements a simple Keypad driver that functions as an I2C client. It handles key press events for keys connected to TCA6416 I2C based IO expander. Signed-off-by: Sriramakrishnan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 16 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tca6416-keypad.c | 349 ++++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 drivers/input/keyboard/tca6416-keypad.c (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a8293388d01..3525f533e18 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -179,6 +179,22 @@ config KEYBOARD_GPIO To compile this driver as a module, choose M here: the module will be called gpio_keys. +config KEYBOARD_TCA6416 + tristate "TCA6416 Keypad Support" + depends on I2C + help + This driver implements basic keypad functionality + for keys connected through TCA6416 IO expander + + Say Y here if your device has keys connected to + TCA6416 IO expander. Your board-specific setup logic + must also provide pin-mask details(of which TCA6416 pins + are used for keypad). + + If enabled the complete TCA6416 device will be managed through + this driver. + + config KEYBOARD_MATRIX tristate "GPIO driven matrix keypad support" depends on GENERIC_GPIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 9a74127e4d1..4596d0c6f92 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o +obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c new file mode 100644 index 00000000000..493c93f25e2 --- /dev/null +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -0,0 +1,349 @@ +/* + * Driver for keys on TCA6416 I2C IO expander + * + * Copyright (C) 2010 Texas Instruments + * + * Author : Sriramakrishnan.A.G. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCA6416_INPUT 0 +#define TCA6416_OUTPUT 1 +#define TCA6416_INVERT 2 +#define TCA6416_DIRECTION 3 + +static const struct i2c_device_id tca6416_id[] = { + { "tca6416-keys", 16, }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tca6416_id); + +struct tca6416_drv_data { + struct input_dev *input; + struct tca6416_button data[0]; +}; + +struct tca6416_keypad_chip { + uint16_t reg_output; + uint16_t reg_direction; + uint16_t reg_input; + + struct i2c_client *client; + struct input_dev *input; + struct delayed_work dwork; + u16 pinmask; + int irqnum; + bool use_polling; + struct tca6416_button buttons[0]; +}; + +static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val) +{ + int error; + + error = i2c_smbus_write_word_data(chip->client, reg << 1, val); + if (error < 0) { + dev_err(&chip->client->dev, + "%s failed, reg: %d, val: %d, error: %d\n", + __func__, reg, val, error); + return error; + } + + return 0; +} + +static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val) +{ + int retval; + + retval = i2c_smbus_read_word_data(chip->client, reg << 1); + if (retval < 0) { + dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n", + __func__, reg, retval); + return retval; + } + + *val = (u16)retval; + return 0; +} + +static void tca6416_keys_scan(struct tca6416_keypad_chip *chip) +{ + struct input_dev *input = chip->input; + u16 reg_val, val; + int error, i, pin_index; + + error = tca6416_read_reg(chip, TCA6416_INPUT, ®_val); + if (error) + return; + + reg_val &= chip->pinmask; + + /* Figure out which lines have changed */ + val = reg_val ^ chip->reg_input; + chip->reg_input = reg_val; + + for (i = 0, pin_index = 0; i < 16; i++) { + if (val & (1 << i)) { + struct tca6416_button *button = &chip->buttons[pin_index]; + unsigned int type = button->type ?: EV_KEY; + int state = ((reg_val & (1 << i)) ? 1 : 0) + ^ button->active_low; + + input_event(input, type, button->code, !!state); + input_sync(input); + } + + if (chip->pinmask & (1 << i)) + pin_index++; + } +} + +/* + * This is threaded IRQ handler and this can (and will) sleep. + */ +static irqreturn_t tca6416_keys_isr(int irq, void *dev_id) +{ + struct tca6416_keypad_chip *chip = dev_id; + + tca6416_keys_scan(chip); + + return IRQ_HANDLED; +} + +static void tca6416_keys_work_func(struct work_struct *work) +{ + struct tca6416_keypad_chip *chip = + container_of(work, struct tca6416_keypad_chip, dwork.work); + + tca6416_keys_scan(chip); + schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); +} + +static int tca6416_keys_open(struct input_dev *dev) +{ + struct tca6416_keypad_chip *chip = input_get_drvdata(dev); + + /* Get initial device state in case it has switches */ + tca6416_keys_scan(chip); + + if (chip->use_polling) + schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); + else + enable_irq(chip->irqnum); + + return 0; +} + +static void tca6416_keys_close(struct input_dev *dev) +{ + struct tca6416_keypad_chip *chip = input_get_drvdata(dev); + + if (chip->use_polling) + cancel_delayed_work_sync(&chip->dwork); + else + disable_irq(chip->irqnum); +} + +static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip) +{ + int error; + + error = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output); + if (error) + return error; + + error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); + if (error) + return error; + + /* ensure that keypad pins are set to input */ + error = tca6416_write_reg(chip, TCA6416_DIRECTION, + chip->reg_direction | chip->pinmask); + if (error) + return error; + + error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); + if (error) + return error; + + error = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input); + if (error) + return error; + + chip->reg_input &= chip->pinmask; + + return 0; +} + +static int __devinit tca6416_keypad_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tca6416_keys_platform_data *pdata; + struct tca6416_keypad_chip *chip; + struct input_dev *input; + int error; + int i; + + /* Check functionality */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + dev_err(&client->dev, "%s adapter not supported\n", + dev_driver_string(&client->adapter->dev)); + return -ENODEV; + } + + pdata = client->dev.platform_data; + if (!pdata) { + dev_dbg(&client->dev, "no platform data\n"); + return -EINVAL; + } + + chip = kzalloc(sizeof(struct tca6416_keypad_chip) + + pdata->nbuttons * sizeof(struct tca6416_button), + GFP_KERNEL); + input = input_allocate_device(); + if (!chip || !input) { + error = -ENOMEM; + goto fail1; + } + + chip->client = client; + chip->input = input; + chip->pinmask = pdata->pinmask; + chip->use_polling = pdata->use_polling; + + INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func); + + input->phys = "tca6416-keys/input0"; + input->name = client->name; + input->dev.parent = &client->dev; + + input->open = tca6416_keys_open; + input->close = tca6416_keys_close; + + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + + /* Enable auto repeat feature of Linux input subsystem */ + if (pdata->rep) + __set_bit(EV_REP, input->evbit); + + for (i = 0; i < pdata->nbuttons; i++) { + unsigned int type; + + chip->buttons[i] = pdata->buttons[i]; + type = (pdata->buttons[i].type) ?: EV_KEY; + input_set_capability(input, type, pdata->buttons[i].code); + } + + input_set_drvdata(input, chip); + + /* + * Initialize cached registers from their original values. + * we can't share this chip with another i2c master. + */ + error = tca6416_setup_registers(chip); + if (error) + goto fail1; + + if (!chip->use_polling) { + if (pdata->irq_is_gpio) + chip->irqnum = gpio_to_irq(client->irq); + else + chip->irqnum = client->irq; + + error = request_threaded_irq(chip->irqnum, NULL, + tca6416_keys_isr, + IRQF_TRIGGER_FALLING, + "tca6416-keypad", chip); + if (error) { + dev_dbg(&client->dev, + "Unable to claim irq %d; error %d\n", + chip->irqnum, error); + goto fail1; + } + disable_irq(chip->irqnum); + } + + error = input_register_device(input); + if (error) { + dev_dbg(&client->dev, + "Unable to register input device, error: %d\n", error); + goto fail2; + } + + i2c_set_clientdata(client, chip); + + return 0; + +fail2: + if (!chip->use_polling) { + free_irq(chip->irqnum, chip); + enable_irq(chip->irqnum); + } +fail1: + input_free_device(input); + kfree(chip); + return error; +} + +static int __devexit tca6416_keypad_remove(struct i2c_client *client) +{ + struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); + + if (!chip->use_polling) { + free_irq(chip->irqnum, chip); + enable_irq(chip->irqnum); + } + + input_unregister_device(chip->input); + kfree(chip); + + i2c_set_clientdata(client, NULL); + + return 0; +} + + +static struct i2c_driver tca6416_keypad_driver = { + .driver = { + .name = "tca6416-keypad", + }, + .probe = tca6416_keypad_probe, + .remove = __devexit_p(tca6416_keypad_remove), + .id_table = tca6416_id, +}; + +static int __init tca6416_keypad_init(void) +{ + return i2c_add_driver(&tca6416_keypad_driver); +} + +subsys_initcall(tca6416_keypad_init); + +static void __exit tca6416_keypad_exit(void) +{ + i2c_del_driver(&tca6416_keypad_driver); +} +module_exit(tca6416_keypad_exit); + +MODULE_AUTHOR("Sriramakrishnan "); +MODULE_DESCRIPTION("Keypad driver over tca6146 IO expander"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 26a6931ba7656dc0ebebee615ba87db8a8e71f2b Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Sat, 24 Apr 2010 21:41:05 -0700 Subject: Input: joydev - allow binding to button-only devices Dance pads don't have an axis, so allow this kind of controllers to be used via legacy joystick interface. Signed-off-by: Christoph Fritz Signed-off-by: Dmitry Torokhov --- drivers/input/joydev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index c52bec4d053..423e0e6031a 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = { .evbit = { BIT_MASK(EV_ABS) }, .absbit = { BIT_MASK(ABS_THROTTLE) }, }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_TRIGGER_HAPPY)] = BIT_MASK(BTN_TRIGGER_HAPPY) }, + }, { } /* Terminating entry */ }; -- cgit v1.2.2 From 29453932d8a2ba9f1bf25a951c1b76b9fe86d1b6 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 28 Apr 2010 01:10:50 +0000 Subject: input: serio: add support for Amstrad Delta serial keyboardport The patch introduces a serio driver that supports a keyboard serial port found on the Amstrad Delta videophone board. After initializing the hardware, the driver reads its input data from a buffer filled in by the board FIQ (Fast Interrupt Request) handler. Standard AT keyboard driver (atkbd) will be used on top of the serio layer for handling the E3 keyboard (called mailboard) connected to the port. Since the device generated scancodes differ from what the atkbd expects, a custom key code to scan code table must be loaded from userspace for the keyboard to be useable. Signed-off-by: Janusz Krzysztofik Acked-by: Dmitry Torokhov Signed-off-by: Tony Lindgren --- drivers/input/serio/Kconfig | 16 +++ drivers/input/serio/Makefile | 1 + drivers/input/serio/ams_delta_serio.c | 177 ++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/input/serio/ams_delta_serio.c (limited to 'drivers/input') diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 7e319d65ec5..f34f1dbeb57 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -209,4 +209,20 @@ config SERIO_ALTERA_PS2 To compile this driver as a module, choose M here: the module will be called altera_ps2. +config SERIO_AMS_DELTA + tristate "Amstrad Delta (E3) mailboard support" + depends on MACH_AMS_DELTA + default y + select AMS_DELTA_FIQ + ---help--- + Say Y here if you have an E3 and want to use its mailboard, + or any standard AT keyboard connected to the mailboard port. + + When used for the E3 mailboard, a non-standard key table + must be loaded from userspace, possibly using udev extras + provided keymap helper utility. + + To compile this driver as a module, choose M here; + the module will be called ams_delta_serio. + endif diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index bf945f789d0..84c80bf7185 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -21,5 +21,6 @@ obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o obj-$(CONFIG_SERIO_LIBPS2) += libps2.o obj-$(CONFIG_SERIO_RAW) += serio_raw.o +obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c new file mode 100644 index 00000000000..8f1770e1e08 --- /dev/null +++ b/drivers/input/serio/ams_delta_serio.c @@ -0,0 +1,177 @@ +/* + * Amstrad E3 (Delta) keyboard port driver + * + * Copyright (c) 2006 Matt Callow + * Copyright (c) 2010 Janusz Krzysztofik + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Thanks to Cliff Lawson for his help + * + * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial + * transmission. The keyboard port is formed of two GPIO lines, for clock + * and data. Due to strict timing requirements of the interface, + * the serial data stream is read and processed by a FIQ handler. + * The resulting words are fetched by this driver from a circular buffer. + * + * Standard AT keyboard driver (atkbd) is used for handling the keyboard data. + * However, when used with the E3 mailboard that producecs non-standard + * scancodes, a custom key table must be prepared and loaded from userspace. + */ +#include +#include +#include +#include + +#include +#include + +#include + +MODULE_AUTHOR("Matt Callow"); +MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver"); +MODULE_LICENSE("GPL"); + +static struct serio *ams_delta_serio; + +static int check_data(int data) +{ + int i, parity = 0; + + /* check valid stop bit */ + if (!(data & 0x400)) { + dev_warn(&ams_delta_serio->dev, + "invalid stop bit, data=0x%X\n", + data); + return SERIO_FRAME; + } + /* calculate the parity */ + for (i = 1; i < 10; i++) { + if (data & (1 << i)) + parity++; + } + /* it should be odd */ + if (!(parity & 0x01)) { + dev_warn(&ams_delta_serio->dev, + "paritiy check failed, data=0x%X parity=0x%X\n", + data, parity); + return SERIO_PARITY; + } + return 0; +} + +static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id) +{ + int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF]; + int data, dfl; + u8 scancode; + + fiq_buffer[FIQ_IRQ_PEND] = 0; + + /* + * Read data from the circular buffer, check it + * and then pass it on the serio + */ + while (fiq_buffer[FIQ_KEYS_CNT] > 0) { + + data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++]; + fiq_buffer[FIQ_KEYS_CNT]--; + if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN]) + fiq_buffer[FIQ_HEAD_OFFSET] = 0; + + dfl = check_data(data); + scancode = (u8) (data >> 1) & 0xFF; + serio_interrupt(ams_delta_serio, scancode, dfl); + } + return IRQ_HANDLED; +} + +static int ams_delta_serio_open(struct serio *serio) +{ + /* enable keyboard */ + ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, + AMD_DELTA_LATCH2_KEYBRD_PWR); + + return 0; +} + +static void ams_delta_serio_close(struct serio *serio) +{ + /* disable keyboard */ + ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, 0); +} + +static int __init ams_delta_serio_init(void) +{ + int err; + + if (!machine_is_ams_delta()) + return -ENODEV; + + ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!ams_delta_serio) + return -ENOMEM; + + ams_delta_serio->id.type = SERIO_8042; + ams_delta_serio->open = ams_delta_serio_open; + ams_delta_serio->close = ams_delta_serio_close; + strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter", + sizeof(ams_delta_serio->name)); + strlcpy(ams_delta_serio->phys, "GPIO/serio0", + sizeof(ams_delta_serio->phys)); + + err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_DATA, "serio-data"); + if (err) { + pr_err("ams_delta_serio: Couldn't request gpio pin for data\n"); + goto serio; + } + gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); + + err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_CLK, "serio-clock"); + if (err) { + pr_err("ams_delta_serio: couldn't request gpio pin for clock\n"); + goto gpio_data; + } + gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); + + err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), + ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING, + "ams-delta-serio", 0); + if (err < 0) { + pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n", + gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); + goto gpio_clk; + } + /* + * Since GPIO register handling for keyboard clock pin is performed + * at FIQ level, switch back from edge to simple interrupt handler + * to avoid bad interaction. + */ + set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), + handle_simple_irq); + + serio_register_port(ams_delta_serio); + dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name); + + return 0; +gpio_clk: + gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); +gpio_data: + gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); +serio: + kfree(ams_delta_serio); + return err; +} +module_init(ams_delta_serio_init); + +static void __exit ams_delta_serio_exit(void) +{ + serio_unregister_port(ams_delta_serio); + free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); + gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); + gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); + kfree(ams_delta_serio); +} +module_exit(ams_delta_serio_exit); -- cgit v1.2.2 From d861f7bf14808b9f457cb32c34585e97df60f140 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 May 2010 15:35:11 -0700 Subject: Input: iforce - add Guillemot Jet Leader Force Feedback This device features a RUDDER on the knob. Signed-off-by: Marek Vasut Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 4 ++++ drivers/input/joystick/iforce/iforce-usb.c | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b1edd778639..5956d89b1d3 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -54,6 +54,9 @@ static signed short btn_avb_wheel[] = static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; +static signed short abs_joystick_rudder[] = +{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 }; + static signed short abs_avb_pegasus[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 }; @@ -76,6 +79,7 @@ static struct iforce_device iforce_device[] = { { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? + { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b41303d3ec5..6c96631ae5d 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -212,6 +212,7 @@ static struct usb_device_id iforce_usb_ids [] = { { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ + { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ { } /* Terminating entry */ -- cgit v1.2.2 From 513d8be9883fe0a7a73d216c7cecd20e7c9effda Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 May 2010 15:35:11 -0700 Subject: Input: iforce - fix Guillemot Jet Leader 3D entry USB ID entry for "Guillemot Jet Leader 3D" in iforce-main.c did not match one used in iforce-usb.c Signed-off-by: Marek Vasut Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 5956d89b1d3..405febd94f2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -81,7 +81,7 @@ static struct iforce_device iforce_device[] = { { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? - { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? + { 0x06f8, 0xa302, "Guillemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; -- cgit v1.2.2 From 5700929d2209c5e2038f340bacc91e9818439cdf Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 15 Mar 2010 22:23:09 +0800 Subject: input: remove now deprecated corgi_ts.c touchscreen driver The corgi touchscreen is now deprecated in favour of the generic ads7846.c driver. The noise reduction technique used in corgi_ts.c, which is to wait till vsync before ADC sampling, is also integrated into ads7846 driver now. Provided that the original driver is not generic and is difficult to maintain, it will be removed now. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Pavel Machek Cc: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 16 -- drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/corgi_ts.c | 385 ----------------------------------- 3 files changed, 402 deletions(-) delete mode 100644 drivers/input/touchscreen/corgi_ts.c (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a..3d1ade2e519 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY To compile this driver as a module, choose M here: the module will be called h3600_ts_input. -config TOUCHSCREEN_CORGI - tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" - depends on PXA_SHARPSL - select CORGI_SSP_DEPRECATED - help - Say Y here to enable the driver for the touchscreen on the - Sharp SL-C7xx and SL-Cxx00 series of PDAs. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called corgi_ts. - - NOTE: this driver is deprecated, try enable SPI and generic - ADS7846-based touchscreen driver. - config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca2..41145d074de 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439..00000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models - * - * Copyright (c) 2004-2005 Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define PWR_MODE_ACTIVE 0 -#define PWR_MODE_SUSPEND 1 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 15000 - -struct ts_event { - short pressure; - short x; - short y; -}; - -struct corgi_ts { - struct input_dev *input; - struct timer_list timer; - struct ts_event tc; - int pendown; - int power_mode; - int irq_gpio; - struct corgits_machinfo *machinfo; -}; - -#ifdef CONFIG_PXA25x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) -#endif -#ifdef CONFIG_PXA27x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) -#endif - -/* ADS7846 Touch Screen Controller bit definitions */ -#define ADSCTRL_PD0 (1u << 0) /* PD0 */ -#define ADSCTRL_PD1 (1u << 1) /* PD1 */ -#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ -#define ADSCTRL_MOD (1u << 3) /* Mode */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS (1u << 7) /* Start Bit */ - -/* External Functions */ -extern unsigned int get_clk_frequency_khz(int info); - -static unsigned long calc_waittime(struct corgi_ts *corgi_ts) -{ - unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); - - if (hsync_invperiod) - return get_clk_frequency_khz(0)*1000/hsync_invperiod; - else - return 0; -} - -static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, - unsigned int address, unsigned long wait_time) -{ - unsigned long timer1 = 0, timer2, pmnc = 0; - int pos = 0; - - if (wait_time && doSend) { - PMNC_GET(pmnc); - if (!(pmnc & 0x01)) - PMNC_SET(0x01); - - /* polling HSync */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - } - - if (doRecive) - pos = corgi_ssp_ads7846_get(); - - if (doSend) { - int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; - /* dummy command */ - corgi_ssp_ads7846_put(cmd); - corgi_ssp_ads7846_get(); - - if (wait_time) { - /* Wait after HSync */ - CCNT(timer2); - if (timer2-timer1 > wait_time) { - /* too slow - timeout, try again */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - /* Wait after HSync */ - CCNT(timer2); - } - while (timer2 - timer1 < wait_time) - CCNT(timer2); - } - corgi_ssp_ads7846_put(cmd); - if (wait_time && !(pmnc & 0x01)) - PMNC_SET(pmnc); - } - return pos; -} - -static int read_xydata(struct corgi_ts *corgi_ts) -{ - unsigned int x, y, z1, z2; - unsigned long flags, wait_time; - - /* critical section */ - local_irq_save(flags); - corgi_ssp_ads7846_lock(); - wait_time = calc_waittime(corgi_ts); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); - - /* X-axis */ - y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); - - /* Z1 */ - x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); - - /* Z2 */ - z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); - z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); - - /* Power-Down Enable */ - corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - corgi_ssp_ads7846_get(); - - corgi_ssp_ads7846_unlock(); - local_irq_restore(flags); - - if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { - corgi_ts->tc.pressure = 0; - return 0; - } - - corgi_ts->tc.x = x; - corgi_ts->tc.y = y; - corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; - return 1; -} - -static void new_data(struct corgi_ts *corgi_ts) -{ - struct input_dev *dev = corgi_ts->input; - - if (corgi_ts->power_mode != PWR_MODE_ACTIVE) - return; - - if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) - return; - - input_report_abs(dev, ABS_X, corgi_ts->tc.x); - input_report_abs(dev, ABS_Y, corgi_ts->tc.y); - input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); - input_sync(dev); -} - -static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) -{ - if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { - /* Disable Interrupt */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); - if (read_xydata(corgi_ts)) { - corgi_ts->pendown = 1; - new_data(corgi_ts); - } - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - } else { - if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - corgi_ts->pendown++; - return; - } - - if (corgi_ts->pendown) { - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - } - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->pendown = 0; - } -} - -static void corgi_ts_timer(unsigned long data) -{ - struct corgi_ts *corgits_data = (struct corgi_ts *) data; - - ts_interrupt_main(corgits_data, 1); -} - -static irqreturn_t ts_interrupt(int irq, void *dev_id) -{ - struct corgi_ts *corgits_data = dev_id; - - ts_interrupt_main(corgits_data, 0); - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM -static int corgits_suspend(struct platform_device *dev, pm_message_t state) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - if (corgi_ts->pendown) { - del_timer_sync(&corgi_ts->timer); - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - corgi_ts->pendown = 0; - } - corgi_ts->power_mode = PWR_MODE_SUSPEND; - - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - - return 0; -} - -static int corgits_resume(struct platform_device *dev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - return 0; -} -#else -#define corgits_suspend NULL -#define corgits_resume NULL -#endif - -static int __devinit corgits_probe(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts; - struct input_dev *input_dev; - int err = -ENOMEM; - - corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgi_ts || !input_dev) - goto fail1; - - platform_set_drvdata(pdev, corgi_ts); - - corgi_ts->machinfo = pdev->dev.platform_data; - corgi_ts->irq_gpio = platform_get_irq(pdev, 0); - - if (corgi_ts->irq_gpio < 0) { - err = -ENODEV; - goto fail1; - } - - corgi_ts->input = input_dev; - - init_timer(&corgi_ts->timer); - corgi_ts->timer.data = (unsigned long) corgi_ts; - corgi_ts->timer.function = corgi_ts_timer; - - input_dev->name = "Corgi Touchscreen"; - input_dev->phys = "corgits/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0002; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); - - pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); - - /* Initiaize ADS7846 Difference Reference mode */ - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - - if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { - err = -EBUSY; - goto fail1; - } - - err = input_register_device(corgi_ts->input); - if (err) - goto fail2; - - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - - return 0; - - fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); - fail1: input_free_device(input_dev); - kfree(corgi_ts); - return err; -} - -static int __devexit corgits_remove(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - - free_irq(corgi_ts->irq_gpio, corgi_ts); - del_timer_sync(&corgi_ts->timer); - corgi_ts->machinfo->put_hsync(); - input_unregister_device(corgi_ts->input); - kfree(corgi_ts); - - return 0; -} - -static struct platform_driver corgits_driver = { - .probe = corgits_probe, - .remove = __devexit_p(corgits_remove), - .suspend = corgits_suspend, - .resume = corgits_resume, - .driver = { - .name = "corgi-ts", - .owner = THIS_MODULE, - }, -}; - -static int __init corgits_init(void) -{ - return platform_driver_register(&corgits_driver); -} - -static void __exit corgits_exit(void) -{ - platform_driver_unregister(&corgits_driver); -} - -module_init(corgits_init); -module_exit(corgits_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:corgi-ts"); -- cgit v1.2.2 From cb8f3c7dea960c27fcc66830cdaab82b13f1b597 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 14:43:03 +0800 Subject: [ARM] pxa/tosa: move CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES to mach/Kconfig Tosa is now able to use generic matrix keypad driver instead of the deprecated tosakbd.c, where CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES is still useful. Move it to mach/Kconfig. Signed-off-by: Eric Miao --- drivers/input/keyboard/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c102355f5..a74ee121f51 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -426,16 +426,6 @@ config KEYBOARD_TOSA To compile this driver as a module, choose M here: the module will be called tosakbd. -config KEYBOARD_TOSA_USE_EXT_KEYCODES - bool "Tosa keyboard: use extended keycodes" - depends on KEYBOARD_TOSA - help - Say Y here to enable the tosa keyboard driver to generate extended - (>= 127) keycodes. Be aware, that they can't be correctly interpreted - by either console keyboard driver or by Kdrive keybd driver. - - Say Y only if you know, what you are doing! - config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO -- cgit v1.2.2 From 25646d70a0d386ab923a189f9790aeae3eb4f1b5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 14:50:54 +0800 Subject: input: remove obsolete {corgi,spitz,tosa}kbd.c Signed-off-by: Eric Miao --- drivers/input/keyboard/Kconfig | 38 --- drivers/input/keyboard/Makefile | 3 - drivers/input/keyboard/corgikbd.c | 414 ------------------------------- drivers/input/keyboard/spitzkbd.c | 496 -------------------------------------- drivers/input/keyboard/tosakbd.c | 431 --------------------------------- 5 files changed, 1382 deletions(-) delete mode 100644 drivers/input/keyboard/corgikbd.c delete mode 100644 drivers/input/keyboard/spitzkbd.c delete mode 100644 drivers/input/keyboard/tosakbd.c (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a74ee121f51..a8293388d01 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -143,19 +143,6 @@ config KEYBOARD_BFIN To compile this driver as a module, choose M here: the module will be called bf54x-keys. -config KEYBOARD_CORGI - tristate "Corgi keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx - series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called corgikbd. - config KEYBOARD_LKKBD tristate "DECstation/VAXstation LK201/LK401 keyboard" select SERIO @@ -339,19 +326,6 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_SPITZ - tristate "Spitz keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called spitzkbd. - config KEYBOARD_STOWAWAY tristate "Stowaway keyboard" select SERIO @@ -414,18 +388,6 @@ config KEYBOARD_TWL4030 To compile this driver as a module, choose M here: the module will be called twl4030_keypad. -config KEYBOARD_TOSA - tristate "Tosa keyboard (deprecated)" - depends on MACH_TOSA - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called tosakbd. - config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5ed5f..9a74127e4d1 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o -obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o @@ -33,10 +32,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o -obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o -obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a8e6b..00000000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Keyboard driver for Sharp Corgi models (SL-C7xx) - * - * Copyright (c) 2004-2005 Richard Purdie - * - * Based on xtkbd.c/locomkbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define KB_ROWS 8 -#define KB_COLS 12 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -/* zero code, 124 scancodes */ -#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (250) /* ms */ - -#define CORGI_KEY_CALENDER KEY_F1 -#define CORGI_KEY_ADDRESS KEY_F2 -#define CORGI_KEY_FN KEY_F3 -#define CORGI_KEY_CANCEL KEY_F4 -#define CORGI_KEY_OFF KEY_SUSPEND -#define CORGI_KEY_EXOK KEY_F5 -#define CORGI_KEY_EXCANCEL KEY_F6 -#define CORGI_KEY_EXJOGDOWN KEY_F7 -#define CORGI_KEY_EXJOGUP KEY_F8 -#define CORGI_KEY_JAP1 KEY_LEFTCTRL -#define CORGI_KEY_JAP2 KEY_LEFTALT -#define CORGI_KEY_MAIL KEY_F10 -#define CORGI_KEY_OK KEY_F11 -#define CORGI_KEY_MENU KEY_F12 - -static unsigned char corgikbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ - CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ - CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ -}; - - -struct corgikbd { - unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; - struct input_dev *input; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void corgikbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; -} - -static inline void corgikbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; - GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; -} - -static inline void corgikbd_activate_col(int col) -{ - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = CORGI_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -static inline void corgikbd_reset_col(int col) -{ - /* STROBE col -> Low */ - GPCR2 = CORGI_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) - -/* - * The corgi keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed; - - if (corgikbd_data->suspended) - return; - - spin_lock_irqsave(&corgikbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - corgikbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - corgikbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - - if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) - && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { - input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); - corgikbd_data->suspend_jiffies=jiffies; - } - } - corgikbd_reset_col(col); - } - - corgikbd_activate_all(); - - input_sync(corgikbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); -} - -/* - * corgi keyboard interrupt handler. - */ -static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) -{ - struct corgikbd *corgikbd_data = dev_id; - - if (!timer_pending(&corgikbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - corgikbd_scankeyboard(corgikbd_data); - } - - return IRQ_HANDLED; -} - -/* - * corgi timer checking for released keys - */ -static void corgikbd_timer_callback(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - corgikbd_scankeyboard(corgikbd_data); -} - -/* - * The hinge switches generate no interrupt so they need to be - * monitored by a timer. - * - * We debounce the switches and pass them to the input system. - * - * gprr == 0x00 - Keyboard with Landscape Screen - * 0x08 - No Keyboard with Portrait Screen - * 0x0c - Keyboard and Screen Closed - */ - -#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void corgikbd_hinge_timer(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - unsigned long gprr; - unsigned long flags; - - gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); - gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); - if (gprr != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = gprr; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&corgikbd_data->lock, flags); - - input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); - input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); - input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); - input_sync(corgikbd_data->input); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); - } - } - mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); -} - -#ifdef CONFIG_PM -static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - corgikbd->suspended = 1; - /* strobe 0 is the power key so this can't be made an input for - powersaving therefore i = 1 */ - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); - - return 0; -} - -static int corgikbd_resume(struct platform_device *dev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - corgikbd->suspend_jiffies=jiffies; - corgikbd->suspended = 0; - - return 0; -} -#else -#define corgikbd_suspend NULL -#define corgikbd_resume NULL -#endif - -static int __devinit corgikbd_probe(struct platform_device *pdev) -{ - struct corgikbd *corgikbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgikbd || !input_dev) - goto fail; - - platform_set_drvdata(pdev, corgikbd); - - corgikbd->input = input_dev; - spin_lock_init(&corgikbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&corgikbd->timer); - corgikbd->timer.function = corgikbd_timer_callback; - corgikbd->timer.data = (unsigned long) corgikbd; - - /* Init Hinge Timer */ - init_timer(&corgikbd->htimer); - corgikbd->htimer.function = corgikbd_hinge_timer; - corgikbd->htimer.data = (unsigned long) corgikbd; - - corgikbd->suspend_jiffies=jiffies; - - memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); - - input_dev->name = "Corgi Keyboard"; - input_dev->phys = "corgikbd/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = corgikbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); - - for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) - set_bit(corgikbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(corgikbd->input); - if (err) - goto fail; - - mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); - if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "corgikbd", corgikbd)) - printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Setup the headphone jack as an input */ - pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); - - return 0; - - fail: input_free_device(input_dev); - kfree(corgikbd); - return err; -} - -static int __devexit corgikbd_remove(struct platform_device *pdev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(pdev); - - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) - free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); - - del_timer_sync(&corgikbd->htimer); - del_timer_sync(&corgikbd->timer); - - input_unregister_device(corgikbd->input); - - kfree(corgikbd); - - return 0; -} - -static struct platform_driver corgikbd_driver = { - .probe = corgikbd_probe, - .remove = __devexit_p(corgikbd_remove), - .suspend = corgikbd_suspend, - .resume = corgikbd_resume, - .driver = { - .name = "corgi-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init corgikbd_init(void) -{ - return platform_driver_register(&corgikbd_driver); -} - -static void __exit corgikbd_exit(void) -{ - platform_driver_unregister(&corgikbd_driver); -} - -module_init(corgikbd_init); -module_exit(corgikbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:corgi-keyboard"); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 13967422658..00000000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) - * - * Copyright (c) 2005 Richard Purdie - * - * Based on corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWS 7 -#define KB_COLS 11 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES ((KB_ROWS<<4) + 1) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (150) /* ms */ - -#define SPITZ_KEY_CALENDER KEY_F1 -#define SPITZ_KEY_ADDRESS KEY_F2 -#define SPITZ_KEY_FN KEY_F3 -#define SPITZ_KEY_CANCEL KEY_F4 -#define SPITZ_KEY_EXOK KEY_F5 -#define SPITZ_KEY_EXCANCEL KEY_F6 -#define SPITZ_KEY_EXJOGDOWN KEY_F7 -#define SPITZ_KEY_EXJOGUP KEY_F8 -#define SPITZ_KEY_JAP1 KEY_LEFTALT -#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL -#define SPITZ_KEY_SYNC KEY_F9 -#define SPITZ_KEY_MAIL KEY_F10 -#define SPITZ_KEY_OK KEY_F11 -#define SPITZ_KEY_MENU KEY_F12 - -static unsigned char spitzkbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ - SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ -}; - -static int spitz_strobes[] = { - SPITZ_GPIO_KEY_STROBE0, - SPITZ_GPIO_KEY_STROBE1, - SPITZ_GPIO_KEY_STROBE2, - SPITZ_GPIO_KEY_STROBE3, - SPITZ_GPIO_KEY_STROBE4, - SPITZ_GPIO_KEY_STROBE5, - SPITZ_GPIO_KEY_STROBE6, - SPITZ_GPIO_KEY_STROBE7, - SPITZ_GPIO_KEY_STROBE8, - SPITZ_GPIO_KEY_STROBE9, - SPITZ_GPIO_KEY_STROBE10, -}; - -static int spitz_senses[] = { - SPITZ_GPIO_KEY_SENSE0, - SPITZ_GPIO_KEY_SENSE1, - SPITZ_GPIO_KEY_SENSE2, - SPITZ_GPIO_KEY_SENSE3, - SPITZ_GPIO_KEY_SENSE4, - SPITZ_GPIO_KEY_SENSE5, - SPITZ_GPIO_KEY_SENSE6, -}; - -struct spitzkbd { - unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; - struct input_dev *input; - char phys[32]; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 11 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void spitzkbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; -} - -static inline void spitzkbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; - GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; - GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; - GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; - GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; - GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; - GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; -} - -static inline void spitzkbd_activate_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPSR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline void spitzkbd_reset_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPCR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline int spitzkbd_get_row_status(int col) -{ - return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) - | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) - | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); -} - -/* - * The spitz keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); - - if (spitzkbd_data->suspended) - return; - - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - spitzkbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - spitzkbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = spitzkbd_get_row_status(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - } - spitzkbd_reset_col(col); - } - - spitzkbd_activate_all(); - - input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); - input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); - - if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { - input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); - spitzkbd_data->suspend_jiffies = jiffies; - } - - input_sync(spitzkbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); -} - -/* - * spitz keyboard interrupt handler. - */ -static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - spitzkbd_scankeyboard(spitzkbd_data); - } - - return IRQ_HANDLED; -} - -/* - * spitz timer checking for released keys - */ -static void spitzkbd_timer_callback(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - - spitzkbd_scankeyboard(spitzkbd_data); -} - -/* - * The hinge switches generate an interrupt. - * We debounce the switches and pass them to the input system. - */ - -static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->htimer)) - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - return IRQ_HANDLED; -} - -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void spitzkbd_hinge_timer(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - unsigned long state; - unsigned long flags; - - state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); - state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); - if (state != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = state; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - } - - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); - input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); - input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); - input_sync(spitzkbd_data->input); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); - } else { - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - } -} - -#ifdef CONFIG_PM -static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - spitzkbd->suspended = 1; - - /* Set Strobe lines as inputs - *except* strobe line 0 leave this - enabled so we can detect a power button press for resume */ - for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); - - return 0; -} - -static int spitzkbd_resume(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - spitzkbd->suspend_jiffies = jiffies; - spitzkbd->suspended = 0; - - return 0; -} -#else -#define spitzkbd_suspend NULL -#define spitzkbd_resume NULL -#endif - -static int __devinit spitzkbd_probe(struct platform_device *dev) -{ - struct spitzkbd *spitzkbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!spitzkbd || !input_dev) - goto fail; - - platform_set_drvdata(dev, spitzkbd); - strcpy(spitzkbd->phys, "spitzkbd/input0"); - - spin_lock_init(&spitzkbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&spitzkbd->timer); - spitzkbd->timer.function = spitzkbd_timer_callback; - spitzkbd->timer.data = (unsigned long) spitzkbd; - - /* Init Hinge Timer */ - init_timer(&spitzkbd->htimer); - spitzkbd->htimer.function = spitzkbd_hinge_timer; - spitzkbd->htimer.data = (unsigned long) spitzkbd; - - spitzkbd->suspend_jiffies = jiffies; - - spitzkbd->input = input_dev; - - input_dev->name = "Spitz Keyboard"; - input_dev->phys = spitzkbd->phys; - input_dev->dev.parent = &dev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = spitzkbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); - - memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); - for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) - set_bit(spitzkbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(KEY_SUSPEND, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(input_dev); - if (err) - goto fail; - - mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(spitz_senses[i] | GPIO_IN); - if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, - IRQF_DISABLED|IRQF_TRIGGER_RISING, - "Spitzkbd Sense", spitzkbd)) - printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); - - request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd Sync", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd PwrOn", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWA", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWB", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd HP", spitzkbd); - - return 0; - - fail: input_free_device(input_dev); - kfree(spitzkbd); - return err; -} - -static int __devexit spitzkbd_remove(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) - free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); - - free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); - - del_timer_sync(&spitzkbd->htimer); - del_timer_sync(&spitzkbd->timer); - - input_unregister_device(spitzkbd->input); - - kfree(spitzkbd); - - return 0; -} - -static struct platform_driver spitzkbd_driver = { - .probe = spitzkbd_probe, - .remove = __devexit_p(spitzkbd_remove), - .suspend = spitzkbd_suspend, - .resume = spitzkbd_resume, - .driver = { - .name = "spitz-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init spitzkbd_init(void) -{ - return platform_driver_register(&spitzkbd_driver); -} - -static void __exit spitzkbd_exit(void) -{ - platform_driver_unregister(&spitzkbd_driver); -} - -module_init(spitzkbd_init); -module_exit(spitzkbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Spitz Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:spitz-keyboard"); diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f269cfc..00000000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Keyboard driver for Sharp Tosa models (SL-6000x) - * - * Copyright (c) 2005 Dirk Opfer - * Copyright (c) 2007 Dmitry Baryshkov - * - * Based on xtkbd.c/locomkbd.c/corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r, c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 - -#define SCAN_INTERVAL (HZ/10) - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -static unsigned short tosakbd_keycode[NR_SCANCODES] = { -0, -0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, -KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, -KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, -0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, -KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, -0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, -KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, -0, 0, 0, -}; - -struct tosakbd { - unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; - struct input_dev *input; - bool suspended; - spinlock_t lock; /* protect kbd scanning */ - struct timer_list timer; -}; - - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) - -static inline void tosakbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; - GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; -} - -static inline void tosakbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; - GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* STATE CLEAR */ - GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; -} - -static inline void tosakbd_activate_col(int col) -{ - if (col <= 5) { - /* STROBE col -> High, not col -> HiZ */ - GPSR1 = TOSA_GPIO_STROBE_BIT(col); - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = TOSA_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} - -static inline void tosakbd_reset_col(int col) -{ - if (col <= 5) { - /* STROBE col -> Low */ - GPCR1 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> Low */ - GPCR2 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} -/* - * The tosa keyboard only generates interrupts when a key is pressed. - * So when a key is pressed, we enable a timer. This timer scans the - * keyboard, and this is how we detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void tosakbd_scankeyboard(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed = 0; - - spin_lock_irqsave(&tosakbd->lock, flags); - - if (tosakbd->suspended) - goto out; - - for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - tosakbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - tosakbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - - for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { - unsigned int scancode, pressed; - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - if (pressed && !tosakbd->keycode[scancode]) - dev_warn(&dev->dev, - "unhandled scancode: 0x%02x\n", - scancode); - - input_report_key(tosakbd->input, - tosakbd->keycode[scancode], - pressed); - if (pressed) - num_pressed++; - } - - tosakbd_reset_col(col); - } - - tosakbd_activate_all(); - - input_sync(tosakbd->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); - - out: - spin_unlock_irqrestore(&tosakbd->lock, flags); -} - -/* - * tosa keyboard interrupt handler. - */ -static irqreturn_t tosakbd_interrupt(int irq, void *__dev) -{ - struct platform_device *dev = __dev; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - if (!timer_pending(&tosakbd->timer)) { - /** wait chattering delay **/ - udelay(20); - tosakbd_scankeyboard(dev); - } - - return IRQ_HANDLED; -} - -/* - * tosa timer checking for released keys - */ -static void tosakbd_timer_callback(unsigned long __dev) -{ - struct platform_device *dev = (struct platform_device *)__dev; - - tosakbd_scankeyboard(dev); -} - -#ifdef CONFIG_PM -static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned long flags; - - spin_lock_irqsave(&tosakbd->lock, flags); - tosakbd->suspended = true; - spin_unlock_irqrestore(&tosakbd->lock, flags); - - del_timer_sync(&tosakbd->timer); - - return 0; -} - -static int tosakbd_resume(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - tosakbd->suspended = false; - tosakbd_scankeyboard(dev); - - return 0; -} -#else -#define tosakbd_suspend NULL -#define tosakbd_resume NULL -#endif - -static int __devinit tosakbd_probe(struct platform_device *pdev) { - - int i; - struct tosakbd *tosakbd; - struct input_dev *input_dev; - int error; - - tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); - if (!tosakbd) - return -ENOMEM; - - input_dev = input_allocate_device(); - if (!input_dev) { - kfree(tosakbd); - return -ENOMEM; - } - - platform_set_drvdata(pdev, tosakbd); - - spin_lock_init(&tosakbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&tosakbd->timer); - tosakbd->timer.function = tosakbd_timer_callback; - tosakbd->timer.data = (unsigned long) pdev; - - tosakbd->input = input_dev; - - input_set_drvdata(input_dev, tosakbd); - input_dev->name = "Tosa Keyboard"; - input_dev->phys = "tosakbd/input0"; - input_dev->dev.parent = &pdev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - input_dev->keycode = tosakbd->keycode; - input_dev->keycodesize = sizeof(tosakbd->keycode[0]); - input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); - - memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); - - for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) - __set_bit(tosakbd->keycode[i], input_dev->keybit); - __clear_bit(KEY_RESERVED, input_dev->keybit); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_SENSE(i); - int irq; - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail; - } - - error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - irq = gpio_to_irq(gpio); - if (irq < 0) { - error = irq; - printk(KERN_ERR "gpio-keys: Unable to get irq number" - " for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - error = request_irq(irq, tosakbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "tosakbd", pdev); - - if (error) { - printk("tosakbd: Can't get IRQ: %d: error %d!\n", - irq, error); - gpio_free(gpio); - goto fail; - } - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_STROBE(i); - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail2; - } - - error = gpio_direction_output(gpio, 1); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail2; - } - - } - - error = input_register_device(input_dev); - if (error) { - printk(KERN_ERR "tosakbd: Unable to register input device, " - "error: %d\n", error); - goto fail2; - } - - printk(KERN_INFO "input: Tosa Keyboard Registered\n"); - - return 0; - -fail2: - while (--i >= 0) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - i = TOSA_KEY_SENSE_NUM; -fail: - while (--i >= 0) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - platform_set_drvdata(pdev, NULL); - input_free_device(input_dev); - kfree(tosakbd); - - return error; -} - -static int __devexit tosakbd_remove(struct platform_device *dev) -{ - int i; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - del_timer_sync(&tosakbd->timer); - - input_unregister_device(tosakbd->input); - - kfree(tosakbd); - - return 0; -} - -static struct platform_driver tosakbd_driver = { - .probe = tosakbd_probe, - .remove = __devexit_p(tosakbd_remove), - .suspend = tosakbd_suspend, - .resume = tosakbd_resume, - .driver = { - .name = "tosa-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __devinit tosakbd_init(void) -{ - return platform_driver_register(&tosakbd_driver); -} - -static void __exit tosakbd_exit(void) -{ - platform_driver_unregister(&tosakbd_driver); -} - -module_init(tosakbd_init); -module_exit(tosakbd_exit); - -MODULE_AUTHOR("Dirk Opfer "); -MODULE_DESCRIPTION("Tosa Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tosa-keyboard"); -- cgit v1.2.2 From 504e8beed161bd11a2c6cbb8aaf352c14d39b5bb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 13 May 2010 00:41:15 -0700 Subject: Input: elantech - use all 3 bytes when checking version Apparently all 3 bytes returned by ETP_FW_VERSION_QUERY are significant and should be taken into account when matching hardware version/features. Tested-by: Eric Piel Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 24 ++++++++++++------------ drivers/input/mouse/elantech.h | 5 ++--- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 2cbf3fc4729..1ac12f7c872 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -184,7 +184,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) int fingers; static int old_fingers; - if (etd->fw_version_maj == 0x01) { + if (etd->fw_version < 0x020000) { /* * byte 0: D U p1 p2 1 p3 R L * byte 1: f 0 th tw x9 x8 y9 y8 @@ -226,7 +226,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - if ((etd->fw_version_maj == 0x01) && + if (etd->fw_version < 0x020000 && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { /* rocker up */ input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); @@ -320,7 +320,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) unsigned char p1, p2, p3; /* Parity bits are placed differently */ - if (etd->fw_version_maj == 0x01) { + if (etd->fw_version < 0x020000) { /* byte 0: D U p1 p2 1 p3 R L */ p1 = (packet[0] & 0x20) >> 5; p2 = (packet[0] & 0x10) >> 4; @@ -456,7 +456,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) switch (etd->hw_version) { case 1: /* Rocker button */ - if ((etd->fw_version_maj == 0x01) && + if (etd->fw_version < 0x020000 && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { __set_bit(BTN_FORWARD, dev->keybit); __set_bit(BTN_BACK, dev->keybit); @@ -685,15 +685,14 @@ int elantech_init(struct psmouse *psmouse) pr_err("elantech.c: failed to query firmware version.\n"); goto init_fail; } - etd->fw_version_maj = param[0]; - etd->fw_version_min = param[2]; + + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; /* * Assume every version greater than this is new EeePC style * hardware with 6 byte packets */ - if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) || - etd->fw_version_maj > 0x02) { + if (etd->fw_version >= 0x020030) { etd->hw_version = 2; /* For now show extra debug information */ etd->debug = 1; @@ -703,8 +702,9 @@ int elantech_init(struct psmouse *psmouse) etd->hw_version = 1; etd->paritycheck = 1; } - pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", - etd->hw_version, etd->fw_version_maj, etd->fw_version_min); + + pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", + etd->hw_version, param[0], param[1], param[2]); if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { pr_err("elantech.c: failed to query capabilities.\n"); @@ -719,8 +719,8 @@ int elantech_init(struct psmouse *psmouse) * a touch action starts causing the mouse cursor or scrolled page * to jump. Enable a workaround. */ - if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { - pr_info("elantech.c: firmware version 2.34 detected, " + if (etd->fw_version == 0x020022) { + pr_info("elantech.c: firmware version 2.0.34 detected, " "enabling jumpy cursor workaround\n"); etd->jumpy_cursor = 1; } diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index feac5f7af96..ac57bde1bb9 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -100,11 +100,10 @@ struct elantech_data { unsigned char reg_26; unsigned char debug; unsigned char capabilities; - unsigned char fw_version_maj; - unsigned char fw_version_min; - unsigned char hw_version; unsigned char paritycheck; unsigned char jumpy_cursor; + unsigned char hw_version; + unsigned int fw_version; unsigned char parity[256]; }; -- cgit v1.2.2 From ef110b24e28f36620f63dab94708a17c7e267358 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 13 May 2010 00:42:23 -0700 Subject: Input: psmouse - reset all types of mice before reconnecting Synaptics hardware requires resetting device after suspend to ram in order for the device to be operational. The reset lives in synaptics-specific reconnect handler, but it is not being invoked if synaptics support is disabled and the device is handled as a standard PS/2 device (bare or IntelliMouse protocol). Let's add reset into generic reconnect handler as well. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cbc80726494..a3c97315a47 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1394,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio) struct psmouse *psmouse = serio_get_drvdata(serio); struct psmouse *parent = NULL; struct serio_driver *drv = serio->drv; + unsigned char type; int rc = -1; if (!drv || !psmouse) { @@ -1413,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio) if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) goto out; - } else if (psmouse_probe(psmouse) < 0 || - psmouse->type != psmouse_extensions(psmouse, - psmouse_max_proto, false)) { - goto out; + } else { + psmouse_reset(psmouse); + + if (psmouse_probe(psmouse) < 0) + goto out; + + type = psmouse_extensions(psmouse, psmouse_max_proto, false); + if (psmouse->type != type) + goto out; } /* ok, the device type (and capabilities) match the old one, -- cgit v1.2.2 From 3843384a055496dfed3c93ae883d964d8290fdab Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 13 May 2010 00:42:23 -0700 Subject: Input: ad7877 - keep dma rx buffers in seperate cache lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With dma based spi transmission, data corruption is observed occasionally. With dma buffers located right next to msg and xfer fields, cache lines correctly flushed in preparation for dma usage may be polluted again when writing to fields in the same cache line. Make sure cache fields used with dma do not share cache lines with fields changed during dma handling. As both fields are part of a struct that is allocated via kzalloc, thus cache aligned, moving the fields to the 1st position and insert padding for alignment does the job. Signed-off-by: Oskar Schirmer Signed-off-by: Daniel Glöckner Signed-off-by: Oliver Schneidewind Signed-off-by: Johannes Weiner Acked-by: Mike Frysinger [dtor@mail.ru - changed to use ___cacheline_aligned as suggested by akpm] Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7877.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e019d53d1ab..0d2d7e54b46 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -156,9 +156,14 @@ struct ser_req { u16 reset; u16 ref_on; u16 command; - u16 sample; struct spi_message msg; struct spi_transfer xfer[6]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u16 sample ____cacheline_aligned; }; struct ad7877 { @@ -182,8 +187,6 @@ struct ad7877 { u8 averaging; u8 pen_down_acc_interval; - u16 conversion_data[AD7877_NR_SENSE]; - struct spi_transfer xfer[AD7877_NR_SENSE + 2]; struct spi_message msg; @@ -195,6 +198,12 @@ struct ad7877 { spinlock_t lock; struct timer_list timer; /* P: lock */ unsigned pending:1; /* P: lock */ + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned; }; static int gpio3; -- cgit v1.2.2 From 73e59b1d6b69f5ae02e3be5e2b3259c46d8bb27a Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 4 May 2010 13:12:41 +0200 Subject: ARM: SAMSUNG: Move mach/ts.h to plat/ts.h This moves mach-s3c2410/include/mach/ts.h to plat-samsung/include/plat/ts.h in order to prepare for s3c64xx support in the touchscreen driver. Signed-off-by: Maurus Cuelenaere Signed-off-by: Ben Dooks --- drivers/input/touchscreen/s3c2410_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 98a7d127948..a2e122878f3 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -37,9 +37,9 @@ #include #include +#include #include -#include #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) -- cgit v1.2.2 From 658ad39ea91d8f0597654032a768930497161a58 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Tue, 18 May 2010 20:44:38 +0900 Subject: Input: s3c24xx_ts - Implement generic GPIO configuration callback This patch implements generic GPIO configuration function in Samsung touchscreen driver. And makes the touchscreen driver s3c24xx-ts.c generic to all the Samsung SoCs. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim [ben-linux@fluff.org: fixed title ] Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index a2e122878f3..86086a42d5e 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -39,8 +39,6 @@ #include #include -#include - #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) #define INT_DOWN (0) @@ -87,21 +85,6 @@ struct s3c2410ts { static struct s3c2410ts ts; -/** - * s3c2410_ts_connect - configure gpio for s3c2410 systems - * - * Configure the GPIO for the S3C2410 system, where we have external FETs - * connected to the device (later systems such as the S3C2440 integrate - * these into the device). -*/ -static inline void s3c2410_ts_connect(void) -{ - s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); - s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); -} - /** * get_down - return the down state of the pen * @data0: The data read from ADCDAT0 register. @@ -296,9 +279,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) goto err_clk; } - /* Configure the touchscreen external FETs on the S3C2410 */ - if (!platform_get_device_id(pdev)->driver_data) - s3c2410_ts_connect(); + /* inititalise the gpio */ + if (info->cfg_gpio) + info->cfg_gpio(to_platform_device(ts.dev)); ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, s3c24xx_ts_conversion, 1); -- cgit v1.2.2 From 91df77d7b550d3c8167c97c6e3b97f2ca4d9f3af Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Tue, 18 May 2010 20:44:45 +0900 Subject: Input: s3c24xx_ts - Add FEAT for Samsung touchscreen support This patch adds a feature bit field in the touchscreen driver for Samsung SoCs. Which can be used to distinguish the TSADC module features. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim [ben-linux@fluff.org: minor fix to title] Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 86086a42d5e..e0b7c834111 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -55,6 +55,8 @@ S3C2410_ADCTSC_AUTO_PST | \ S3C2410_ADCTSC_XY_PST(0)) +#define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */ + /* Per-touchscreen data. */ /** @@ -69,6 +71,7 @@ * @irq_tc: The interrupt number for pen up/down interrupt * @count: The number of samples collected. * @shift: The log2 of the maximum count to read in one go. + * @features: The features supported by the TSADC MOdule. */ struct s3c2410ts { struct s3c_adc_client *client; @@ -81,6 +84,7 @@ struct s3c2410ts { int irq_tc; int count; int shift; + int features; }; static struct s3c2410ts ts; @@ -171,6 +175,11 @@ static irqreturn_t stylus_irq(int irq, void *dev_id) else dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); + if (ts.features & FEAT_PEN_IRQ) { + /* Clear pen down/up interrupt */ + writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP); + } + return IRQ_HANDLED; } @@ -317,6 +326,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) ts.input->id.version = 0x0102; ts.shift = info->oversampling_shift; + ts.features = platform_get_device_id(pdev)->driver_data; ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, "s3c2410_ts_pen", ts.input); @@ -403,15 +413,14 @@ static struct dev_pm_ops s3c_ts_pmops = { #endif static struct platform_device_id s3cts_driver_ids[] = { - { "s3c2410-ts", 0 }, - { "s3c2440-ts", 1 }, + { "s3c64xx-ts", FEAT_PEN_IRQ }, { } }; MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); static struct platform_driver s3c_ts_driver = { .driver = { - .name = "s3c24xx-ts", + .name = "samsung-ts", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &s3c_ts_pmops, -- cgit v1.2.2 From 504d36e91ac12ccdb0e1193cee7bef9831a1c99e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 May 2010 14:45:01 +0900 Subject: Input: s3c24xx_ts - depend on SAMSUNG_DEV_TS and update menu entry Make the driver depend on either ARCH_S3C2410 (as legacy) or the new device selection of SAMSUNG_DEV_TS. Change the menuconfig name to reflect this driver is now handling more devices that just the s3c2410. Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a..77a50d9bba1 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -158,8 +158,8 @@ config TOUCHSCREEN_FUJITSU module will be called fujitsu-ts. config TOUCHSCREEN_S3C2410 - tristate "Samsung S3C2410 touchscreen input driver" - depends on ARCH_S3C2410 + tristate "Samsung S3C2410/generic touchscreen input driver" + depends on ARCH_S3C2410 || SAMSUNG_DEV_TS select S3C24XX_ADC help Say Y here if you have the s3c2410 touchscreen. -- cgit v1.2.2 From af8b01b03941e6b008d63b42c0433699c3d3d184 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Wed, 19 May 2010 10:11:13 -0700 Subject: Input: wm9712 - fix wm97xx_set_gpio() logic WM97XX_GPIO_HIGH is not a bitmap and should to be treated as such. Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm97xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 5109bf3dd85..cbfef1ea7e3 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -200,7 +200,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, mutex_lock(&wm->codec_mutex); reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); - if (status & WM97XX_GPIO_HIGH) + if (status == WM97XX_GPIO_HIGH) reg |= gpio; else reg &= ~gpio; -- cgit v1.2.2 From 09fac079d9d21c219df211559528cbe8439af59d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 19 May 2010 10:11:13 -0700 Subject: Input: i8042 - add some extra PNP keyboard types Some Japanese machines declare their keyboard with a different PNP ID. Add it to the list of probed device IDs. While we're at it, add all the other IDs that Windows binds to - we'll probably never see them in the real world, but it doesn't hurt. Signed-off-by: Matthew Garrett Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ead0494721d..871a74c722a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -660,8 +660,21 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * } static struct pnp_device_id pnp_kbd_devids[] = { + { .id = "PNP0300", .driver_data = 0 }, + { .id = "PNP0301", .driver_data = 0 }, + { .id = "PNP0302", .driver_data = 0 }, { .id = "PNP0303", .driver_data = 0 }, + { .id = "PNP0304", .driver_data = 0 }, + { .id = "PNP0305", .driver_data = 0 }, + { .id = "PNP0306", .driver_data = 0 }, + { .id = "PNP0309", .driver_data = 0 }, + { .id = "PNP030a", .driver_data = 0 }, { .id = "PNP030b", .driver_data = 0 }, + { .id = "PNP0320", .driver_data = 0 }, + { .id = "PNP0343", .driver_data = 0 }, + { .id = "PNP0344", .driver_data = 0 }, + { .id = "PNP0345", .driver_data = 0 }, + { .id = "CPQA0D7", .driver_data = 0 }, { .id = "", }, }; -- cgit v1.2.2 From dba06b839a502321ae40b7061d64308bc91d260f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 19 May 2010 10:11:13 -0700 Subject: Input: i8042 - add a PNP entry to the aux device list Windows checks for an ALPS PS/2 device in PNP. Add it on the off-chance that there's a machine that expresses this without also providing a compatibility ID. Signed-off-by: Matthew Garrett Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 871a74c722a..6168469ad1a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -685,6 +685,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = { }; static struct pnp_device_id pnp_aux_devids[] = { + { .id = "AUI0200", .driver_data = 0 }, { .id = "FJC6000", .driver_data = 0 }, { .id = "FJC6001", .driver_data = 0 }, { .id = "PNP0f03", .driver_data = 0 }, -- cgit v1.2.2 From ee6e54e2ae56734a96fd7b66cf46b756d0f25ca3 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 19 May 2010 10:11:13 -0700 Subject: Input: 88pm860x_onkey - remove invalid irq number assignment Irq number of onkey is assigned twice. The second assignment is wrong. Signed-off-by: Haojian Zhuang Signed-off-by: Dmitry Torokhov --- drivers/input/misc/88pm860x_onkey.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index 40dabd8487b..4cc82826ea6 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c @@ -87,7 +87,6 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) info->idev->phys = "88pm860x_on/input0"; info->idev->id.bustype = BUS_I2C; info->idev->dev.parent = &pdev->dev; - info->irq = irq; info->idev->evbit[0] = BIT_MASK(EV_KEY); info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); -- cgit v1.2.2 From 685afae02557a178185a4be36f58332976e79f63 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Wed, 19 May 2010 10:11:14 -0700 Subject: Input: do not force selecting i8042 on Moorestown Moorestown does not have i8042 based keyboard controller, so give an option to deselect i8042 for non-pc mid. Signed-off-by: Jacob Pan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/mouse/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 3525f533e18..d8fa5d724c5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -73,7 +73,7 @@ config KEYBOARD_ATKBD default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86 + select SERIO_I8042 if X86 && !X86_MRST select SERIO_GSCPS2 if GSC help Say Y here if you want to use a standard AT or PS/2 keyboard. Usually diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index c714ca2407f..eeb58c1cac1 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -17,7 +17,7 @@ config MOUSE_PS2 default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86 + select SERIO_I8042 if X86 && !X86_MRST select SERIO_GSCPS2 if GSC help Say Y here if you have a PS/2 mouse connected to your system. This -- cgit v1.2.2 From 641d446f89314d19fe17fcb9f19659a09fabe418 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 19 May 2010 10:11:14 -0700 Subject: Input: usbtouchscreen - switch to using kmemdup() Use kmemdup when some other buffer is immediately copied into the allocated region. Signed-off-by: Julia Lawall Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 99330bbdbac..0b0ae2e17a6 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -811,12 +811,11 @@ static int nexio_init(struct usbtouch_usb *usbtouch) priv = usbtouch->priv; - priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL); + priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), + GFP_KERNEL); if (!priv->ack_buf) goto err_priv; - memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt)); - priv->ack = usb_alloc_urb(0, GFP_KERNEL); if (!priv->ack) { dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); -- cgit v1.2.2 From f8300ab8c3e0bea42c82bbdcdff7b791b795d58f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 19 May 2010 10:11:14 -0700 Subject: Input: wistron_btns - switch to using kmemdup() Use kmemdup when some other buffer is immediately copied into the allocated region. Signed-off-by: Julia Lawall Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 04d5a4a3181..4dac8b79fcd 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -983,11 +983,11 @@ static int __init copy_keymap(void) for (key = keymap; key->type != KE_END; key++) length++; - new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); + new_keymap = kmemdup(keymap, length * sizeof(struct key_entry), + GFP_KERNEL); if (!new_keymap) return -ENOMEM; - memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); keymap = new_keymap; return 0; -- cgit v1.2.2 From d4ae84a84bedcb79341887ff070e6528d1374663 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 13 May 2010 00:41:15 -0700 Subject: Input: elantech - enforce common prefix on messages Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 67 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 35 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 112b4ee52ff..232556a89c4 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -10,6 +10,8 @@ * Trademarks are the property of their respective owners. */ +#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt + #include #include #include @@ -19,10 +21,10 @@ #include "psmouse.h" #include "elantech.h" -#define elantech_debug(format, arg...) \ - do { \ - if (etd->debug) \ - printk(KERN_DEBUG format, ##arg); \ +#define elantech_debug(fmt, ...) \ + do { \ + if (etd->debug) \ + printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ } while (0) static bool force_elantech; @@ -37,7 +39,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, { if (psmouse_sliced_command(psmouse, c) || ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { - pr_err("elantech.c: synaptics_send_cmd query 0x%02x failed.\n", c); + pr_err("synaptics_send_cmd query 0x%02x failed.\n", c); return -1; } @@ -60,13 +62,13 @@ static int elantech_ps2_command(struct psmouse *psmouse, if (rc == 0) break; tries--; - elantech_debug("elantech.c: retrying ps2 command 0x%02x (%d).\n", - command, tries); + elantech_debug("retrying ps2 command 0x%02x (%d).\n", + command, tries); msleep(ETP_PS2_COMMAND_DELAY); } while (tries > 0); if (rc) - pr_err("elantech.c: ps2 command 0x%02x failed.\n", command); + pr_err("ps2 command 0x%02x failed.\n", command); return rc; } @@ -108,7 +110,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, } if (rc) - pr_err("elantech.c: failed to read register 0x%02x.\n", reg); + pr_err("failed to read register 0x%02x.\n", reg); else *val = param[0]; @@ -154,7 +156,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, } if (rc) - pr_err("elantech.c: failed to write register 0x%02x with value 0x%02x.\n", + pr_err("failed to write register 0x%02x with value 0x%02x.\n", reg, val); return rc; @@ -167,7 +169,7 @@ static void elantech_packet_dump(unsigned char *packet, int size) { int i; - printk(KERN_DEBUG "elantech.c: PS/2 packet ["); + printk(KERN_DEBUG pr_fmt("PS/2 packet [")); for (i = 0; i < size; i++) printk("%s0x%02x ", (i) ? ", " : " ", packet[i]); printk("]\n"); @@ -203,7 +205,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) if (etd->jumpy_cursor) { /* Discard packets that are likely to have bogus coordinates */ if (fingers > old_fingers) { - elantech_debug("elantech.c: discarding packet\n"); + elantech_debug("discarding packet\n"); goto discard_packet_v1; } } @@ -413,23 +415,21 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) if (rc == 0) break; tries--; - elantech_debug("elantech.c: retrying read (%d).\n", - tries); + elantech_debug("retrying read (%d).\n", tries); msleep(ETP_READ_BACK_DELAY); } while (tries > 0); if (rc) { - pr_err("elantech.c: failed to read back register 0x10.\n"); + pr_err("failed to read back register 0x10.\n"); } else if (etd->hw_version == 1 && !(val & ETP_R10_ABSOLUTE_MODE)) { - pr_err("elantech.c: touchpad refuses " - "to switch to absolute mode.\n"); + pr_err("touchpad refuses to switch to absolute mode.\n"); rc = -1; } } if (rc) - pr_err("elantech.c: failed to initialise registers.\n"); + pr_err("failed to initialise registers.\n"); return rc; } @@ -590,7 +590,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - pr_debug("elantech.c: sending Elantech magic knock failed.\n"); + pr_debug("sending Elantech magic knock failed.\n"); return -1; } @@ -599,8 +599,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) * set of magic numbers */ if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { - pr_debug("elantech.c: " - "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", + pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); return -1; } @@ -611,20 +610,20 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) * to Elantech magic knock and there might be more. */ if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { - pr_debug("elantech.c: failed to query firmware version.\n"); + pr_debug("failed to query firmware version.\n"); return -1; } - pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", + pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); if (param[0] == 0 || param[1] != 0) { if (!force_elantech) { - pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); + pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); return -1; } - pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); + pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); } if (set_properties) { @@ -655,7 +654,7 @@ static int elantech_reconnect(struct psmouse *psmouse) return -1; if (elantech_set_absolute_mode(psmouse)) { - pr_err("elantech.c: failed to put touchpad back into absolute mode.\n"); + pr_err("failed to put touchpad back into absolute mode.\n"); return -1; } @@ -683,7 +682,7 @@ int elantech_init(struct psmouse *psmouse) * Do the version query again so we can store the result */ if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { - pr_err("elantech.c: failed to query firmware version.\n"); + pr_err("failed to query firmware version.\n"); goto init_fail; } @@ -704,14 +703,14 @@ int elantech_init(struct psmouse *psmouse) etd->paritycheck = 1; } - pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", + pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", etd->hw_version, param[0], param[1], param[2]); if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { - pr_err("elantech.c: failed to query capabilities.\n"); + pr_err("failed to query capabilities.\n"); goto init_fail; } - pr_info("elantech.c: Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", + pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); etd->capabilities = param[0]; @@ -721,13 +720,12 @@ int elantech_init(struct psmouse *psmouse) * to jump. Enable a workaround. */ if (etd->fw_version == 0x020022) { - pr_info("elantech.c: firmware version 2.0.34 detected, " - "enabling jumpy cursor workaround\n"); + pr_info("firmware version 2.0.34 detected, enabling jumpy cursor workaround\n"); etd->jumpy_cursor = 1; } if (elantech_set_absolute_mode(psmouse)) { - pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); + pr_err("failed to put touchpad into absolute mode.\n"); goto init_fail; } @@ -736,8 +734,7 @@ int elantech_init(struct psmouse *psmouse) error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, &elantech_attr_group); if (error) { - pr_err("elantech.c: failed to create sysfs attributes, error: %d.\n", - error); + pr_err("failed to create sysfs attributes, error: %d.\n", error); goto init_fail; } -- cgit v1.2.2 From a083632eaf6231162b33e40561cfec6a9c156945 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 May 2010 10:11:13 -0700 Subject: Input: elantech - relax signature checks Apparently there are Elantech touchpads that report non-zero in the 2nd byte of their signature. Adjust the detection routine so that if 2nd byte is zero and 3rd byte contains value that is not a valid report rate, we still assume that signature is valid. Tested-by: Eric Piel Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 232556a89c4..b18862b2a70 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -575,6 +575,24 @@ static struct attribute_group elantech_attr_group = { .attrs = elantech_attrs, }; +static bool elantech_is_signature_valid(const unsigned char *param) +{ + static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; + int i; + + if (param[0] == 0) + return false; + + if (param[1] == 0) + return true; + + for (i = 0; i < ARRAY_SIZE(rates); i++) + if (param[2] == rates[i]) + return false; + + return true; +} + /* * Use magic knock to detect Elantech touchpad */ @@ -617,7 +635,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); - if (param[0] == 0 || param[1] != 0) { + if (!elantech_is_signature_valid(param)) { if (!force_elantech) { pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); return -1; -- cgit v1.2.2 From 83ba9ea8a04b72dfee2515428c15e7414ba4fc61 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 10 May 2010 23:06:52 -0700 Subject: Input: synaptics - set dimensions as reported by firmware Newer Synaptics firmware allows to query maximim dimensions reported by device, let's use this data. Tested-by: Takashi Iwai Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 32 +++++++++++++++++++++++--------- drivers/input/mouse/synaptics.h | 6 ++++-- 2 files changed, 27 insertions(+), 11 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ebd7a99efea..52bb1de32e4 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -36,6 +36,8 @@ * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, * section 2.3.2, which says that they should be valid regardless of the * actual size of the sensor. + * Note that newer firmware allows querying device for maximum useable + * coordinates. */ #define XMIN_NOMINAL 1472 #define XMAX_NOMINAL 5472 @@ -194,23 +196,33 @@ static int synaptics_identify(struct psmouse *psmouse) } /* - * Read touchpad resolution + * Read touchpad resolution and maximum reported coordinates * Resolution is left zero if touchpad does not support the query */ static int synaptics_resolution(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; unsigned char res[3]; + unsigned char max[3]; if (SYN_ID_MAJOR(priv->identity) < 4) - return 0; - if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res)) - return 0; + if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) { + if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { + priv->x_res = res[0]; /* x resolution in units/mm */ + priv->y_res = res[2]; /* y resolution in units/mm */ + } + } - if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) { - priv->x_res = res[0]; /* x resolution in units/mm */ - priv->y_res = res[2]; /* y resolution in units/mm */ + if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && + SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) { + printk(KERN_ERR "Synaptics claims to have dimensions query," + " but I'm not able to read it.\n"); + } else { + priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1); + priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3); + } } return 0; @@ -578,8 +590,10 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) int i; __set_bit(EV_ABS, dev->evbit); - input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); - input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); + input_set_abs_params(dev, ABS_X, + XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); + input_set_abs_params(dev, ABS_Y, + YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); __set_bit(ABS_TOOL_WIDTH, dev->absbit); diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index ae37c5d162a..7d4d5e12c0d 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -19,6 +19,7 @@ #define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_EXT_CAPAB 0x09 #define SYN_QUE_EXT_CAPAB_0C 0x0c +#define SYN_QUE_EXT_DIMENSIONS 0x0d /* synatics modes */ #define SYN_BIT_ABSOLUTE_MODE (1 << 7) @@ -51,6 +52,7 @@ #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) +#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -101,8 +103,8 @@ struct synaptics_data { unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ unsigned long int identity; /* Identification */ - int x_res; /* X resolution in units/mm */ - int y_res; /* Y resolution in units/mm */ + unsigned int x_res, y_res; /* X/Y resolution in units/mm */ + unsigned int x_max, y_max; /* Max dimensions (from FW) */ unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char mode; /* current mode byte */ -- cgit v1.2.2 From a62f0d27b4196bad5e900d766b285feb7069cd16 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 May 2010 10:39:17 -0700 Subject: Input: psmouse - small formatting changes to better follow coding style Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/hgpk.c | 4 +- drivers/input/mouse/logips2pp.c | 98 ++++++++++++++++++++------------------ drivers/input/mouse/psmouse-base.c | 72 ++++++++++++++-------------- drivers/input/mouse/synaptics.c | 21 ++++---- 4 files changed, 100 insertions(+), 95 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 08d66d820d2..1d2205b2480 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -40,8 +40,8 @@ #include "psmouse.h" #include "hgpk.h" -static int tpdebug; -module_param(tpdebug, int, 0644); +static bool tpdebug; +module_param(tpdebug, bool, 0644); MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); static int recalib_delta = 100; diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 543c240a85f..c9983aee908 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -56,36 +56,36 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse) /* Logitech extended packet */ switch ((packet[1] >> 4) | (packet[0] & 0x30)) { - case 0x0d: /* Mouse extra info */ + case 0x0d: /* Mouse extra info */ - input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL, - (int) (packet[2] & 8) - (int) (packet[2] & 7)); - input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1); + input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL, + (int) (packet[2] & 8) - (int) (packet[2] & 7)); + input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1); + input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1); - break; + break; - case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */ + case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */ - input_report_key(dev, BTN_SIDE, (packet[2]) & 1); - input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1); - input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1); - input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1); - input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1); + input_report_key(dev, BTN_SIDE, (packet[2]) & 1); + input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1); + input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1); + input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1); + input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1); - break; + break; - case 0x0f: /* TouchPad extra info */ + case 0x0f: /* TouchPad extra info */ - input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL, - (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); - packet[0] = packet[2] | 0x08; - break; + input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL, + (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); + packet[0] = packet[2] | 0x08; + break; #ifdef DEBUG - default: - printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n", - (packet[1] >> 4) | (packet[0] & 0x30)); + default: + printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n", + (packet[1] >> 4) | (packet[0] & 0x30)); #endif } } else { @@ -250,7 +250,6 @@ static const struct ps2pp_info *get_model_info(unsigned char model) if (model == ps2pp_list[i].model) return &ps2pp_list[i]; - printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model); return NULL; } @@ -285,31 +284,32 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, __set_bit(REL_HWHEEL, input_dev->relbit); switch (model_info->kind) { - case PS2PP_KIND_WHEEL: - psmouse->name = "Wheel Mouse"; - break; - - case PS2PP_KIND_MX: - psmouse->name = "MX Mouse"; - break; - case PS2PP_KIND_TP3: - psmouse->name = "TouchPad 3"; - break; - - case PS2PP_KIND_TRACKMAN: - psmouse->name = "TrackMan"; - break; - - default: - /* - * Set name to "Mouse" only when using PS2++, - * otherwise let other protocols define suitable - * name - */ - if (using_ps2pp) - psmouse->name = "Mouse"; - break; + case PS2PP_KIND_WHEEL: + psmouse->name = "Wheel Mouse"; + break; + + case PS2PP_KIND_MX: + psmouse->name = "MX Mouse"; + break; + + case PS2PP_KIND_TP3: + psmouse->name = "TouchPad 3"; + break; + + case PS2PP_KIND_TRACKMAN: + psmouse->name = "TrackMan"; + break; + + default: + /* + * Set name to "Mouse" only when using PS2++, + * otherwise let other protocols define suitable + * name + */ + if (using_ps2pp) + psmouse->name = "Mouse"; + break; } } @@ -343,7 +343,8 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) if (!model || !buttons) return -1; - if ((model_info = get_model_info(model)) != NULL) { + model_info = get_model_info(model); + if (model_info) { /* * Do Logitech PS2++ / PS2T++ magic init. @@ -379,6 +380,9 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) use_ps2pp = true; } } + + } else { + printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model); } if (set_properties) { diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index a3c97315a47..979c5021528 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -147,18 +147,18 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) if (psmouse->type == PSMOUSE_IMEX) { switch (packet[3] & 0xC0) { - case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x00: - case 0xC0: - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); - input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); - break; + case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x00: + case 0xC0: + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); + input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); + input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); + break; } } @@ -247,31 +247,31 @@ static int psmouse_handle_byte(struct psmouse *psmouse) psmouse_ret_t rc = psmouse->protocol_handler(psmouse); switch (rc) { - case PSMOUSE_BAD_DATA: - if (psmouse->state == PSMOUSE_ACTIVATED) { - printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", - psmouse->name, psmouse->phys, psmouse->pktcnt); - if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { - __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); - serio_reconnect(psmouse->ps2dev.serio); - return -1; - } - } - psmouse->pktcnt = 0; - break; - - case PSMOUSE_FULL_PACKET: - psmouse->pktcnt = 0; - if (psmouse->out_of_sync_cnt) { - psmouse->out_of_sync_cnt = 0; - printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", - psmouse->name, psmouse->phys); + case PSMOUSE_BAD_DATA: + if (psmouse->state == PSMOUSE_ACTIVATED) { + printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); + if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { + __psmouse_set_state(psmouse, PSMOUSE_IGNORE); + printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); + serio_reconnect(psmouse->ps2dev.serio); + return -1; } - break; + } + psmouse->pktcnt = 0; + break; + + case PSMOUSE_FULL_PACKET: + psmouse->pktcnt = 0; + if (psmouse->out_of_sync_cnt) { + psmouse->out_of_sync_cnt = 0; + printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", + psmouse->name, psmouse->phys); + } + break; - case PSMOUSE_GOOD_DATA: - break; + case PSMOUSE_GOOD_DATA: + break; } return 0; } @@ -1245,7 +1245,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, psmouse->pktsize = 3; if (proto && (proto->detect || proto->init)) { - if (proto->detect && proto->detect(psmouse, 1) < 0) + if (proto->detect && proto->detect(psmouse, true) < 0) return -1; if (proto->init && proto->init(psmouse) < 0) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 52bb1de32e4..40cea334ad1 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -532,19 +532,20 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha return 0; switch (pkt_type) { - case SYN_NEWABS: - case SYN_NEWABS_RELAXED: - return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; - case SYN_NEWABS_STRICT: - return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; + case SYN_NEWABS: + case SYN_NEWABS_RELAXED: + return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; - case SYN_OLDABS: - return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; + case SYN_NEWABS_STRICT: + return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; - default: - printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type); - return 0; + case SYN_OLDABS: + return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; + + default: + printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type); + return 0; } } -- cgit v1.2.2 From 0ede76fcec5415ef82a423a95120286895822e2d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 5 Mar 2010 15:10:17 -0500 Subject: USB: remove uses of URB_NO_SETUP_DMA_MAP This patch (as1350) removes all usages of coherent buffers for USB control-request setup-packet buffers. There's no good reason to reserve coherent memory for these things; control requests are hardly ever used in large quantity (the major exception is firmware transfers, and they aren't time-critical). Furthermore, only seven drivers used it. We might as well always use streaming DMA mappings for setup-packet buffers, and remove some extra complexity from usbcore. The DMA-mapping portion of hcd.c is currently in flux. A separate patch will be submitted to remove support for URB_NO_SETUP_DMA_MAP after everything else settles down. The removal should go smoothly, as by then nobody will be using it. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/cm109.c | 12 +++--------- drivers/input/misc/powermate.c | 9 ++------- drivers/input/misc/yealink.c | 11 +++-------- 3 files changed, 8 insertions(+), 24 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 86457feccfc..8d2d291ee50 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -102,7 +102,6 @@ struct cm109_dev { struct cm109_ctl_packet *ctl_data; dma_addr_t ctl_dma; struct usb_ctrlrequest *ctl_req; - dma_addr_t ctl_req_dma; struct urb *urb_ctl; /* * The 3 bitfields below are protected by ctl_submit_lock. @@ -629,9 +628,7 @@ static const struct usb_device_id cm109_usb_table[] = { static void cm109_usb_cleanup(struct cm109_dev *dev) { - if (dev->ctl_req) - usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), - dev->ctl_req, dev->ctl_req_dma); + kfree(dev->ctl_req); if (dev->ctl_data) usb_buffer_free(dev->udev, USB_PKT_LEN, dev->ctl_data, dev->ctl_dma); @@ -696,8 +693,7 @@ static int cm109_usb_probe(struct usb_interface *intf, if (!dev->ctl_data) goto err_out; - dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), - GFP_KERNEL, &dev->ctl_req_dma); + dev->ctl_req = kmalloc(sizeof(*(dev->ctl_req)), GFP_KERNEL); if (!dev->ctl_req) goto err_out; @@ -735,10 +731,8 @@ static int cm109_usb_probe(struct usb_interface *intf, usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, cm109_urb_ctl_callback, dev); - dev->urb_ctl->setup_dma = dev->ctl_req_dma; dev->urb_ctl->transfer_dma = dev->ctl_dma; - dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | - URB_NO_TRANSFER_DMA_MAP; + dev->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; dev->urb_ctl->dev = udev; /* find out the physical bus location */ diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 668913d1204..7ba4b5f53fc 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -64,7 +64,6 @@ struct powermate_device { dma_addr_t data_dma; struct urb *irq, *config; struct usb_ctrlrequest *configcr; - dma_addr_t configcr_dma; struct usb_device *udev; struct input_dev *input; spinlock_t lock; @@ -182,8 +181,6 @@ static void powermate_sync_state(struct powermate_device *pm) usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), (void *) pm->configcr, NULL, 0, powermate_config_complete, pm); - pm->config->setup_dma = pm->configcr_dma; - pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; if (usb_submit_urb(pm->config, GFP_ATOMIC)) printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); @@ -281,8 +278,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev if (!pm->data) return -1; - pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), - GFP_ATOMIC, &pm->configcr_dma); + pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL); if (!pm->configcr) return -1; @@ -293,8 +289,7 @@ static void powermate_free_buffers(struct usb_device *udev, struct powermate_dev { usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, pm->data, pm->data_dma); - usb_buffer_free(udev, sizeof(*(pm->configcr)), - pm->configcr, pm->configcr_dma); + kfree(pm->configcr); } /* Called whenever a USB device matching one in our supported devices table is connected */ diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 93a22ac0f88..2828328e9dd 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -111,7 +111,6 @@ struct yealink_dev { struct yld_ctl_packet *ctl_data; dma_addr_t ctl_dma; struct usb_ctrlrequest *ctl_req; - dma_addr_t ctl_req_dma; struct urb *urb_ctl; char phys[64]; /* physical device path */ @@ -836,8 +835,7 @@ static int usb_cleanup(struct yealink_dev *yld, int err) usb_free_urb(yld->urb_irq); usb_free_urb(yld->urb_ctl); - usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), - yld->ctl_req, yld->ctl_req_dma); + kfree(yld->ctl_req); usb_buffer_free(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma); usb_buffer_free(yld->udev, USB_PKT_LEN, @@ -896,8 +894,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) if (!yld->ctl_data) return usb_cleanup(yld, -ENOMEM); - yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), - GFP_ATOMIC, &yld->ctl_req_dma); + yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL); if (yld->ctl_req == NULL) return usb_cleanup(yld, -ENOMEM); @@ -936,10 +933,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, urb_ctl_callback, yld); - yld->urb_ctl->setup_dma = yld->ctl_req_dma; yld->urb_ctl->transfer_dma = yld->ctl_dma; - yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | - URB_NO_TRANSFER_DMA_MAP; + yld->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; yld->urb_ctl->dev = udev; /* find out the physical bus location */ -- cgit v1.2.2 From 997ea58eb92f9970b8af7aae48800d0ef43b9423 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Apr 2010 13:17:25 +0200 Subject: USB: rename usb_buffer_alloc() and usb_buffer_free() users For more clearance what the functions actually do, usb_buffer_alloc() is renamed to usb_alloc_coherent() usb_buffer_free() is renamed to usb_free_coherent() They should only be used in code which really needs DMA coherency. All call sites have been changed accordingly, except for staging drivers. Signed-off-by: Daniel Mack Cc: Alan Stern Cc: Pedro Ribeiro Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/xpad.c | 16 ++++++++-------- drivers/input/misc/ati_remote.c | 12 ++++++------ drivers/input/misc/ati_remote2.c | 4 ++-- drivers/input/misc/cm109.c | 16 ++++++++-------- drivers/input/misc/keyspan_remote.c | 6 +++--- drivers/input/misc/powermate.c | 8 ++++---- drivers/input/misc/yealink.c | 14 ++++++-------- drivers/input/mouse/appletouch.c | 12 ++++++------ drivers/input/mouse/bcm5974.c | 24 ++++++++++++------------ drivers/input/tablet/acecad.c | 6 +++--- drivers/input/tablet/aiptek.c | 14 +++++++------- drivers/input/tablet/gtco.c | 12 ++++++------ drivers/input/tablet/kbtab.c | 6 +++--- drivers/input/tablet/wacom_sys.c | 10 +++++----- drivers/input/touchscreen/usbtouchscreen.c | 8 ++++---- 15 files changed, 83 insertions(+), 85 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 9b3353b404d..c1087ce4cef 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -533,8 +533,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) return 0; - xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->odata_dma); + xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->odata_dma); if (!xpad->odata) goto fail1; @@ -554,7 +554,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) return 0; - fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); + fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); fail1: return error; } @@ -568,7 +568,7 @@ static void xpad_deinit_output(struct usb_xpad *xpad) { if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { usb_free_urb(xpad->irq_out); - usb_buffer_free(xpad->udev, XPAD_PKT_LEN, + usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); } } @@ -788,8 +788,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id if (!xpad || !input_dev) goto fail1; - xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->idata_dma); + xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->idata_dma); if (!xpad->idata) goto fail1; @@ -942,7 +942,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id fail5: usb_kill_urb(xpad->irq_in); fail4: usb_free_urb(xpad->irq_in); fail3: xpad_deinit_output(xpad); - fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); + fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); fail1: input_free_device(input_dev); kfree(xpad); return error; @@ -964,7 +964,7 @@ static void xpad_disconnect(struct usb_interface *intf) usb_kill_urb(xpad->irq_in); } usb_free_urb(xpad->irq_in); - usb_buffer_free(xpad->udev, XPAD_PKT_LEN, + usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); kfree(xpad); } diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index e8bbc619f6d..bce57129afb 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c @@ -624,13 +624,13 @@ static void ati_remote_irq_in(struct urb *urb) static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote) { - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->inbuf_dma); + ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, + &ati_remote->inbuf_dma); if (!ati_remote->inbuf) return -1; - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->outbuf_dma); + ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, + &ati_remote->outbuf_dma); if (!ati_remote->outbuf) return -1; @@ -653,10 +653,10 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote) usb_free_urb(ati_remote->irq_urb); usb_free_urb(ati_remote->out_urb); - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->inbuf_dma); - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, ati_remote->outbuf, ati_remote->outbuf_dma); } diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 2124b99378b..e148749b585 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -589,7 +589,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2) int i, pipe, maxp; for (i = 0; i < 2; i++) { - ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); + ar2->buf[i] = usb_alloc_coherent(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); if (!ar2->buf[i]) return -ENOMEM; @@ -617,7 +617,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) for (i = 0; i < 2; i++) { usb_free_urb(ar2->urb[i]); - usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); + usb_free_coherent(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); } } diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 8d2d291ee50..2b0eba6619b 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -630,11 +630,11 @@ static void cm109_usb_cleanup(struct cm109_dev *dev) { kfree(dev->ctl_req); if (dev->ctl_data) - usb_buffer_free(dev->udev, USB_PKT_LEN, - dev->ctl_data, dev->ctl_dma); + usb_free_coherent(dev->udev, USB_PKT_LEN, + dev->ctl_data, dev->ctl_dma); if (dev->irq_data) - usb_buffer_free(dev->udev, USB_PKT_LEN, - dev->irq_data, dev->irq_dma); + usb_free_coherent(dev->udev, USB_PKT_LEN, + dev->irq_data, dev->irq_dma); usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ @@ -683,13 +683,13 @@ static int cm109_usb_probe(struct usb_interface *intf, goto err_out; /* allocate usb buffers */ - dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_KERNEL, &dev->irq_dma); + dev->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->irq_dma); if (!dev->irq_data) goto err_out; - dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_KERNEL, &dev->ctl_dma); + dev->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->ctl_dma); if (!dev->ctl_data) goto err_out; diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index 86afdd1fdf9..a93c525475c 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -464,7 +464,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->in_endpoint = endpoint; remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); + remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); if (!remote->in_buffer) { error = -ENOMEM; goto fail1; @@ -543,7 +543,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic return 0; fail3: usb_free_urb(remote->irq_urb); - fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); fail1: kfree(remote); input_free_device(input_dev); @@ -564,7 +564,7 @@ static void keyspan_disconnect(struct usb_interface *interface) input_unregister_device(remote->input); usb_kill_urb(remote->irq_urb); usb_free_urb(remote->irq_urb); - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); kfree(remote); } } diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 7ba4b5f53fc..bf170f6b442 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -273,8 +273,8 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) { - pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, - GFP_ATOMIC, &pm->data_dma); + pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, + GFP_ATOMIC, &pm->data_dma); if (!pm->data) return -1; @@ -287,8 +287,8 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) { - usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, - pm->data, pm->data_dma); + usb_free_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, + pm->data, pm->data_dma); kfree(pm->configcr); } diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 2828328e9dd..41201c6b5e6 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -836,10 +836,8 @@ static int usb_cleanup(struct yealink_dev *yld, int err) usb_free_urb(yld->urb_ctl); kfree(yld->ctl_req); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->ctl_data, yld->ctl_dma); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->irq_data, yld->irq_dma); + usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma); + usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma); kfree(yld); return err; @@ -884,13 +882,13 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return usb_cleanup(yld, -ENOMEM); /* allocate usb buffers */ - yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->irq_dma); + yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_ATOMIC, &yld->irq_dma); if (yld->irq_data == NULL) return usb_cleanup(yld, -ENOMEM); - yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->ctl_dma); + yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_ATOMIC, &yld->ctl_dma); if (!yld->ctl_data) return usb_cleanup(yld, -ENOMEM); diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 53ec7ddd182..05edd75abca 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -806,8 +806,8 @@ static int atp_probe(struct usb_interface *iface, if (!dev->urb) goto err_free_devs; - dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL, - &dev->urb->transfer_dma); + dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL, + &dev->urb->transfer_dma); if (!dev->data) goto err_free_urb; @@ -862,8 +862,8 @@ static int atp_probe(struct usb_interface *iface, return 0; err_free_buffer: - usb_buffer_free(dev->udev, dev->info->datalen, - dev->data, dev->urb->transfer_dma); + usb_free_coherent(dev->udev, dev->info->datalen, + dev->data, dev->urb->transfer_dma); err_free_urb: usb_free_urb(dev->urb); err_free_devs: @@ -881,8 +881,8 @@ 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->info->datalen, - dev->data, dev->urb->transfer_dma); + usb_free_coherent(dev->udev, dev->info->datalen, + dev->data, dev->urb->transfer_dma); usb_free_urb(dev->urb); kfree(dev); } diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b89879bd860..6dedded2722 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -715,15 +715,15 @@ static int bcm5974_probe(struct usb_interface *iface, if (!dev->tp_urb) goto err_free_bt_urb; - dev->bt_data = usb_buffer_alloc(dev->udev, - dev->cfg.bt_datalen, GFP_KERNEL, - &dev->bt_urb->transfer_dma); + dev->bt_data = usb_alloc_coherent(dev->udev, + dev->cfg.bt_datalen, GFP_KERNEL, + &dev->bt_urb->transfer_dma); if (!dev->bt_data) goto err_free_urb; - dev->tp_data = usb_buffer_alloc(dev->udev, - dev->cfg.tp_datalen, GFP_KERNEL, - &dev->tp_urb->transfer_dma); + dev->tp_data = usb_alloc_coherent(dev->udev, + dev->cfg.tp_datalen, GFP_KERNEL, + &dev->tp_urb->transfer_dma); if (!dev->tp_data) goto err_free_bt_buffer; @@ -765,10 +765,10 @@ static int bcm5974_probe(struct usb_interface *iface, return 0; err_free_buffer: - usb_buffer_free(dev->udev, dev->cfg.tp_datalen, + usb_free_coherent(dev->udev, dev->cfg.tp_datalen, dev->tp_data, dev->tp_urb->transfer_dma); err_free_bt_buffer: - usb_buffer_free(dev->udev, dev->cfg.bt_datalen, + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, dev->bt_data, dev->bt_urb->transfer_dma); err_free_urb: usb_free_urb(dev->tp_urb); @@ -788,10 +788,10 @@ static void bcm5974_disconnect(struct usb_interface *iface) usb_set_intfdata(iface, NULL); input_unregister_device(dev->input); - usb_buffer_free(dev->udev, dev->cfg.tp_datalen, - dev->tp_data, dev->tp_urb->transfer_dma); - usb_buffer_free(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.tp_datalen, + dev->tp_data, dev->tp_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, + dev->bt_data, dev->bt_urb->transfer_dma); usb_free_urb(dev->tp_urb); usb_free_urb(dev->bt_urb); kfree(dev); diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 670c61c5a51..c0470163dc6 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -155,7 +155,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ goto fail1; } - acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); + acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma); if (!acecad->data) { err= -ENOMEM; goto fail1; @@ -241,7 +241,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ return 0; - fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); + fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma); fail1: input_free_device(input_dev); kfree(acecad); return err; @@ -256,7 +256,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf) usb_kill_urb(acecad->irq); input_unregister_device(acecad->input); usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); + usb_free_coherent(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); kfree(acecad); } } diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 4be039d7dca..51b80b08d46 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1711,8 +1711,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) goto fail1; } - aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, - GFP_ATOMIC, &aiptek->data_dma); + aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH, + GFP_ATOMIC, &aiptek->data_dma); if (!aiptek->data) { dev_warn(&intf->dev, "cannot allocate usb buffer\n"); goto fail1; @@ -1884,8 +1884,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); fail3: usb_free_urb(aiptek->urb); - fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, - aiptek->data_dma); + fail2: usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, + aiptek->data_dma); fail1: usb_set_intfdata(intf, NULL); input_free_device(inputdev); kfree(aiptek); @@ -1909,9 +1909,9 @@ static void aiptek_disconnect(struct usb_interface *intf) input_unregister_device(aiptek->inputdev); sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); usb_free_urb(aiptek->urb); - usb_buffer_free(interface_to_usbdev(intf), - AIPTEK_PACKET_LENGTH, - aiptek->data, aiptek->data_dma); + usb_free_coherent(interface_to_usbdev(intf), + AIPTEK_PACKET_LENGTH, + aiptek->data, aiptek->data_dma); kfree(aiptek); } } diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 866a9ee1af1..8ea6afe2e99 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -850,8 +850,8 @@ static int gtco_probe(struct usb_interface *usbinterface, gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); /* Allocate some data for incoming reports */ - gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, - GFP_KERNEL, >co->buf_dma); + gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE, + GFP_KERNEL, >co->buf_dma); if (!gtco->buffer) { err("No more memory for us buffers"); error = -ENOMEM; @@ -982,8 +982,8 @@ static int gtco_probe(struct usb_interface *usbinterface, err_free_urb: usb_free_urb(gtco->urbinfo); err_free_buf: - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); + usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); err_free_devs: input_free_device(input_dev); kfree(gtco); @@ -1005,8 +1005,8 @@ static void gtco_disconnect(struct usb_interface *interface) input_unregister_device(gtco->inputdevice); usb_kill_urb(gtco->urbinfo); usb_free_urb(gtco->urbinfo); - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); + usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); kfree(gtco); } diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 6682b17bf84..d31b9c79355 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -129,7 +129,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i if (!kbtab || !input_dev) goto fail1; - kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); + kbtab->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbtab->data_dma); if (!kbtab->data) goto fail1; @@ -182,7 +182,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; fail3: usb_free_urb(kbtab->irq); - fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); + fail2: usb_free_coherent(dev, 10, kbtab->data, kbtab->data_dma); fail1: input_free_device(input_dev); kfree(kbtab); return error; @@ -197,7 +197,7 @@ static void kbtab_disconnect(struct usb_interface *intf) usb_kill_urb(kbtab->irq); input_unregister_device(kbtab->dev); usb_free_urb(kbtab->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); + usb_free_coherent(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); kfree(kbtab); } } diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f46502589e4..191197cd83e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -556,8 +556,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail1; } - wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, - GFP_KERNEL, &wacom->data_dma); + wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX, + GFP_KERNEL, &wacom->data_dma); if (!wacom_wac->data) { error = -ENOMEM; goto fail1; @@ -633,7 +633,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; fail3: usb_free_urb(wacom->irq); - fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); + fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: input_free_device(input_dev); kfree(wacom); kfree(wacom_wac); @@ -649,8 +649,8 @@ static void wacom_disconnect(struct usb_interface *intf) usb_kill_urb(wacom->irq); input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); - usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, - wacom->wacom_wac->data, wacom->data_dma); + usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, + wacom->wacom_wac->data, wacom->data_dma); kfree(wacom->wacom_wac); kfree(wacom); } diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 99330bbdbac..ea41a851ddf 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -1291,8 +1291,8 @@ static void usbtouch_close(struct input_dev *input) static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch) { - usb_buffer_free(udev, usbtouch->type->rept_size, - usbtouch->data, usbtouch->data_dma); + usb_free_coherent(udev, usbtouch->type->rept_size, + usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer); } @@ -1336,8 +1336,8 @@ static int usbtouch_probe(struct usb_interface *intf, if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; - usbtouch->data = usb_buffer_alloc(udev, type->rept_size, - GFP_KERNEL, &usbtouch->data_dma); + usbtouch->data = usb_alloc_coherent(udev, type->rept_size, + GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; -- cgit v1.2.2