Commit 70a3eff5 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (53 commits)
  Input: synaptics - fix reporting of min coordinates
  Input: tegra-kbc - enable key autorepeat
  Input: kxtj9 - fix locking typo in kxtj9_set_poll()
  Input: kxtj9 - fix bug in probe()
  Input: intel-mid-touch - remove pointless checking for variable 'found'
  Input: hp_sdc - staticize hp_sdc_kicker()
  Input: pmic8xxx-keypad - fix a leak of the IRQ during init failure
  Input: cy8ctmg110_ts - set reset_pin and irq_pin from platform data
  Input: cy8ctmg110_ts - constify i2c_device_id table
  Input: cy8ctmg110_ts - fix checking return value of i2c_master_send
  Input: lifebook - make dmi callback functions return 1
  Input: atkbd - make dmi callback functions return 1
  Input: gpio_keys - switch to using SIMPLE_DEV_PM_OPS
  Input: gpio_keys - add support for device-tree platform data
  Input: aiptek - remove double define
  Input: synaptics - set minimum coordinates as reported by firmware
  Input: synaptics - process button bits in AGM packets
  Input: synaptics - rename set_slot to be more descriptive
  Input: synaptics - fuzz position for touchpad with reduced filtering
  Input: synaptics - set resolution for MT_POSITION_X/Y axes
  ...
parents 9ed3689b aa7eb8e7
Device-Tree bindings for input/gpio_keys.c keyboard driver
Required properties:
- compatible = "gpio-keys";
Optional properties:
- autorepeat: Boolean, Enable auto repeat feature of Linux input
subsystem.
Each button (key) is represented as a sub-node of "gpio-keys":
Subnode properties:
- gpios: OF devcie-tree gpio specificatin.
- label: Descriptive name of the key.
- linux,code: Keycode to emit.
Optional subnode-properties:
- linux,input-type: Specify event type this button/key generates.
If not specified defaults to <1> == EV_KEY.
- debounce-interval: Debouncing interval time in milliseconds.
If not specified defaults to 5.
- gpio-key,wakeup: Boolean, button can wake-up the system.
Example nodes:
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
button@21 {
label = "GPIO Key UP";
linux,code = <103>;
gpios = <&gpio1 0 1>;
};
...
...@@ -154,10 +154,13 @@ static const struct xpad_device { ...@@ -154,10 +154,13 @@ static const struct xpad_device {
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
...@@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = { ...@@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = {
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
{ } { }
}; };
...@@ -545,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) ...@@ -545,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
struct usb_endpoint_descriptor *ep_irq_out; struct usb_endpoint_descriptor *ep_irq_out;
int error; int error;
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) if (xpad->xtype == XTYPE_UNKNOWN)
return 0; return 0;
xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
...@@ -579,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) ...@@ -579,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
static void xpad_stop_output(struct usb_xpad *xpad) static void xpad_stop_output(struct usb_xpad *xpad)
{ {
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) if (xpad->xtype != XTYPE_UNKNOWN)
usb_kill_urb(xpad->irq_out); usb_kill_urb(xpad->irq_out);
} }
static void xpad_deinit_output(struct usb_xpad *xpad) static void xpad_deinit_output(struct usb_xpad *xpad)
{ {
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { if (xpad->xtype != XTYPE_UNKNOWN) {
usb_free_urb(xpad->irq_out); usb_free_urb(xpad->irq_out);
usb_free_coherent(xpad->udev, XPAD_PKT_LEN, usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->odata, xpad->odata_dma); xpad->odata, xpad->odata_dma);
...@@ -632,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect ...@@ -632,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
case XTYPE_XBOX360W:
xpad->odata[0] = 0x00;
xpad->odata[1] = 0x01;
xpad->odata[2] = 0x0F;
xpad->odata[3] = 0xC0;
xpad->odata[4] = 0x00;
xpad->odata[5] = strong / 256;
xpad->odata[6] = weak / 256;
xpad->odata[7] = 0x00;
xpad->odata[8] = 0x00;
xpad->odata[9] = 0x00;
xpad->odata[10] = 0x00;
xpad->odata[11] = 0x00;
xpad->irq_out->transfer_buffer_length = 12;
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
default: default:
dbg("%s - rumble command sent to unsupported xpad type: %d", dbg("%s - rumble command sent to unsupported xpad type: %d",
__func__, xpad->xtype); __func__, xpad->xtype);
...@@ -644,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect ...@@ -644,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
static int xpad_init_ff(struct usb_xpad *xpad) static int xpad_init_ff(struct usb_xpad *xpad)
{ {
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) if (xpad->xtype == XTYPE_UNKNOWN)
return 0; return 0;
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
......
...@@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) ...@@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
atkbd_platform_fixup = atkbd_apply_forced_release_keylist; atkbd_platform_fixup = atkbd_apply_forced_release_keylist;
atkbd_platform_fixup_data = id->driver_data; atkbd_platform_fixup_data = id->driver_data;
return 0; return 1;
} }
static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
{ {
atkbd_platform_scancode_fixup = id->driver_data; atkbd_platform_scancode_fixup = id->driver_data;
return 0; return 1;
} }
static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Driver for keys on GPIO lines capable of generating interrupts. * Driver for keys on GPIO lines capable of generating interrupts.
* *
* Copyright 2005 Phil Blundell * Copyright 2005 Phil Blundell
* Copyright 2010, 2011 David Jander <david@protonic.nl>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -25,6 +26,8 @@ ...@@ -25,6 +26,8 @@
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
struct gpio_button_data { struct gpio_button_data {
struct gpio_keys_button *button; struct gpio_keys_button *button;
...@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, ...@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
if (!button->can_disable) if (!button->can_disable)
irqflags |= IRQF_SHARED; irqflags |= IRQF_SHARED;
error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata);
if (error < 0) { if (error < 0) {
dev_err(dev, "Unable to claim irq %d; error %d\n", dev_err(dev, "Unable to claim irq %d; error %d\n",
irq, error); irq, error);
...@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input) ...@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input)
ddata->disable(input->dev.parent); ddata->disable(input->dev.parent);
} }
/*
* Handlers for alternative sources of platform_data
*/
#ifdef CONFIG_OF
/*
* Translate OpenFirmware node properties into platform_data
*/
static int gpio_keys_get_devtree_pdata(struct device *dev,
struct gpio_keys_platform_data *pdata)
{
struct device_node *node, *pp;
int i;
struct gpio_keys_button *buttons;
const u32 *reg;
int len;
node = dev->of_node;
if (node == NULL)
return -ENODEV;
memset(pdata, 0, sizeof *pdata);
pdata->rep = !!of_get_property(node, "autorepeat", &len);
/* First count the subnodes */
pdata->nbuttons = 0;
pp = NULL;
while ((pp = of_get_next_child(node, pp)))
pdata->nbuttons++;
if (pdata->nbuttons == 0)
return -ENODEV;
buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
if (!buttons)
return -ENODEV;
pp = NULL;
i = 0;
while ((pp = of_get_next_child(node, pp))) {
enum of_gpio_flags flags;
if (!of_find_property(pp, "gpios", NULL)) {
pdata->nbuttons--;
dev_warn(dev, "Found button without gpios\n");
continue;
}
buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
reg = of_get_property(pp, "linux,code", &len);
if (!reg) {
dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
goto out_fail;
}
buttons[i].code = be32_to_cpup(reg);
buttons[i].desc = of_get_property(pp, "label", &len);
reg = of_get_property(pp, "linux,input-type", &len);
buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
reg = of_get_property(pp, "debounce-interval", &len);
buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
i++;
}
pdata->buttons = buttons;
return 0;
out_fail:
kfree(buttons);
return -ENODEV;
}
static struct of_device_id gpio_keys_of_match[] = {
{ .compatible = "gpio-keys", },
{ },
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
#else
static int gpio_keys_get_devtree_pdata(struct device *dev,
struct gpio_keys_platform_data *altp)
{
return -ENODEV;
}
#define gpio_keys_of_match NULL
#endif
static int __devinit gpio_keys_probe(struct platform_device *pdev) static int __devinit gpio_keys_probe(struct platform_device *pdev)
{ {
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata; struct gpio_keys_drvdata *ddata;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct gpio_keys_platform_data alt_pdata;
struct input_dev *input; struct input_dev *input;
int i, error; int i, error;
int wakeup = 0; int wakeup = 0;
if (!pdata) {
error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
if (error)
return error;
pdata = &alt_pdata;
}
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
pdata->nbuttons * sizeof(struct gpio_button_data), pdata->nbuttons * sizeof(struct gpio_button_data),
GFP_KERNEL); GFP_KERNEL);
...@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail1: fail1:
input_free_device(input); input_free_device(input);
kfree(ddata); kfree(ddata);
/* If we have no platform_data, we allocated buttons dynamically. */
if (!pdev->dev.platform_data)
kfree(pdata->buttons);
return error; return error;
} }
static int __devexit gpio_keys_remove(struct platform_device *pdev) static int __devexit gpio_keys_remove(struct platform_device *pdev)
{ {
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct input_dev *input = ddata->input; struct input_dev *input = ddata->input;
int i; int i;
...@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) ...@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < ddata->n_buttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio); int irq = gpio_to_irq(ddata->data[i].button->gpio);
free_irq(irq, &ddata->data[i]); free_irq(irq, &ddata->data[i]);
if (ddata->data[i].timer_debounce) if (ddata->data[i].timer_debounce)
del_timer_sync(&ddata->data[i].timer); del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work); cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio); gpio_free(ddata->data[i].button->gpio);
} }
input_unregister_device(input); input_unregister_device(input);
/*
* If we had no platform_data, we allocated buttons dynamically, and
* must free them here. ddata->data[0].button is the pointer to the
* beginning of the allocated array.
*/
if (!pdev->dev.platform_data)
kfree(ddata->data[0].button);
kfree(ddata);
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM
static int gpio_keys_suspend(struct device *dev) static int gpio_keys_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i; int i;
if (device_may_wakeup(&pdev->dev)) { if (device_may_wakeup(dev)) {
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button *button = ddata->data[i].button;
if (button->wakeup) { if (button->wakeup) {
int irq = gpio_to_irq(button->gpio); int irq = gpio_to_irq(button->gpio);
enable_irq_wake(irq); enable_irq_wake(irq);
...@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev) ...@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev)
static int gpio_keys_resume(struct device *dev) static int gpio_keys_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i; int i;
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button *button = ddata->data[i].button;
if (button->wakeup && device_may_wakeup(&pdev->dev)) { if (button->wakeup && device_may_wakeup(dev)) {
int irq = gpio_to_irq(button->gpio); int irq = gpio_to_irq(button->gpio);
disable_irq_wake(irq); disable_irq_wake(irq);
} }
...@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev) ...@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev)
return 0; return 0;
} }
static const struct dev_pm_ops gpio_keys_pm_ops = {
.suspend = gpio_keys_suspend,
.resume = gpio_keys_resume,
};
#endif #endif
static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
static struct platform_driver gpio_keys_device_driver = { static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe, .probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove), .remove = __devexit_p(gpio_keys_remove),
.driver = { .driver = {
.name = "gpio-keys", .name = "gpio-keys",
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &gpio_keys_pm_ops, .pm = &gpio_keys_pm_ops,
#endif .of_match_table = gpio_keys_of_match,
} }
}; };
...@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void) ...@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void)
platform_driver_unregister(&gpio_keys_device_driver); platform_driver_unregister(&gpio_keys_device_driver);
} }
module_init(gpio_keys_init); late_initcall(gpio_keys_init);
module_exit(gpio_keys_exit); module_exit(gpio_keys_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); MODULE_DESCRIPTION("Keyboard driver for GPIOs");
MODULE_ALIAS("platform:gpio-keys"); MODULE_ALIAS("platform:gpio-keys");
...@@ -146,7 +146,6 @@ struct lm8323_chip { ...@@ -146,7 +146,6 @@ struct lm8323_chip {
/* device lock */ /* device lock */
struct mutex lock; struct mutex lock;
struct i2c_client *client; struct i2c_client *client;
struct work_struct work;
struct input_dev *idev; struct input_dev *idev;
bool kp_enabled; bool kp_enabled;
bool pm_suspend; bool pm_suspend;
...@@ -162,7 +161,6 @@ struct lm8323_chip { ...@@ -162,7 +161,6 @@ struct lm8323_chip {
#define client_to_lm8323(c) container_of(c, struct lm8323_chip, client) #define client_to_lm8323(c) container_of(c, struct lm8323_chip, client)
#define dev_to_lm8323(d) container_of(d, struct lm8323_chip, client->dev) #define dev_to_lm8323(d) container_of(d, struct lm8323_chip, client->dev)
#define work_to_lm8323(w) container_of(w, struct lm8323_chip, work)
#define cdev_to_pwm(c) container_of(c, struct lm8323_pwm, cdev) #define cdev_to_pwm(c) container_of(c, struct lm8323_pwm, cdev)
#define work_to_pwm(w) container_of(w, struct lm8323_pwm, work) #define work_to_pwm(w) container_of(w, struct lm8323_pwm, work)
...@@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm) ...@@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm)
* Bottom half: handle the interrupt by posting key events, or dealing with * Bottom half: handle the interrupt by posting key events, or dealing with
* errors appropriately. * errors appropriately.
*/ */
static void lm8323_work(struct work_struct *work) static irqreturn_t lm8323_irq(int irq, void *_lm)
{ {
struct lm8323_chip *lm = work_to_lm8323(work); struct lm8323_chip *lm = _lm;
u8 ints; u8 ints;
int i; int i;
...@@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work) ...@@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work)
} }
mutex_unlock(&lm->lock); mutex_unlock(&lm->lock);
}
/*
* We cannot use I2C in interrupt context, so we just schedule work.
*/
static irqreturn_t lm8323_irq(int irq, void *data)
{
struct lm8323_chip *lm = data;
schedule_work(&lm->work);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client, ...@@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client,
lm->client = client; lm->client = client;
lm->idev = idev; lm->idev = idev;
mutex_init(&lm->lock); mutex_init(&lm->lock);
INIT_WORK(&lm->work, lm8323_work);
lm->size_x = pdata->size_x; lm->size_x = pdata->size_x;
lm->size_y = pdata->size_y; lm->size_y = pdata->size_y;
...@@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client, ...@@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client,
goto fail3; goto fail3;
} }
err = request_irq(client->irq, lm8323_irq, err = request_threaded_irq(client->irq, NULL, lm8323_irq,
IRQF_TRIGGER_FALLING | IRQF_DISABLED, IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm);
"lm8323", lm);
if (err) { if (err) {
dev_err(&client->dev, "could not get IRQ %d\n", client->irq); dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
goto fail4; goto fail4;
...@@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client) ...@@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
disable_irq_wake(client->irq); disable_irq_wake(client->irq);
free_irq(client->irq, lm); free_irq(client->irq, lm);
cancel_work_sync(&lm->work);
input_unregister_device(lm->idev); input_unregister_device(lm->idev);
......
...@@ -43,14 +43,15 @@ ...@@ -43,14 +43,15 @@
* enabled capacitance sensing inputs and its run/suspend mode. * enabled capacitance sensing inputs and its run/suspend mode.
*/ */
#define ELECTRODE_CONF_ADDR 0x5e #define ELECTRODE_CONF_ADDR 0x5e
#define ELECTRODE_CONF_QUICK_CHARGE 0x80
#define AUTO_CONFIG_CTRL_ADDR 0x7b #define AUTO_CONFIG_CTRL_ADDR 0x7b
#define AUTO_CONFIG_USL_ADDR 0x7d #define AUTO_CONFIG_USL_ADDR 0x7d
#define AUTO_CONFIG_LSL_ADDR 0x7e #define AUTO_CONFIG_LSL_ADDR 0x7e
#define AUTO_CONFIG_TL_ADDR 0x7f #define AUTO_CONFIG_TL_ADDR 0x7f
/* Threshold of touch/release trigger */ /* Threshold of touch/release trigger */
#define TOUCH_THRESHOLD 0x0f #define TOUCH_THRESHOLD 0x08
#define RELEASE_THRESHOLD 0x0a #define RELEASE_THRESHOLD 0x05
/* Masks for touch and release triggers */ /* Masks for touch and release triggers */
#define TOUCH_STATUS_MASK 0xfff #define TOUCH_STATUS_MASK 0xfff
/* MPR121 has 12 keys */ /* MPR121 has 12 keys */
...@@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata, ...@@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
struct i2c_client *client) struct i2c_client *client)
{ {
const struct mpr121_init_register *reg; const struct mpr121_init_register *reg;
unsigned char usl, lsl, tl; unsigned char usl, lsl, tl, eleconf;
int i, t, vdd, ret; int i, t, vdd, ret;
/* Set up touch/release threshold for ele0-ele11 */ /* Set up touch/release threshold for ele0-ele11 */
...@@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata, ...@@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl); ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl);
ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl); ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl);
ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl); ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl);
/*
* Quick charge bit will let the capacitive charge to ready
* state quickly, or the buttons may not function after system
* boot.
*/
eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE;
ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR, ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
mpr121->keycount); eleconf);
if (ret != 0) if (ret != 0)
goto err_i2c_write; goto err_i2c_write;
......
...@@ -700,9 +700,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) ...@@ -700,9 +700,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
return 0; return 0;
err_pmic_reg_read: err_pmic_reg_read:
free_irq(kp->key_stuck_irq, NULL); free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq: err_req_stuck_irq:
free_irq(kp->key_sense_irq, NULL); free_irq(kp->key_sense_irq, kp);
err_gpio_config: err_gpio_config:
err_get_irq: err_get_irq:
input_free_device(kp->input); input_free_device(kp->input);
...@@ -717,8 +717,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) ...@@ -717,8 +717,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
free_irq(kp->key_stuck_irq, NULL); free_irq(kp->key_stuck_irq, kp);
free_irq(kp->key_sense_irq, NULL); free_irq(kp->key_sense_irq, kp);
input_unregister_device(kp->input); input_unregister_device(kp->input);
kfree(kp); kfree(kp);
......
...@@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client) ...@@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client)
input_unregister_device(data->input); input_unregister_device(data->input);
kfree(data); kfree(data);
i2c_set_clientdata(client, NULL);
return 0; return 0;
} }
......
...@@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) ...@@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#if CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int sh_keysc_suspend(struct device *dev) static int sh_keysc_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
......
...@@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) ...@@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
input_set_drvdata(input_dev, kbc); input_set_drvdata(input_dev, kbc);
input_dev->evbit[0] = BIT_MASK(EV_KEY); input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_dev->keycode = kbc->keycode; input_dev->keycode = kbc->keycode;
......
...@@ -337,5 +337,5 @@ module_exit(keypad_exit); ...@@ -337,5 +337,5 @@ module_exit(keypad_exit);
MODULE_AUTHOR("Cyril Chemparathy"); MODULE_AUTHOR("Cyril Chemparathy");
MODULE_DESCRIPTION("TNETV107X Keypad Driver"); MODULE_DESCRIPTION("TNETV107X Keypad Driver");
MODULE_ALIAS("platform: tnetv107x-keypad"); MODULE_ALIAS("platform:tnetv107x-keypad");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -100,6 +100,27 @@ config INPUT_MAX8925_ONKEY ...@@ -100,6 +100,27 @@ config INPUT_MAX8925_ONKEY
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called max8925_onkey. will be called max8925_onkey.
config INPUT_MMA8450
tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
depends on I2C
select INPUT_POLLDEV
help
Say Y here if you want to support Freescale's MMA8450 Accelerometer
through I2C interface.
To compile this driver as a module, choose M here: the
module will be called mma8450.
config INPUT_MPU3050
tristate "MPU3050 Triaxial gyroscope sensor"
depends on I2C
help
Say Y here if you want to support InvenSense MPU3050
connected via an I2C bus.
To compile this driver as a module, choose M here: the
module will be called mpu3050.
config INPUT_APANEL config INPUT_APANEL
tristate "Fujitsu Lifebook Application Panel buttons" tristate "Fujitsu Lifebook Application Panel buttons"
depends on X86 && I2C && LEDS_CLASS depends on X86 && I2C && LEDS_CLASS
...@@ -209,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE ...@@ -209,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called keyspan_remote. be called keyspan_remote.
config INPUT_KXTJ9
tristate "Kionix KXTJ9 tri-axis digital accelerometer"
depends on I2C
help
Say Y here to enable support for the Kionix KXTJ9 digital tri-axis
accelerometer.
To compile this driver as a module, choose M here: the module will
be called kxtj9.
config INPUT_KXTJ9_POLLED_MODE
bool "Enable polling mode support"
depends on INPUT_KXTJ9
select INPUT_POLLDEV
help
Say Y here if you need accelerometer to work in polling mode.
config INPUT_POWERMATE config INPUT_POWERMATE
tristate "Griffin PowerMate and Contour Jog support" tristate "Griffin PowerMate and Contour Jog support"
depends on USB_ARCH_HAS_HCD depends on USB_ARCH_HAS_HCD
......
...@@ -25,8 +25,11 @@ obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o ...@@ -25,8 +25,11 @@ obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
obj-$(CONFIG_INPUT_MMA8450) += mma8450.o
obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
...@@ -46,4 +49,3 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o ...@@ -46,4 +49,3 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
......
This diff is collapsed.
/*
* Driver for Freescale's 3-Axis Accelerometer MMA8450
*
* Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input-polldev.h>
#define MMA8450_DRV_NAME "mma8450"
#define MODE_CHANGE_DELAY_MS 100
#define POLL_INTERVAL 100
#define POLL_INTERVAL_MAX 500
/* register definitions */
#define MMA8450_STATUS 0x00
#define MMA8450_STATUS_ZXYDR 0x08
#define MMA8450_OUT_X8 0x01
#define MMA8450_OUT_Y8 0x02
#define MMA8450_OUT_Z8 0x03
#define MMA8450_OUT_X_LSB 0x05
#define MMA8450_OUT_X_MSB 0x06
#define MMA8450_OUT_Y_LSB 0x07
#define MMA8450_OUT_Y_MSB 0x08
#define MMA8450_OUT_Z_LSB 0x09
#define MMA8450_OUT_Z_MSB 0x0a
#define MMA8450_XYZ_DATA_CFG 0x16
#define MMA8450_CTRL_REG1 0x38
#define MMA8450_CTRL_REG2 0x39
/* mma8450 status */
struct mma8450 {
struct i2c_client *client;
struct input_polled_dev *idev;
};
static int mma8450_read(struct mma8450 *m, unsigned off)
{
struct i2c_client *c = m->client;
int ret;
ret = i2c_smbus_read_byte_data(c, off);
if (ret < 0)
dev_err(&c->dev,
"failed to read register 0x%02x, error %d\n",
off, ret);
return ret;
}
static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
{
struct i2c_client *c = m->client;
int error;
error = i2c_smbus_write_byte_data(c, off, v);
if (error < 0) {
dev_err(&c->dev,
"failed to write to register 0x%02x, error %d\n",
off, error);
return error;
}
return 0;
}
static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
{
struct i2c_client *c = m->client;
u8 buff[6];
int err;
err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
if (err < 0) {
dev_err(&c->dev,
"failed to read block data at 0x%02x, error %d\n",
MMA8450_OUT_X_LSB, err);
return err;
}
*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
return 0;
}
static void mma8450_poll(struct input_polled_dev *dev)
{
struct mma8450 *m = dev->private;
int x, y, z;
int ret;
int err;
ret = mma8450_read(m, MMA8450_STATUS);
if (ret < 0)
return;
if (!(ret & MMA8450_STATUS_ZXYDR))
return;
err = mma8450_read_xyz(m, &x, &y, &z);
if (err)
return;
input_report_abs(dev->input, ABS_X, x);
input_report_abs(dev->input, ABS_Y, y);
input_report_abs(dev->input, ABS_Z, z);
input_sync(dev->input);
}
/* Initialize the MMA8450 chip */
static void mma8450_open(struct input_polled_dev *dev)
{
struct mma8450 *m = dev->private;
int err;
/* enable all events from X/Y/Z, no FIFO */
err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
if (err)
return;
/*
* Sleep mode poll rate - 50Hz
* System output data rate - 400Hz
* Full scale selection - Active, +/- 2G
*/
err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
if (err < 0)
return;
msleep(MODE_CHANGE_DELAY_MS);
}
static void mma8450_close(struct input_polled_dev *dev)
{
struct mma8450 *m = dev->private;
mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
}
/*
* I2C init/probing/exit functions
*/
static int __devinit mma8450_probe(struct i2c_client *c,
const struct i2c_device_id *id)
{
struct input_polled_dev *idev;
struct mma8450 *m;
int err;
m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
idev = input_allocate_polled_device();
if (!m || !idev) {
err = -ENOMEM;
goto err_free_mem;
}
m->client = c;
m->idev = idev;
idev->private = m;
idev->input->name = MMA8450_DRV_NAME;
idev->input->id.bustype = BUS_I2C;
idev->poll = mma8450_poll;
idev->poll_interval = POLL_INTERVAL;
idev->poll_interval_max = POLL_INTERVAL_MAX;
idev->open = mma8450_open;
idev->close = mma8450_close;
__set_bit(EV_ABS, idev->input->evbit);
input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
err = input_register_polled_device(idev);
if (err) {
dev_err(&c->dev, "failed to register polled input device\n");
goto err_free_mem;
}
return 0;
err_free_mem:
input_free_polled_device(idev);
kfree(m);
return err;
}
static int __devexit mma8450_remove(struct i2c_client *c)
{
struct mma8450 *m = i2c_get_clientdata(c);
struct input_polled_dev *idev = m->idev;
input_unregister_polled_device(idev);
input_free_polled_device(idev);
kfree(m);
return 0;
}
static const struct i2c_device_id mma8450_id[] = {
{ MMA8450_DRV_NAME, 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, mma8450_id);
static struct i2c_driver mma8450_driver = {
.driver = {
.name = MMA8450_DRV_NAME,
.owner = THIS_MODULE,
},
.probe = mma8450_probe,
.remove = __devexit_p(mma8450_remove),
.id_table = mma8450_id,
};
static int __init mma8450_init(void)
{
return i2c_add_driver(&mma8450_driver);
}
module_init(mma8450_init);
static void __exit mma8450_exit(void)
{
i2c_del_driver(&mma8450_driver);
}
module_exit(mma8450_exit);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
MODULE_LICENSE("GPL");
/*
* MPU3050 Tri-axis gyroscope driver
*
* Copyright (C) 2011 Wistron Co.Ltd
* Joseph Lai <joseph_lai@wistron.com>
*
* Trimmed down by Alan Cox <alan@linux.intel.com> to produce this version
*
* This is a 'lite' version of the driver, while we consider the right way
* to present the other features to user space. In particular it requires the
* device has an IRQ, and it only provides an input interface, so is not much
* use for device orientation. A fuller version is available from the Meego
* tree.
*
* This program is based on bma023.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#define MPU3050_CHIP_ID_REG 0x00
#define MPU3050_CHIP_ID 0x69
#define MPU3050_XOUT_H 0x1D
#define MPU3050_PWR_MGM 0x3E
#define MPU3050_PWR_MGM_POS 6
#define MPU3050_PWR_MGM_MASK 0x40
#define MPU3050_AUTO_DELAY 1000
#define MPU3050_MIN_VALUE -32768
#define MPU3050_MAX_VALUE 32767
struct axis_data {
s16 x;
s16 y;
s16 z;
};
struct mpu3050_sensor {
struct i2c_client *client;
struct device *dev;
struct input_dev *idev;
};
/**
* mpu3050_xyz_read_reg - read the axes values
* @buffer: provide register addr and get register
* @length: length of register
*
* Reads the register values in one transaction or returns a negative
* error code on failure.
*/
static int mpu3050_xyz_read_reg(struct i2c_client *client,
u8 *buffer, int length)
{
/*
* Annoying we can't make this const because the i2c layer doesn't
* declare input buffers const.
*/
char cmd = MPU3050_XOUT_H;
struct i2c_msg msg[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &cmd,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = buffer,
},
};
return i2c_transfer(client->adapter, msg, 2);
}
/**
* mpu3050_read_xyz - get co-ordinates from device
* @client: i2c address of sensor
* @coords: co-ordinates to update
*
* Return the converted X Y and Z co-ordinates from the sensor device
*/
static void mpu3050_read_xyz(struct i2c_client *client,
struct axis_data *coords)
{
u16 buffer[3];
mpu3050_xyz_read_reg(client, (u8 *)buffer, 6);
coords->x = be16_to_cpu(buffer[0]);
coords->y = be16_to_cpu(buffer[1]);
coords->z = be16_to_cpu(buffer[2]);
dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__,
coords->x, coords->y, coords->z);
}
/**
* mpu3050_set_power_mode - set the power mode
* @client: i2c client for the sensor
* @val: value to switch on/off of power, 1: normal power, 0: low power
*
* Put device to normal-power mode or low-power mode.
*/
static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
{
u8 value;
value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
value = (value & ~MPU3050_PWR_MGM_MASK) |
(((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
MPU3050_PWR_MGM_MASK);
i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
}
/**
* mpu3050_input_open - called on input event open
* @input: input dev of opened device
*
* The input layer calls this function when input event is opened. The
* function will push the device to resume. Then, the device is ready
* to provide data.
*/
static int mpu3050_input_open(struct input_dev *input)
{
struct mpu3050_sensor *sensor = input_get_drvdata(input);
pm_runtime_get(sensor->dev);
return 0;
}
/**
* mpu3050_input_close - called on input event close
* @input: input dev of closed device
*
* The input layer calls this function when input event is closed. The
* function will push the device to suspend.
*/
static void mpu3050_input_close(struct input_dev *input)
{
struct mpu3050_sensor *sensor = input_get_drvdata(input);
pm_runtime_put(sensor->dev);
}
/**
* mpu3050_interrupt_thread - handle an IRQ
* @irq: interrupt numner
* @data: the sensor
*
* Called by the kernel single threaded after an interrupt occurs. Read
* the sensor data and generate an input event for it.
*/
static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
{
struct mpu3050_sensor *sensor = data;
struct axis_data axis;
mpu3050_read_xyz(sensor->client, &axis);
input_report_abs(sensor->idev, ABS_X, axis.x);
input_report_abs(sensor->idev, ABS_Y, axis.y);
input_report_abs(sensor->idev, ABS_Z, axis.z);
input_sync(sensor->idev);
return IRQ_HANDLED;
}
/**
* mpu3050_probe - device detection callback
* @client: i2c client of found device
* @id: id match information
*
* The I2C layer calls us when it believes a sensor is present at this
* address. Probe to see if this is correct and to validate the device.
*
* If present install the relevant sysfs interfaces and input device.
*/
static int __devinit mpu3050_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mpu3050_sensor *sensor;
struct input_dev *idev;
int ret;
int error;
sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
idev = input_allocate_device();
if (!sensor || !idev) {
dev_err(&client->dev, "failed to allocate driver data\n");
error = -ENOMEM;
goto err_free_mem;
}
sensor->client = client;
sensor->dev = &client->dev;
sensor->idev = idev;
mpu3050_set_power_mode(client, 1);
msleep(10);
ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
if (ret < 0) {
dev_err(&client->dev, "failed to detect device\n");
error = -ENXIO;
goto err_free_mem;
}
if (ret != MPU3050_CHIP_ID) {
dev_err(&client->dev, "unsupported chip id\n");
error = -ENXIO;
goto err_free_mem;
}
idev->name = "MPU3050";
idev->id.bustype = BUS_I2C;
idev->dev.parent = &client->dev;
idev->open = mpu3050_input_open;
idev->close = mpu3050_input_close;
__set_bit(EV_ABS, idev->evbit);
input_set_abs_params(idev, ABS_X,
MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
input_set_abs_params(idev, ABS_Y,
MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
input_set_abs_params(idev, ABS_Z,
MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
input_set_drvdata(idev, sensor);
pm_runtime_set_active(&client->dev);
error = request_threaded_irq(client->irq,
NULL, mpu3050_interrupt_thread,
IRQF_TRIGGER_RISING,
"mpu_int", sensor);
if (error) {
dev_err(&client->dev,
"can't get IRQ %d, error %d\n", client->irq, error);
goto err_pm_set_suspended;
}
error = input_register_device(idev);
if (error) {
dev_err(&client->dev, "failed to register input device\n");
goto err_free_irq;
}
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
return 0;
err_free_irq:
free_irq(client->irq, sensor);
err_pm_set_suspended:
pm_runtime_set_suspended(&client->dev);
err_free_mem:
input_unregister_device(idev);
kfree(sensor);
return error;
}
/**
* mpu3050_remove - remove a sensor
* @client: i2c client of sensor being removed
*
* Our sensor is going away, clean up the resources.
*/
static int __devexit mpu3050_remove(struct i2c_client *client)
{
struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
free_irq(client->irq, sensor);
input_unregister_device(sensor->idev);
kfree(sensor);
return 0;
}
#ifdef CONFIG_PM
/**
* mpu3050_suspend - called on device suspend
* @dev: device being suspended
*
* Put the device into sleep mode before we suspend the machine.
*/
static int mpu3050_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
mpu3050_set_power_mode(client, 0);
return 0;
}
/**
* mpu3050_resume - called on device resume
* @dev: device being resumed
*
* Put the device into powered mode on resume.
*/
static int mpu3050_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
mpu3050_set_power_mode(client, 1);
msleep(100); /* wait for gyro chip resume */
return 0;
}
#endif
static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
static const struct i2c_device_id mpu3050_ids[] = {
{ "mpu3050", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
static struct i2c_driver mpu3050_i2c_driver = {
.driver = {
.name = "mpu3050",
.owner = THIS_MODULE,
.pm = &mpu3050_pm,
},
.probe = mpu3050_probe,
.remove = __devexit_p(mpu3050_remove),
.id_table = mpu3050_ids,
};
static int __init mpu3050_init(void)
{
return i2c_add_driver(&mpu3050_i2c_driver);
}
module_init(mpu3050_init);
static void __exit mpu3050_exit(void)
{
i2c_del_driver(&mpu3050_i2c_driver);
}
module_exit(mpu3050_exit);
MODULE_AUTHOR("Wistron Corp.");
MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
MODULE_LICENSE("GPL");
...@@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = { ...@@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = {
static int __init xenkbd_init(void) static int __init xenkbd_init(void)
{ {
if (!xen_pv_domain()) if (!xen_domain())
return -ENODEV; return -ENODEV;
/* Nothing to do if running in dom0. */ /* Nothing to do if running in dom0. */
......
...@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void) ...@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void)
} }
module_exit(gpio_mouse_exit); module_exit(gpio_mouse_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_DESCRIPTION("GPIO mouse driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
......
...@@ -33,7 +33,7 @@ static const char *desired_serio_phys; ...@@ -33,7 +33,7 @@ static const char *desired_serio_phys;
static int lifebook_limit_serio3(const struct dmi_system_id *d) static int lifebook_limit_serio3(const struct dmi_system_id *d)
{ {
desired_serio_phys = "isa0060/serio3"; desired_serio_phys = "isa0060/serio3";
return 0; return 1;
} }
static bool lifebook_use_6byte_proto; static bool lifebook_use_6byte_proto;
...@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto; ...@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto;
static int lifebook_set_6byte_proto(const struct dmi_system_id *d) static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
{ {
lifebook_use_6byte_proto = true; lifebook_use_6byte_proto = true;
return 0; return 1;
} }
static const struct dmi_system_id __initconst lifebook_dmi_table[] = { static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/version.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/libps2.h> #include <linux/libps2.h>
......
...@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse) ...@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse)
static int synaptics_resolution(struct psmouse *psmouse) static int synaptics_resolution(struct psmouse *psmouse)
{ {
struct synaptics_data *priv = psmouse->private; struct synaptics_data *priv = psmouse->private;
unsigned char res[3]; unsigned char resp[3];
unsigned char max[3];
if (SYN_ID_MAJOR(priv->identity) < 4) if (SYN_ID_MAJOR(priv->identity) < 4)
return 0; return 0;
if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) { if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
priv->x_res = res[0]; /* x resolution in units/mm */ priv->x_res = resp[0]; /* x resolution in units/mm */
priv->y_res = res[2]; /* y resolution in units/mm */ priv->y_res = resp[2]; /* y resolution in units/mm */
} }
} }
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
printk(KERN_ERR "Synaptics claims to have dimensions query," printk(KERN_ERR "Synaptics claims to have max coordinates"
" but I'm not able to read it.\n"); " query, but I'm not able to read it.\n");
} else {
priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
}
}
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
printk(KERN_ERR "Synaptics claims to have min coordinates"
" query, but I'm not able to read it.\n");
} else { } else {
priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1); priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3); priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
} }
} }
...@@ -406,26 +416,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ...@@ -406,26 +416,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
memset(hw, 0, sizeof(struct synaptics_hw_state)); memset(hw, 0, sizeof(struct synaptics_hw_state));
if (SYN_MODEL_NEWABS(priv->model_id)) { if (SYN_MODEL_NEWABS(priv->model_id)) {
hw->x = (((buf[3] & 0x10) << 8) |
((buf[1] & 0x0f) << 8) |
buf[4]);
hw->y = (((buf[3] & 0x20) << 7) |
((buf[1] & 0xf0) << 4) |
buf[5]);
hw->z = buf[2];
hw->w = (((buf[0] & 0x30) >> 2) | hw->w = (((buf[0] & 0x30) >> 2) |
((buf[0] & 0x04) >> 1) | ((buf[0] & 0x04) >> 1) |
((buf[3] & 0x04) >> 2)); ((buf[3] & 0x04) >> 2));
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
/* Gesture packet: (x, y, z) at half resolution */
priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
return 1;
}
hw->left = (buf[0] & 0x01) ? 1 : 0; hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0;
...@@ -448,6 +442,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ...@@ -448,6 +442,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
} }
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
/* Gesture packet: (x, y, z) at half resolution */
priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
return 1;
}
hw->x = (((buf[3] & 0x10) << 8) |
((buf[1] & 0x0f) << 8) |
buf[4]);
hw->y = (((buf[3] & 0x20) << 7) |
((buf[1] & 0xf0) << 4) |
buf[5]);
hw->z = buf[2];
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
((buf[0] ^ buf[3]) & 0x02)) { ((buf[0] ^ buf[3]) & 0x02)) {
switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
...@@ -485,7 +495,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ...@@ -485,7 +495,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
return 0; return 0;
} }
static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y) static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
bool active, int x, int y)
{ {
input_mt_slot(dev, slot); input_mt_slot(dev, slot);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
...@@ -502,14 +513,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev, ...@@ -502,14 +513,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
int num_fingers) int num_fingers)
{ {
if (num_fingers >= 2) { if (num_fingers >= 2) {
set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y)); synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y)); min(a->y, b->y));
synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
max(a->y, b->y));
} else if (num_fingers == 1) { } else if (num_fingers == 1) {
set_slot(dev, 0, true, a->x, a->y); synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
set_slot(dev, 1, false, 0, 0); synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
} else { } else {
set_slot(dev, 0, false, 0, 0); synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
set_slot(dev, 1, false, 0, 0); synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
} }
} }
...@@ -684,23 +697,36 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) ...@@ -684,23 +697,36 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
{ {
int i; int i;
int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
SYN_REDUCED_FILTER_FUZZ : 0;
__set_bit(INPUT_PROP_POINTER, dev->propbit); __set_bit(INPUT_PROP_POINTER, dev->propbit);
__set_bit(EV_ABS, dev->evbit); __set_bit(EV_ABS, dev->evbit);
input_set_abs_params(dev, ABS_X, input_set_abs_params(dev, ABS_X,
XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); priv->x_min ?: XMIN_NOMINAL,
priv->x_max ?: XMAX_NOMINAL,
fuzz, 0);
input_set_abs_params(dev, ABS_Y, input_set_abs_params(dev, ABS_Y,
YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); priv->y_min ?: YMIN_NOMINAL,
priv->y_max ?: YMAX_NOMINAL,
fuzz, 0);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit); __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2); input_mt_init_slots(dev, 2);
input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, input_set_abs_params(dev, ABS_MT_POSITION_X,
priv->x_max ?: XMAX_NOMINAL, 0, 0); priv->x_min ?: XMIN_NOMINAL,
input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL,
priv->y_max ?: YMAX_NOMINAL, 0, 0); fuzz, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y,
priv->y_min ?: YMIN_NOMINAL,
priv->y_max ?: YMAX_NOMINAL,
fuzz, 0);
input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
} }
if (SYN_CAP_PALMDETECT(priv->capabilities)) if (SYN_CAP_PALMDETECT(priv->capabilities))
...@@ -971,4 +997,3 @@ bool synaptics_supported(void) ...@@ -971,4 +997,3 @@ bool synaptics_supported(void)
} }
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
#define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09 #define SYN_QUE_EXT_CAPAB 0x09
#define SYN_QUE_EXT_CAPAB_0C 0x0c #define SYN_QUE_EXT_CAPAB_0C 0x0c
#define SYN_QUE_EXT_DIMENSIONS 0x0d #define SYN_QUE_EXT_MAX_COORDS 0x0d
#define SYN_QUE_EXT_MIN_COORDS 0x0f
/* synatics modes */ /* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7) #define SYN_BIT_ABSOLUTE_MODE (1 << 7)
...@@ -66,18 +67,21 @@ ...@@ -66,18 +67,21 @@
* 1 0x60 multifinger mode identifies firmware finger counting * 1 0x60 multifinger mode identifies firmware finger counting
* (not reporting!) algorithm. * (not reporting!) algorithm.
* Not particularly meaningful * Not particularly meaningful
* 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered
* 2 0x01 clickpad bit 1 2-button ClickPad * 2 0x01 clickpad bit 1 2-button ClickPad
* 2 0x02 deluxe LED controls touchpad support LED commands * 2 0x02 deluxe LED controls touchpad support LED commands
* ala multimedia control bar * ala multimedia control bar
* 2 0x04 reduced filtering firmware does less filtering on * 2 0x04 reduced filtering firmware does less filtering on
* position data, driver should watch * position data, driver should watch
* for noise. * for noise.
* 2 0x20 report min query 0x0f gives min coord reported
*/ */
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */
#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000)
#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000)
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400)
/* synaptics modes query bits */ /* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
...@@ -104,6 +108,9 @@ ...@@ -104,6 +108,9 @@
#define SYN_NEWABS_RELAXED 2 #define SYN_NEWABS_RELAXED 2
#define SYN_OLDABS 3 #define SYN_OLDABS 3
/* amount to fuzz position data when touchpad reports reduced filtering */
#define SYN_REDUCED_FILTER_FUZZ 8
/* /*
* A structure to describe the state of the touchpad hardware (buttons and pad) * A structure to describe the state of the touchpad hardware (buttons and pad)
*/ */
...@@ -130,7 +137,8 @@ struct synaptics_data { ...@@ -130,7 +137,8 @@ struct synaptics_data {
unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */
unsigned long int identity; /* Identification */ unsigned long int identity; /* Identification */
unsigned int x_res, y_res; /* X/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 int x_max, y_max; /* Max coordinates (from FW) */
unsigned int x_min, y_min; /* Min coordinates (from FW) */
unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */ unsigned char mode; /* current mode byte */
......
...@@ -372,6 +372,6 @@ static void __exit psif_exit(void) ...@@ -372,6 +372,6 @@ static void __exit psif_exit(void)
module_init(psif_init); module_init(psif_init);
module_exit(psif_exit); module_exit(psif_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver"); MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) ...@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
/************************* Keepalive timer task *********************/ /************************* Keepalive timer task *********************/
void hp_sdc_kicker (unsigned long data) static void hp_sdc_kicker(unsigned long data)
{ {
tasklet_schedule(&hp_sdc.task); tasklet_schedule(&hp_sdc.task);
/* Re-insert the periodic task. */ /* Re-insert the periodic task. */
......
...@@ -225,7 +225,6 @@ ...@@ -225,7 +225,6 @@
/* toolMode codes /* toolMode codes
*/ */
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
#define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL #define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL
#define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH #define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH
#define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "wacom_wac.h" #include "wacom_wac.h"
#include "wacom.h" #include "wacom.h"
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/hid.h>
/* resolution for penabled devices */ /* resolution for penabled devices */
#define WACOM_PL_RES 20 #define WACOM_PL_RES 20
...@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) ...@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
wacom->id[0] = 0; wacom->id[0] = 0;
input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
input_report_key(input, wacom->tool[0], prox); input_report_key(input, wacom->tool[0], prox);
input_event(input, EV_MSC, MSC_SERIAL, 1);
input_sync(input); /* sync last event */ input_sync(input); /* sync last event */
} }
...@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) ...@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = data[7] & 0xf8; prox = data[7] & 0xf8;
if (prox || wacom->id[1]) { if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID; wacom->id[1] = PAD_DEVICE_ID;
input_report_key(input, BTN_0, (data[7] & 0x40)); input_report_key(input, BTN_BACK, (data[7] & 0x40));
input_report_key(input, BTN_4, (data[7] & 0x80)); input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
input_report_rel(input, REL_WHEEL, rw); input_report_rel(input, REL_WHEEL, rw);
input_report_key(input, BTN_TOOL_FINGER, 0xf0);
if (!prox) if (!prox)
wacom->id[1] = 0; wacom->id[1] = 0;
input_report_abs(input, ABS_MISC, wacom->id[1]); input_report_abs(input, ABS_MISC, wacom->id[1]);
...@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) ...@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = (data[7] & 0xf8) || data[8]; prox = (data[7] & 0xf8) || data[8];
if (prox || wacom->id[1]) { if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID; wacom->id[1] = PAD_DEVICE_ID;
input_report_key(input, BTN_0, (data[7] & 0x08)); input_report_key(input, BTN_BACK, (data[7] & 0x08));
input_report_key(input, BTN_1, (data[7] & 0x20)); input_report_key(input, BTN_LEFT, (data[7] & 0x20));
input_report_key(input, BTN_4, (data[7] & 0x10)); input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
input_report_key(input, BTN_5, (data[7] & 0x40)); input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
input_report_key(input, BTN_TOOL_FINGER, 0xf0);
if (!prox) if (!prox)
wacom->id[1] = 0; wacom->id[1] = 0;
input_report_abs(input, ABS_MISC, wacom->id[1]); input_report_abs(input, ABS_MISC, wacom->id[1]);
input_event(input, EV_MSC, MSC_SERIAL, 0xf0); input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
retval = 1;
} }
retval = 1;
break; break;
} }
exit: exit:
...@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) ...@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
/* pad packets. Works as a second tool and is always in prox */ /* pad packets. Works as a second tool and is always in prox */
if (data[0] == WACOM_REPORT_INTUOSPAD) { if (data[0] == WACOM_REPORT_INTUOSPAD) {
/* initiate the pad as a device */
if (wacom->tool[1] != BTN_TOOL_FINGER)
wacom->tool[1] = BTN_TOOL_FINGER;
if (features->type >= INTUOS4S && features->type <= INTUOS4L) { if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
input_report_key(input, BTN_0, (data[2] & 0x01)); input_report_key(input, BTN_0, (data[2] & 0x01));
input_report_key(input, BTN_1, (data[3] & 0x01)); input_report_key(input, BTN_1, (data[3] & 0x01));
...@@ -1080,18 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, ...@@ -1080,18 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
switch (wacom_wac->features.type) { switch (wacom_wac->features.type) {
case WACOM_MO: case WACOM_MO:
__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); input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
/* fall through */ /* fall through */
case WACOM_G4: case WACOM_G4:
input_set_capability(input_dev, EV_MSC, MSC_SERIAL); input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
__set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit);
__set_bit(BTN_0, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit);
__set_bit(BTN_4, input_dev->keybit);
/* fall through */ /* fall through */
case GRAPHIRE: case GRAPHIRE:
...@@ -1127,10 +1119,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, ...@@ -1127,10 +1119,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
case CINTIQ: case CINTIQ:
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
__set_bit(BTN_0 + i, input_dev->keybit); __set_bit(BTN_0 + i, input_dev->keybit);
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); if (wacom_wac->features.type != WACOM_21UX2) {
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
wacom_setup_cintiq(wacom_wac); wacom_setup_cintiq(wacom_wac);
break; break;
...@@ -1151,8 +1145,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, ...@@ -1151,8 +1145,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(BTN_2, input_dev->keybit); __set_bit(BTN_2, input_dev->keybit);
__set_bit(BTN_3, 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_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
/* fall through */ /* fall through */
...@@ -1170,7 +1162,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, ...@@ -1170,7 +1162,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS4S: case INTUOS4S:
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
__set_bit(BTN_0 + i, input_dev->keybit); __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); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
wacom_setup_intuos(wacom_wac); wacom_setup_intuos(wacom_wac);
...@@ -1295,6 +1286,12 @@ static const struct wacom_features wacom_features_0x65 = ...@@ -1295,6 +1286,12 @@ static const struct wacom_features wacom_features_0x65 =
static const struct wacom_features wacom_features_0x69 = static const struct wacom_features wacom_features_0x69 =
{ "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511,
63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
static const struct wacom_features wacom_features_0x6A =
{ "Wacom Bamboo1 4x6", WACOM_PKGLEN_GRAPHIRE, 14760, 9225, 1023,
63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x6B =
{ "Wacom Bamboo1 5x8", WACOM_PKGLEN_GRAPHIRE, 21648, 13530, 1023,
63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x20 = static const struct wacom_features wacom_features_0x20 =
{ "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
...@@ -1427,6 +1424,9 @@ static const struct wacom_features wacom_features_0x90 = ...@@ -1427,6 +1424,9 @@ static const struct wacom_features wacom_features_0x90 =
static const struct wacom_features wacom_features_0x93 = static const struct wacom_features wacom_features_0x93 =
{ "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x97 =
{ "Wacom ISDv4 97", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 511,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x9A = static const struct wacom_features wacom_features_0x9A =
{ "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
...@@ -1458,7 +1458,7 @@ static const struct wacom_features wacom_features_0xD3 = ...@@ -1458,7 +1458,7 @@ static const struct wacom_features wacom_features_0xD3 =
{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD4 = static const struct wacom_features wacom_features_0xD4 =
{ "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD6 = static const struct wacom_features wacom_features_0xD6 =
{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
...@@ -1483,6 +1483,11 @@ static const struct wacom_features wacom_features_0x6004 = ...@@ -1483,6 +1483,11 @@ static const struct wacom_features wacom_features_0x6004 =
USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
.driver_info = (kernel_ulong_t)&wacom_features_##prod .driver_info = (kernel_ulong_t)&wacom_features_##prod
#define USB_DEVICE_DETAILED(prod, class, sub, proto) \
USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
sub, proto), \
.driver_info = (kernel_ulong_t)&wacom_features_##prod
#define USB_DEVICE_LENOVO(prod) \ #define USB_DEVICE_LENOVO(prod) \
USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
.driver_info = (kernel_ulong_t)&wacom_features_##prod .driver_info = (kernel_ulong_t)&wacom_features_##prod
...@@ -1506,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = { ...@@ -1506,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x64) }, { USB_DEVICE_WACOM(0x64) },
{ USB_DEVICE_WACOM(0x65) }, { USB_DEVICE_WACOM(0x65) },
{ USB_DEVICE_WACOM(0x69) }, { USB_DEVICE_WACOM(0x69) },
{ USB_DEVICE_WACOM(0x6A) },
{ USB_DEVICE_WACOM(0x6B) },
{ USB_DEVICE_WACOM(0x20) }, { USB_DEVICE_WACOM(0x20) },
{ USB_DEVICE_WACOM(0x21) }, { USB_DEVICE_WACOM(0x21) },
{ USB_DEVICE_WACOM(0x22) }, { USB_DEVICE_WACOM(0x22) },
...@@ -1545,7 +1552,13 @@ const struct usb_device_id wacom_ids[] = { ...@@ -1545,7 +1552,13 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xC5) }, { USB_DEVICE_WACOM(0xC5) },
{ USB_DEVICE_WACOM(0xC6) }, { USB_DEVICE_WACOM(0xC6) },
{ USB_DEVICE_WACOM(0xC7) }, { USB_DEVICE_WACOM(0xC7) },
{ USB_DEVICE_WACOM(0xCE) }, /*
* DTU-2231 has two interfaces on the same configuration,
* only one is used.
*/
{ USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ USB_DEVICE_WACOM(0xD0) }, { USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) }, { USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) }, { USB_DEVICE_WACOM(0xD2) },
...@@ -1560,6 +1573,7 @@ const struct usb_device_id wacom_ids[] = { ...@@ -1560,6 +1573,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xCC) }, { USB_DEVICE_WACOM(0xCC) },
{ USB_DEVICE_WACOM(0x90) }, { USB_DEVICE_WACOM(0x90) },
{ USB_DEVICE_WACOM(0x93) }, { USB_DEVICE_WACOM(0x93) },
{ USB_DEVICE_WACOM(0x97) },
{ USB_DEVICE_WACOM(0x9A) }, { USB_DEVICE_WACOM(0x9A) },
{ USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0x9F) },
{ USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE2) },
......
...@@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 ...@@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
ts->get_pendown_state = pdata->get_pendown_state; ts->get_pendown_state = pdata->get_pendown_state;
} else if (gpio_is_valid(pdata->gpio_pendown)) { } else if (gpio_is_valid(pdata->gpio_pendown)) {
err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN,
"ads7846_pendown");
if (err) { if (err) {
dev_err(&spi->dev, "failed to request pendown GPIO%d\n", dev_err(&spi->dev,
pdata->gpio_pendown); "failed to request/setup pendown GPIO%d: %d\n",
return err; pdata->gpio_pendown, err);
}
err = gpio_direction_input(pdata->gpio_pendown);
if (err) {
dev_err(&spi->dev, "failed to setup pendown GPIO%d\n",
pdata->gpio_pendown);
gpio_free(pdata->gpio_pendown);
return err; return err;
} }
......
...@@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id) ...@@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
data = ac97c_readl(atmel_wm97xx, CBRHR); data = ac97c_readl(atmel_wm97xx, CBRHR);
value = data & 0x0fff; value = data & 0x0fff;
source = data & WM97XX_ADCSRC_MASK; source = data & WM97XX_ADCSEL_MASK;
pen_down = (data & WM97XX_PEN_DOWN) >> 8; pen_down = (data & WM97XX_PEN_DOWN) >> 8;
if (source == WM97XX_ADCSEL_X) if (source == WM97XX_ADCSEL_X)
...@@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void) ...@@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void)
} }
module_exit(atmel_wm97xx_exit); module_exit(atmel_wm97xx_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
This diff is collapsed.
...@@ -84,9 +84,9 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, ...@@ -84,9 +84,9 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
memcpy(i2c_data + 1, value, len); memcpy(i2c_data + 1, value, len);
ret = i2c_master_send(client, i2c_data, len + 1); ret = i2c_master_send(client, i2c_data, len + 1);
if (ret != 1) { if (ret != len + 1) {
dev_err(&client->dev, "i2c write data cmd failed\n"); dev_err(&client->dev, "i2c write data cmd failed\n");
return ret ? ret : -EIO; return ret < 0 ? ret : -EIO;
} }
return 0; return 0;
...@@ -193,6 +193,8 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client, ...@@ -193,6 +193,8 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
ts->client = client; ts->client = client;
ts->input = input_dev; ts->input = input_dev;
ts->reset_pin = pdata->reset_pin;
ts->irq_pin = pdata->irq_pin;
snprintf(ts->phys, sizeof(ts->phys), snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev)); "%s/input0", dev_name(&client->dev));
...@@ -328,7 +330,7 @@ static int __devexit cy8ctmg110_remove(struct i2c_client *client) ...@@ -328,7 +330,7 @@ static int __devexit cy8ctmg110_remove(struct i2c_client *client)
return 0; return 0;
} }
static struct i2c_device_id cy8ctmg110_idtable[] = { static const struct i2c_device_id cy8ctmg110_idtable[] = {
{ CY8CTMG110_DRIVER_NAME, 1 }, { CY8CTMG110_DRIVER_NAME, 1 },
{ } { }
}; };
......
...@@ -448,15 +448,11 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev) ...@@ -448,15 +448,11 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
*/ */
static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
{ {
int err, i, found; int found = 0;
int err, i;
u8 r8; u8 r8;
found = -1;
for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) { for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
if (found >= 0)
break;
err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8); err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
if (err) if (err)
return err; return err;
...@@ -466,16 +462,15 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) ...@@ -466,16 +462,15 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
break; break;
} }
} }
if (found < 0)
return 0;
if (tsdev->vendor == PMIC_VENDOR_FS) { if (tsdev->vendor == PMIC_VENDOR_FS) {
if (found && found > (MRSTOUCH_MAX_CHANNELS - 18)) if (found > MRSTOUCH_MAX_CHANNELS - 18)
return -ENOSPC; return -ENOSPC;
} else { } else {
if (found && found > (MRSTOUCH_MAX_CHANNELS - 4)) if (found > MRSTOUCH_MAX_CHANNELS - 4)
return -ENOSPC; return -ENOSPC;
} }
return found; return found;
} }
......
...@@ -157,9 +157,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) ...@@ -157,9 +157,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
x, y, p); x, y, p);
/* are samples valid */ /* are samples valid */
if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
(y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
(p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
goto up; goto up;
/* coordinate is good */ /* coordinate is good */
......
...@@ -393,5 +393,5 @@ module_exit(tsc_exit); ...@@ -393,5 +393,5 @@ module_exit(tsc_exit);
MODULE_AUTHOR("Cyril Chemparathy"); MODULE_AUTHOR("Cyril Chemparathy");
MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
MODULE_ALIAS("platform: tnetv107x-ts"); MODULE_ALIAS("platform:tnetv107x-ts");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -215,8 +215,9 @@ static inline int is_pden(struct wm97xx *wm) ...@@ -215,8 +215,9 @@ static inline int is_pden(struct wm97xx *wm)
static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
{ {
int timeout = 5 * delay; int timeout = 5 * delay;
bool wants_pen = adcsel & WM97XX_PEN_DOWN;
if (!wm->pen_probably_down) { if (wants_pen && !wm->pen_probably_down) {
u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
if (!(data & WM97XX_PEN_DOWN)) if (!(data & WM97XX_PEN_DOWN))
return RC_PENUP; return RC_PENUP;
...@@ -224,13 +225,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -224,13 +225,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
} }
/* set up digitiser */ /* set up digitiser */
if (adcsel & 0x8000)
adcsel = ((adcsel & 0x7fff) + 3) << 12;
if (wm->mach_ops && wm->mach_ops->pre_sample) if (wm->mach_ops && wm->mach_ops->pre_sample)
wm->mach_ops->pre_sample(adcsel); wm->mach_ops->pre_sample(adcsel);
wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); | WM97XX_POLL | WM97XX_DELAY(delay));
/* wait 3 AC97 time slots + delay for conversion */ /* wait 3 AC97 time slots + delay for conversion */
poll_delay(delay); poll_delay(delay);
...@@ -256,13 +254,14 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -256,13 +254,14 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
wm->mach_ops->post_sample(adcsel); wm->mach_ops->post_sample(adcsel);
/* check we have correct sample */ /* check we have correct sample */
if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
*sample & WM97XX_ADCSEL_MASK); adcsel & WM97XX_ADCSEL_MASK,
*sample & WM97XX_ADCSEL_MASK);
return RC_PENUP; return RC_PENUP;
} }
if (!(*sample & WM97XX_PEN_DOWN)) { if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
wm->pen_probably_down = 0; wm->pen_probably_down = 0;
return RC_PENUP; return RC_PENUP;
} }
...@@ -277,14 +276,14 @@ static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) ...@@ -277,14 +276,14 @@ static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
{ {
int rc; int rc;
rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
if (pil) { if (pil) {
rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p); rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
} else } else
......
...@@ -255,8 +255,9 @@ static inline int is_pden(struct wm97xx *wm) ...@@ -255,8 +255,9 @@ static inline int is_pden(struct wm97xx *wm)
static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
{ {
int timeout = 5 * delay; int timeout = 5 * delay;
bool wants_pen = adcsel & WM97XX_PEN_DOWN;
if (!wm->pen_probably_down) { if (wants_pen && !wm->pen_probably_down) {
u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
if (!(data & WM97XX_PEN_DOWN)) if (!(data & WM97XX_PEN_DOWN))
return RC_PENUP; return RC_PENUP;
...@@ -264,13 +265,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -264,13 +265,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
} }
/* set up digitiser */ /* set up digitiser */
if (adcsel & 0x8000)
adcsel = ((adcsel & 0x7fff) + 3) << 12;
if (wm->mach_ops && wm->mach_ops->pre_sample) if (wm->mach_ops && wm->mach_ops->pre_sample)
wm->mach_ops->pre_sample(adcsel); wm->mach_ops->pre_sample(adcsel);
wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); | WM97XX_POLL | WM97XX_DELAY(delay));
/* wait 3 AC97 time slots + delay for conversion */ /* wait 3 AC97 time slots + delay for conversion */
poll_delay(delay); poll_delay(delay);
...@@ -296,13 +294,14 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -296,13 +294,14 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
wm->mach_ops->post_sample(adcsel); wm->mach_ops->post_sample(adcsel);
/* check we have correct sample */ /* check we have correct sample */
if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
*sample & WM97XX_ADCSEL_MASK); adcsel & WM97XX_ADCSEL_MASK,
*sample & WM97XX_ADCSEL_MASK);
return RC_PENUP; return RC_PENUP;
} }
if (!(*sample & WM97XX_PEN_DOWN)) { if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
wm->pen_probably_down = 0; wm->pen_probably_down = 0;
return RC_PENUP; return RC_PENUP;
} }
...@@ -387,16 +386,18 @@ static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) ...@@ -387,16 +386,18 @@ static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
} else { } else {
rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
&data->x);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
&data->y);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
if (pil && !five_wire) { if (pil && !five_wire) {
rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
&data->p); &data->p);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
......
...@@ -261,8 +261,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -261,8 +261,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
{ {
u16 dig1; u16 dig1;
int timeout = 5 * delay; int timeout = 5 * delay;
bool wants_pen = adcsel & WM97XX_PEN_DOWN;
if (!wm->pen_probably_down) { if (wants_pen && !wm->pen_probably_down) {
u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
if (!(data & WM97XX_PEN_DOWN)) if (!(data & WM97XX_PEN_DOWN))
return RC_PENUP; return RC_PENUP;
...@@ -270,15 +271,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -270,15 +271,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
} }
/* set up digitiser */ /* set up digitiser */
if (adcsel & 0x8000)
adcsel = 1 << ((adcsel & 0x7fff) + 3);
dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1); dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
dig1 &= ~WM9713_ADCSEL_MASK; dig1 &= ~WM9713_ADCSEL_MASK;
/* WM97XX_ADCSEL_* channels need to be converted to WM9713 format */
dig1 |= 1 << ((adcsel & WM97XX_ADCSEL_MASK) >> 12);
if (wm->mach_ops && wm->mach_ops->pre_sample) if (wm->mach_ops && wm->mach_ops->pre_sample)
wm->mach_ops->pre_sample(adcsel); wm->mach_ops->pre_sample(adcsel);
wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL); wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL);
/* wait 3 AC97 time slots + delay for conversion */ /* wait 3 AC97 time slots + delay for conversion */
poll_delay(delay); poll_delay(delay);
...@@ -304,13 +304,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) ...@@ -304,13 +304,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
wm->mach_ops->post_sample(adcsel); wm->mach_ops->post_sample(adcsel);
/* check we have correct sample */ /* check we have correct sample */
if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) { if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
*sample & WM97XX_ADCSRC_MASK); adcsel & WM97XX_ADCSEL_MASK,
*sample & WM97XX_ADCSEL_MASK);
return RC_PENUP; return RC_PENUP;
} }
if (!(*sample & WM97XX_PEN_DOWN)) { if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
wm->pen_probably_down = 0; wm->pen_probably_down = 0;
return RC_PENUP; return RC_PENUP;
} }
...@@ -400,14 +401,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) ...@@ -400,14 +401,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
} else { } else {
rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x); rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y); rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
if (pil) { if (pil) {
rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
&data->p); &data->p);
if (rc != RC_VALID) if (rc != RC_VALID)
return rc; return rc;
......
...@@ -122,9 +122,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) ...@@ -122,9 +122,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
x, y, p); x, y, p);
/* are samples valid */ /* are samples valid */
if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
(y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
(p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
goto up; goto up;
/* coordinate is good */ /* coordinate is good */
......
...@@ -119,9 +119,9 @@ struct input_keymap_entry { ...@@ -119,9 +119,9 @@ struct input_keymap_entry {
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */ #define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */ #define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */ #define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len) /* get event bits */
#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */ #define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set abs value/limits */ #define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */ #define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */ #define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
......
/*
* Copyright (C) 2011 Kionix, Inc.
* Written by Chris Hudson <chudson@kionix.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifndef __KXTJ9_H__
#define __KXTJ9_H__
#define KXTJ9_I2C_ADDR 0x0F
struct kxtj9_platform_data {
unsigned int min_interval; /* minimum poll interval (in milli-seconds) */
/*
* By default, x is axis 0, y is axis 1, z is axis 2; these can be
* changed to account for sensor orientation within the host device.
*/
u8 axis_map_x;
u8 axis_map_y;
u8 axis_map_z;
/*
* Each axis can be negated to account for sensor orientation within
* the host device.
*/
bool negate_x;
bool negate_y;
bool negate_z;
/* CTRL_REG1: set resolution, g-range, data ready enable */
/* Output resolution: 8-bit valid or 12-bit valid */
#define RES_8BIT 0
#define RES_12BIT (1 << 6)
u8 res_12bit;
/* Output g-range: +/-2g, 4g, or 8g */
#define KXTJ9_G_2G 0
#define KXTJ9_G_4G (1 << 3)
#define KXTJ9_G_8G (1 << 4)
u8 g_range;
/* DATA_CTRL_REG: controls the output data rate of the part */
#define ODR12_5F 0
#define ODR25F 1
#define ODR50F 2
#define ODR100F 3
#define ODR200F 4
#define ODR400F 5
#define ODR800F 6
u8 data_odr_init;
int (*init)(void);
void (*exit)(void);
int (*power_on)(void);
int (*power_off)(void);
};
#endif /* __KXTJ9_H__ */
...@@ -38,7 +38,11 @@ ...@@ -38,7 +38,11 @@
#define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */ #define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */
#define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */ #define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */
#define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */ #define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */
#define WM97XX_ADCSEL_MASK 0x7000 #define WM97XX_AUX_ID1 0x4000
#define WM97XX_AUX_ID2 0x5000
#define WM97XX_AUX_ID3 0x6000
#define WM97XX_AUX_ID4 0x7000
#define WM97XX_ADCSEL_MASK 0x7000 /* ADC selection mask */
#define WM97XX_COO 0x0800 /* enable coordinate mode */ #define WM97XX_COO 0x0800 /* enable coordinate mode */
#define WM97XX_CTC 0x0400 /* enable continuous mode */ #define WM97XX_CTC 0x0400 /* enable continuous mode */
#define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */ #define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */
...@@ -61,13 +65,6 @@ ...@@ -61,13 +65,6 @@
#define WM97XX_PRP_DET_DIG 0xc000 /* setect on, digitise on */ #define WM97XX_PRP_DET_DIG 0xc000 /* setect on, digitise on */
#define WM97XX_RPR 0x2000 /* wake up on pen down */ #define WM97XX_RPR 0x2000 /* wake up on pen down */
#define WM97XX_PEN_DOWN 0x8000 /* pen is down */ #define WM97XX_PEN_DOWN 0x8000 /* pen is down */
#define WM97XX_ADCSRC_MASK 0x7000 /* ADC source mask */
#define WM97XX_AUX_ID1 0x8001
#define WM97XX_AUX_ID2 0x8002
#define WM97XX_AUX_ID3 0x8003
#define WM97XX_AUX_ID4 0x8004
/* WM9712 Bits */ /* WM9712 Bits */
#define WM9712_45W 0x1000 /* set for 5-wire touchscreen */ #define WM9712_45W 0x1000 /* set for 5-wire touchscreen */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment