Commit 238ccbb0 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: (22 commits)
  Input: ALPS - add interleaved protocol support (Dell E6x00 series)
  Input: keyboard - don't override beep with a bell
  Input: altera_ps2 - fix test of unsigned in altera_ps2_probe()
  Input: add mc13783 touchscreen driver
  Input: ep93xx_keypad - update driver to new core support
  Input: wacom - separate pen from express keys on Graphire
  Input: wacom - add defines for data packet report IDs
  Input: wacom - add support for new LCD tablets
  Input: wacom - add defines for packet lengths of various devices
  Input: wacom - ensure the device is initialized properly upon resume
  Input: at32psif - do not sleep in atomic context
  Input: i8042 - add Gigabyte M1022M to the noloop list
  Input: i8042 - allow installing platform filters for incoming data
  Input: i8042 - fix locking in interrupt routine
  Input: ALPS - do not set REL_X/REL_Y capabilities on the touchpad
  Input: document use of input_event() function
  Input: sa1111ps2 - annotate probe() and remove() methods
  Input: ambakmi - annotate probe() and remove() methods
  Input: gscps2 - fix probe() and remove() annotations
  Input: altera_ps2 - add annotations to probe and remove methods
  ...
parents c5113e3d 1d9f2626
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#ifndef __ASM_ARCH_EP93XX_KEYPAD_H #ifndef __ASM_ARCH_EP93XX_KEYPAD_H
#define __ASM_ARCH_EP93XX_KEYPAD_H #define __ASM_ARCH_EP93XX_KEYPAD_H
#define MAX_MATRIX_KEY_ROWS (8)
#define MAX_MATRIX_KEY_COLS (8)
/* flags for the ep93xx_keypad driver */ /* flags for the ep93xx_keypad driver */
#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */ #define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */
#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ #define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */
...@@ -18,8 +15,6 @@ ...@@ -18,8 +15,6 @@
/** /**
* struct ep93xx_keypad_platform_data - platform specific device structure * struct ep93xx_keypad_platform_data - platform specific device structure
* @matrix_key_rows: number of rows in the keypad matrix
* @matrix_key_cols: number of columns in the keypad matrix
* @matrix_key_map: array of keycodes defining the keypad matrix * @matrix_key_map: array of keycodes defining the keypad matrix
* @matrix_key_map_size: ARRAY_SIZE(matrix_key_map) * @matrix_key_map_size: ARRAY_SIZE(matrix_key_map)
* @debounce: debounce start count; terminal count is 0xff * @debounce: debounce start count; terminal count is 0xff
...@@ -27,8 +22,6 @@ ...@@ -27,8 +22,6 @@
* @flags: see above * @flags: see above
*/ */
struct ep93xx_keypad_platform_data { struct ep93xx_keypad_platform_data {
unsigned int matrix_key_rows;
unsigned int matrix_key_cols;
unsigned int *matrix_key_map; unsigned int *matrix_key_map;
int matrix_key_map_size; int matrix_key_map_size;
unsigned int debounce; unsigned int debounce;
...@@ -36,7 +29,7 @@ struct ep93xx_keypad_platform_data { ...@@ -36,7 +29,7 @@ struct ep93xx_keypad_platform_data {
unsigned int flags; unsigned int flags;
}; };
/* macro for creating the matrix_key_map table */ #define EP93XX_MATRIX_ROWS (8)
#define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val)) #define EP93XX_MATRIX_COLS (8)
#endif /* __ASM_ARCH_EP93XX_KEYPAD_H */ #endif /* __ASM_ARCH_EP93XX_KEYPAD_H */
...@@ -233,7 +233,8 @@ int setkeycode(unsigned int scancode, unsigned int keycode) ...@@ -233,7 +233,8 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
} }
/* /*
* Making beeps and bells. * Making beeps and bells. Note that we prefer beeps to bells, but when
* shutting the sound off we do both.
*/ */
static int kd_sound_helper(struct input_handle *handle, void *data) static int kd_sound_helper(struct input_handle *handle, void *data)
...@@ -242,9 +243,12 @@ static int kd_sound_helper(struct input_handle *handle, void *data) ...@@ -242,9 +243,12 @@ static int kd_sound_helper(struct input_handle *handle, void *data)
struct input_dev *dev = handle->dev; struct input_dev *dev = handle->dev;
if (test_bit(EV_SND, dev->evbit)) { if (test_bit(EV_SND, dev->evbit)) {
if (test_bit(SND_TONE, dev->sndbit)) if (test_bit(SND_TONE, dev->sndbit)) {
input_inject_event(handle, EV_SND, SND_TONE, *hz); input_inject_event(handle, EV_SND, SND_TONE, *hz);
if (test_bit(SND_BELL, handle->dev->sndbit)) if (*hz)
return 0;
}
if (test_bit(SND_BELL, dev->sndbit))
input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0); input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
} }
......
...@@ -296,9 +296,15 @@ static void input_handle_event(struct input_dev *dev, ...@@ -296,9 +296,15 @@ static void input_handle_event(struct input_dev *dev,
* @value: value of the event * @value: value of the event
* *
* This function should be used by drivers implementing various input * This function should be used by drivers implementing various input
* devices. See also input_inject_event(). * devices to report input events. See also input_inject_event().
*
* NOTE: input_event() may be safely used right after input device was
* allocated with input_allocate_device(), even before it is registered
* with input_register_device(), but the event will not reach any of the
* input handlers. Such early invocation of input_event() may be used
* to 'seed' initial state of a switch or initial position of absolute
* axis, etc.
*/ */
void input_event(struct input_dev *dev, void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
......
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h>
#include <linux/input/matrix_keypad.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/ep93xx_keypad.h> #include <mach/ep93xx_keypad.h>
/* /*
...@@ -60,38 +60,37 @@ ...@@ -60,38 +60,37 @@
#define KEY_REG_KEY1_MASK (0x0000003f) #define KEY_REG_KEY1_MASK (0x0000003f)
#define KEY_REG_KEY1_SHIFT (0) #define KEY_REG_KEY1_SHIFT (0)
#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
#define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off))
#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
struct ep93xx_keypad { struct ep93xx_keypad {
struct ep93xx_keypad_platform_data *pdata; struct ep93xx_keypad_platform_data *pdata;
struct clk *clk;
struct input_dev *input_dev; struct input_dev *input_dev;
struct clk *clk;
void __iomem *mmio_base; void __iomem *mmio_base;
int irq; unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE];
int enabled;
int key1; int key1;
int key2; int key2;
unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; int irq;
bool enabled;
}; };
static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
{ {
struct ep93xx_keypad_platform_data *pdata = keypad->pdata; struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev; struct input_dev *input_dev = keypad->input_dev;
unsigned int *key;
int i; int i;
for (i = 0; i < pdata->matrix_key_map_size; i++) { key = &pdata->matrix_key_map[0];
unsigned int key = pdata->matrix_key_map[i]; for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
int row = (key >> 28) & 0xf; int row = KEY_ROW(*key);
int col = (key >> 24) & 0xf; int col = KEY_COL(*key);
int code = key & 0xffffff; int code = KEY_VAL(*key);
keypad->matrix_keycodes[(row << 3) + col] = code; keypad->matrix_keycodes[(row << 3) + col] = code;
__set_bit(code, input_dev->keybit); __set_bit(code, input_dev->keybit);
...@@ -102,9 +101,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) ...@@ -102,9 +101,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
{ {
struct ep93xx_keypad *keypad = dev_id; struct ep93xx_keypad *keypad = dev_id;
struct input_dev *input_dev = keypad->input_dev; struct input_dev *input_dev = keypad->input_dev;
unsigned int status = keypad_readl(KEY_REG); unsigned int status;
int keycode, key1, key2; int keycode, key1, key2;
status = __raw_readl(keypad->mmio_base + KEY_REG);
keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
key1 = keypad->matrix_keycodes[keycode]; key1 = keypad->matrix_keycodes[keycode];
...@@ -152,7 +153,10 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) ...@@ -152,7 +153,10 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
struct ep93xx_keypad_platform_data *pdata = keypad->pdata; struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
unsigned int val = 0; unsigned int val = 0;
clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV); if (pdata->flags & EP93XX_KEYPAD_KDIV)
clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4);
else
clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16);
if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
val |= KEY_INIT_DIS3KY; val |= KEY_INIT_DIS3KY;
...@@ -167,7 +171,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) ...@@ -167,7 +171,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
keypad_writel(val, KEY_INIT); __raw_writel(val, keypad->mmio_base + KEY_INIT);
} }
static int ep93xx_keypad_open(struct input_dev *pdev) static int ep93xx_keypad_open(struct input_dev *pdev)
...@@ -177,7 +181,7 @@ static int ep93xx_keypad_open(struct input_dev *pdev) ...@@ -177,7 +181,7 @@ static int ep93xx_keypad_open(struct input_dev *pdev)
if (!keypad->enabled) { if (!keypad->enabled) {
ep93xx_keypad_config(keypad); ep93xx_keypad_config(keypad);
clk_enable(keypad->clk); clk_enable(keypad->clk);
keypad->enabled = 1; keypad->enabled = true;
} }
return 0; return 0;
...@@ -189,7 +193,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) ...@@ -189,7 +193,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev)
if (keypad->enabled) { if (keypad->enabled) {
clk_disable(keypad->clk); clk_disable(keypad->clk);
keypad->enabled = 0; keypad->enabled = false;
} }
} }
...@@ -211,7 +215,7 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, ...@@ -211,7 +215,7 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev,
if (keypad->enabled) { if (keypad->enabled) {
clk_disable(keypad->clk); clk_disable(keypad->clk);
keypad->enabled = 0; keypad->enabled = false;
} }
mutex_unlock(&input_dev->mutex); mutex_unlock(&input_dev->mutex);
...@@ -236,7 +240,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) ...@@ -236,7 +240,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev)
if (!keypad->enabled) { if (!keypad->enabled) {
ep93xx_keypad_config(keypad); ep93xx_keypad_config(keypad);
clk_enable(keypad->clk); clk_enable(keypad->clk);
keypad->enabled = 1; keypad->enabled = true;
} }
} }
...@@ -252,88 +256,56 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) ...@@ -252,88 +256,56 @@ static int ep93xx_keypad_resume(struct platform_device *pdev)
static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
{ {
struct ep93xx_keypad *keypad; struct ep93xx_keypad *keypad;
struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input_dev; struct input_dev *input_dev;
struct resource *res; struct resource *res;
int irq, err, i, gpio; int err;
if (!pdata ||
!pdata->matrix_key_rows ||
pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
!pdata->matrix_key_cols ||
pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
dev_err(&pdev->dev, "invalid or missing platform data\n");
return -EINVAL;
}
keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
if (!keypad) { if (!keypad)
dev_err(&pdev->dev, "failed to allocate driver data\n");
return -ENOMEM; return -ENOMEM;
}
keypad->pdata = pdata; keypad->pdata = pdev->dev.platform_data;
if (!keypad->pdata) {
err = -EINVAL;
goto failed_free;
}
irq = platform_get_irq(pdev, 0); keypad->irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (!keypad->irq) {
dev_err(&pdev->dev, "failed to get keypad irq\n");
err = -ENXIO; err = -ENXIO;
goto failed_free; goto failed_free;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "failed to get I/O memory\n");
err = -ENXIO; err = -ENXIO;
goto failed_free; goto failed_free;
} }
res = request_mem_region(res->start, resource_size(res), pdev->name); res = request_mem_region(res->start, resource_size(res), pdev->name);
if (!res) { if (!res) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
err = -EBUSY; err = -EBUSY;
goto failed_free; goto failed_free;
} }
keypad->mmio_base = ioremap(res->start, resource_size(res)); keypad->mmio_base = ioremap(res->start, resource_size(res));
if (keypad->mmio_base == NULL) { if (keypad->mmio_base == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
err = -ENXIO; err = -ENXIO;
goto failed_free_mem; goto failed_free_mem;
} }
/* Request the needed GPIO's */ err = ep93xx_keypad_acquire_gpio(pdev);
gpio = EP93XX_GPIO_LINE_ROW0; if (err)
for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) { goto failed_free_io;
err = gpio_request(gpio, pdev->name);
if (err) {
dev_err(&pdev->dev, "failed to request gpio-%d\n",
gpio);
goto failed_free_rows;
}
}
gpio = EP93XX_GPIO_LINE_COL0;
for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) {
err = gpio_request(gpio, pdev->name);
if (err) {
dev_err(&pdev->dev, "failed to request gpio-%d\n",
gpio);
goto failed_free_cols;
}
}
keypad->clk = clk_get(&pdev->dev, "key_clk"); keypad->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(keypad->clk)) { if (IS_ERR(keypad->clk)) {
dev_err(&pdev->dev, "failed to get keypad clock\n");
err = PTR_ERR(keypad->clk); err = PTR_ERR(keypad->clk);
goto failed_free_io; goto failed_free_gpio;
} }
/* Create and register the input driver */
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev) {
dev_err(&pdev->dev, "failed to allocate input device\n");
err = -ENOMEM; err = -ENOMEM;
goto failed_put_clk; goto failed_put_clk;
} }
...@@ -358,44 +330,29 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) ...@@ -358,44 +330,29 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
ep93xx_keypad_build_keycode(keypad); ep93xx_keypad_build_keycode(keypad);
platform_set_drvdata(pdev, keypad); platform_set_drvdata(pdev, keypad);
err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED, err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
pdev->name, keypad); IRQF_DISABLED, pdev->name, keypad);
if (err) { if (err)
dev_err(&pdev->dev, "failed to request IRQ\n");
goto failed_free_dev; goto failed_free_dev;
}
keypad->irq = irq;
/* Register the input device */
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) { if (err)
dev_err(&pdev->dev, "failed to register input device\n");
goto failed_free_irq; goto failed_free_irq;
}
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
return 0; return 0;
failed_free_irq: failed_free_irq:
free_irq(irq, pdev); free_irq(keypad->irq, pdev);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
failed_free_dev: failed_free_dev:
input_free_device(input_dev); input_free_device(input_dev);
failed_put_clk: failed_put_clk:
clk_put(keypad->clk); clk_put(keypad->clk);
failed_free_gpio:
ep93xx_keypad_release_gpio(pdev);
failed_free_io: failed_free_io:
i = keypad->pdata->matrix_key_cols - 1;
gpio = EP93XX_GPIO_LINE_COL0 + i;
failed_free_cols:
for ( ; i >= 0; i--, gpio--)
gpio_free(gpio);
i = keypad->pdata->matrix_key_rows - 1;
gpio = EP93XX_GPIO_LINE_ROW0 + i;
failed_free_rows:
for ( ; i >= 0; i--, gpio--)
gpio_free(gpio);
iounmap(keypad->mmio_base); iounmap(keypad->mmio_base);
failed_free_mem: failed_free_mem:
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
...@@ -408,7 +365,6 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) ...@@ -408,7 +365,6 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
{ {
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct resource *res; struct resource *res;
int i, gpio;
free_irq(keypad->irq, pdev); free_irq(keypad->irq, pdev);
...@@ -420,15 +376,7 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) ...@@ -420,15 +376,7 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
input_unregister_device(keypad->input_dev); input_unregister_device(keypad->input_dev);
i = keypad->pdata->matrix_key_cols - 1; ep93xx_keypad_release_gpio(pdev);
gpio = EP93XX_GPIO_LINE_COL0 + i;
for ( ; i >= 0; i--, gpio--)
gpio_free(gpio);
i = keypad->pdata->matrix_key_rows - 1;
gpio = EP93XX_GPIO_LINE_ROW0 + i;
for ( ; i >= 0; i--, gpio--)
gpio_free(gpio);
iounmap(keypad->mmio_base); iounmap(keypad->mmio_base);
......
This diff is collapsed.
...@@ -23,6 +23,7 @@ struct alps_data { ...@@ -23,6 +23,7 @@ struct alps_data {
char phys[32]; /* Phys */ char phys[32]; /* Phys */
const struct alps_model_info *i;/* Info */ const struct alps_model_info *i;/* Info */
int prev_fin; /* Finger bit from previous packet */ int prev_fin; /* Finger bit from previous packet */
struct timer_list timer;
}; };
#ifdef CONFIG_MOUSE_PS2_ALPS #ifdef CONFIG_MOUSE_PS2_ALPS
......
...@@ -79,11 +79,11 @@ static void altera_ps2_close(struct serio *io) ...@@ -79,11 +79,11 @@ static void altera_ps2_close(struct serio *io)
/* /*
* Add one device to this driver. * Add one device to this driver.
*/ */
static int altera_ps2_probe(struct platform_device *pdev) static int __devinit altera_ps2_probe(struct platform_device *pdev)
{ {
struct ps2if *ps2if; struct ps2if *ps2if;
struct serio *serio; struct serio *serio;
int error; int error, irq;
ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL);
serio = kzalloc(sizeof(struct serio), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
...@@ -108,11 +108,13 @@ static int altera_ps2_probe(struct platform_device *pdev) ...@@ -108,11 +108,13 @@ static int altera_ps2_probe(struct platform_device *pdev)
goto err_free_mem; goto err_free_mem;
} }
ps2if->irq = platform_get_irq(pdev, 0);
if (ps2if->irq < 0) { irq = platform_get_irq(pdev, 0);
if (irq < 0) {
error = -ENXIO; error = -ENXIO;
goto err_free_mem; goto err_free_mem;
} }
ps2if->irq = irq;
if (!request_mem_region(ps2if->iomem_res->start, if (!request_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res), pdev->name)) { resource_size(ps2if->iomem_res), pdev->name)) {
...@@ -155,7 +157,7 @@ static int altera_ps2_probe(struct platform_device *pdev) ...@@ -155,7 +157,7 @@ static int altera_ps2_probe(struct platform_device *pdev)
/* /*
* Remove one device from this driver. * Remove one device from this driver.
*/ */
static int altera_ps2_remove(struct platform_device *pdev) static int __devexit altera_ps2_remove(struct platform_device *pdev)
{ {
struct ps2if *ps2if = platform_get_drvdata(pdev); struct ps2if *ps2if = platform_get_drvdata(pdev);
...@@ -175,9 +177,10 @@ static int altera_ps2_remove(struct platform_device *pdev) ...@@ -175,9 +177,10 @@ static int altera_ps2_remove(struct platform_device *pdev)
*/ */
static struct platform_driver altera_ps2_driver = { static struct platform_driver altera_ps2_driver = {
.probe = altera_ps2_probe, .probe = altera_ps2_probe,
.remove = altera_ps2_remove, .remove = __devexit_p(altera_ps2_remove),
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE,
}, },
}; };
......
...@@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) ...@@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io)
clk_disable(kmi->clk); clk_disable(kmi->clk);
} }
static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
{ {
struct amba_kmi_port *kmi; struct amba_kmi_port *kmi;
struct serio *io; struct serio *io;
...@@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) ...@@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
io->port_data = kmi; io->port_data = kmi;
io->dev.parent = &dev->dev; io->dev.parent = &dev->dev;
kmi->io = io; kmi->io = io;
kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); kmi->base = ioremap(dev->res.start, resource_size(&dev->res));
if (!kmi->base) { if (!kmi->base) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) ...@@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
return ret; return ret;
} }
static int amba_kmi_remove(struct amba_device *dev) static int __devexit amba_kmi_remove(struct amba_device *dev)
{ {
struct amba_kmi_port *kmi = amba_get_drvdata(dev); struct amba_kmi_port *kmi = amba_get_drvdata(dev);
...@@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = { ...@@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = {
static struct amba_driver ambakmi_driver = { static struct amba_driver ambakmi_driver = {
.drv = { .drv = {
.name = "kmi-pl050", .name = "kmi-pl050",
.owner = THIS_MODULE,
}, },
.id_table = amba_kmi_idtable, .id_table = amba_kmi_idtable,
.probe = amba_kmi_probe, .probe = amba_kmi_probe,
.remove = amba_kmi_remove, .remove = __devexit_p(amba_kmi_remove),
.resume = amba_kmi_resume, .resume = amba_kmi_resume,
}; };
......
...@@ -137,7 +137,7 @@ static int psif_write(struct serio *io, unsigned char val) ...@@ -137,7 +137,7 @@ static int psif_write(struct serio *io, unsigned char val)
spin_lock_irqsave(&psif->lock, flags); spin_lock_irqsave(&psif->lock, flags);
while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
msleep(10); udelay(50);
if (timeout >= 0) { if (timeout >= 0) {
psif_writel(psif, THR, val); psif_writel(psif, THR, val);
...@@ -352,6 +352,7 @@ static struct platform_driver psif_driver = { ...@@ -352,6 +352,7 @@ static struct platform_driver psif_driver = {
.remove = __exit_p(psif_remove), .remove = __exit_p(psif_remove),
.driver = { .driver = {
.name = "atmel_psif", .name = "atmel_psif",
.owner = THIS_MODULE,
}, },
.suspend = psif_suspend, .suspend = psif_suspend,
.resume = psif_resume, .resume = psif_resume,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
* *
* Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
* Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
* Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
* Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
...@@ -326,7 +326,7 @@ static void gscps2_close(struct serio *port) ...@@ -326,7 +326,7 @@ static void gscps2_close(struct serio *port)
* @return: success/error report * @return: success/error report
*/ */
static int __init gscps2_probe(struct parisc_device *dev) static int __devinit gscps2_probe(struct parisc_device *dev)
{ {
struct gscps2port *ps2port; struct gscps2port *ps2port;
struct serio *serio; struct serio *serio;
...@@ -443,7 +443,7 @@ static struct parisc_driver parisc_ps2_driver = { ...@@ -443,7 +443,7 @@ static struct parisc_driver parisc_ps2_driver = {
.name = "gsc_ps2", .name = "gsc_ps2",
.id_table = gscps2_device_tbl, .id_table = gscps2_device_tbl,
.probe = gscps2_probe, .probe = gscps2_probe,
.remove = gscps2_remove, .remove = __devexit_p(gscps2_remove),
}; };
static int __init gscps2_init(void) static int __init gscps2_init(void)
......
...@@ -993,10 +993,8 @@ int hil_mlc_unregister(hil_mlc *mlc) ...@@ -993,10 +993,8 @@ int hil_mlc_unregister(hil_mlc *mlc)
static int __init hil_mlc_init(void) static int __init hil_mlc_init(void)
{ {
init_timer(&hil_mlcs_kicker); setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
hil_mlcs_kicker.expires = jiffies + HZ; mod_timer(&hil_mlcs_kicker, jiffies + HZ);
hil_mlcs_kicker.function = &hil_mlcs_timer;
add_timer(&hil_mlcs_kicker);
tasklet_enable(&hil_mlcs_tasklet); tasklet_enable(&hil_mlcs_tasklet);
...@@ -1005,7 +1003,7 @@ static int __init hil_mlc_init(void) ...@@ -1005,7 +1003,7 @@ static int __init hil_mlc_init(void)
static void __exit hil_mlc_exit(void) static void __exit hil_mlc_exit(void)
{ {
del_timer(&hil_mlcs_kicker); del_timer_sync(&hil_mlcs_kicker);
tasklet_disable(&hil_mlcs_tasklet); tasklet_disable(&hil_mlcs_tasklet);
tasklet_kill(&hil_mlcs_tasklet); tasklet_kill(&hil_mlcs_tasklet);
......
...@@ -157,6 +157,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { ...@@ -157,6 +157,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "01"), DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
}, },
}, },
{
/* Gigabyte M1022M netbook */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
},
},
{ {
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
......
...@@ -126,6 +126,8 @@ static unsigned char i8042_suppress_kbd_ack; ...@@ -126,6 +126,8 @@ static unsigned char i8042_suppress_kbd_ack;
static struct platform_device *i8042_platform_device; static struct platform_device *i8042_platform_device;
static irqreturn_t i8042_interrupt(int irq, void *dev_id); static irqreturn_t i8042_interrupt(int irq, void *dev_id);
static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
struct serio *serio);
void i8042_lock_chip(void) void i8042_lock_chip(void)
{ {
...@@ -139,6 +141,48 @@ void i8042_unlock_chip(void) ...@@ -139,6 +141,48 @@ void i8042_unlock_chip(void)
} }
EXPORT_SYMBOL(i8042_unlock_chip); EXPORT_SYMBOL(i8042_unlock_chip);
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&i8042_lock, flags);
if (i8042_platform_filter) {
ret = -EBUSY;
goto out;
}
i8042_platform_filter = filter;
out:
spin_unlock_irqrestore(&i8042_lock, flags);
return ret;
}
EXPORT_SYMBOL(i8042_install_filter);
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *port))
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&i8042_lock, flags);
if (i8042_platform_filter != filter) {
ret = -EINVAL;
goto out;
}
i8042_platform_filter = NULL;
out:
spin_unlock_irqrestore(&i8042_lock, flags);
return ret;
}
EXPORT_SYMBOL(i8042_remove_filter);
/* /*
* The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
* be ready for reading values from it / writing values to it. * be ready for reading values from it / writing values to it.
...@@ -368,6 +412,31 @@ static void i8042_stop(struct serio *serio) ...@@ -368,6 +412,31 @@ static void i8042_stop(struct serio *serio)
port->serio = NULL; port->serio = NULL;
} }
/*
* i8042_filter() filters out unwanted bytes from the input data stream.
* It is called from i8042_interrupt and thus is running with interrupts
* off and i8042_lock held.
*/
static bool i8042_filter(unsigned char data, unsigned char str,
struct serio *serio)
{
if (unlikely(i8042_suppress_kbd_ack)) {
if ((~str & I8042_STR_AUXDATA) &&
(data == 0xfa || data == 0xfe)) {
i8042_suppress_kbd_ack--;
dbg("Extra keyboard ACK - filtered out\n");
return true;
}
}
if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) {
dbg("Filtered out by platfrom filter\n");
return true;
}
return false;
}
/* /*
* i8042_interrupt() is the most important function in this driver - * i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes * it handles the interrupts from the i8042, and sends incoming bytes
...@@ -377,13 +446,16 @@ static void i8042_stop(struct serio *serio) ...@@ -377,13 +446,16 @@ static void i8042_stop(struct serio *serio)
static irqreturn_t i8042_interrupt(int irq, void *dev_id) static irqreturn_t i8042_interrupt(int irq, void *dev_id)
{ {
struct i8042_port *port; struct i8042_port *port;
struct serio *serio;
unsigned long flags; unsigned long flags;
unsigned char str, data; unsigned char str, data;
unsigned int dfl; unsigned int dfl;
unsigned int port_no; unsigned int port_no;
bool filtered;
int ret = 1; int ret = 1;
spin_lock_irqsave(&i8042_lock, flags); spin_lock_irqsave(&i8042_lock, flags);
str = i8042_read_status(); str = i8042_read_status();
if (unlikely(~str & I8042_STR_OBF)) { if (unlikely(~str & I8042_STR_OBF)) {
spin_unlock_irqrestore(&i8042_lock, flags); spin_unlock_irqrestore(&i8042_lock, flags);
...@@ -391,8 +463,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) ...@@ -391,8 +463,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
ret = 0; ret = 0;
goto out; goto out;
} }
data = i8042_read_data(); data = i8042_read_data();
spin_unlock_irqrestore(&i8042_lock, flags);
if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
static unsigned long last_transmit; static unsigned long last_transmit;
...@@ -441,21 +513,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) ...@@ -441,21 +513,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
} }
port = &i8042_ports[port_no]; port = &i8042_ports[port_no];
serio = port->exists ? port->serio : NULL;
dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", dbg("%02x <- i8042 (interrupt, %d, %d%s%s)",
data, port_no, irq, data, port_no, irq,
dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : ""); dfl & SERIO_TIMEOUT ? ", timeout" : "");
if (unlikely(i8042_suppress_kbd_ack)) filtered = i8042_filter(data, str, serio);
if (port_no == I8042_KBD_PORT_NO &&
(data == 0xfa || data == 0xfe)) { spin_unlock_irqrestore(&i8042_lock, flags);
i8042_suppress_kbd_ack--;
goto out;
}
if (likely(port->exists)) if (likely(port->exists && !filtered))
serio_interrupt(port->serio, data, dfl); serio_interrupt(serio, data, dfl);
out: out:
return IRQ_RETVAL(ret); return IRQ_RETVAL(ret);
......
...@@ -180,8 +180,8 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) ...@@ -180,8 +180,8 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
} }
} }
static inline unsigned int static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
ps2_test_one(struct ps2if *ps2if, unsigned int mask) unsigned int mask)
{ {
unsigned int val; unsigned int val;
...@@ -197,7 +197,7 @@ ps2_test_one(struct ps2if *ps2if, unsigned int mask) ...@@ -197,7 +197,7 @@ ps2_test_one(struct ps2if *ps2if, unsigned int mask)
* Test the keyboard interface. We basically check to make sure that * Test the keyboard interface. We basically check to make sure that
* we can drive each line to the keyboard independently of each other. * we can drive each line to the keyboard independently of each other.
*/ */
static int __init ps2_test(struct ps2if *ps2if) static int __devinit ps2_test(struct ps2if *ps2if)
{ {
unsigned int stat; unsigned int stat;
int ret = 0; int ret = 0;
...@@ -312,7 +312,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) ...@@ -312,7 +312,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
/* /*
* Remove one device from this driver. * Remove one device from this driver.
*/ */
static int ps2_remove(struct sa1111_dev *dev) static int __devexit ps2_remove(struct sa1111_dev *dev)
{ {
struct ps2if *ps2if = sa1111_get_drvdata(dev); struct ps2if *ps2if = sa1111_get_drvdata(dev);
...@@ -335,7 +335,7 @@ static struct sa1111_driver ps2_driver = { ...@@ -335,7 +335,7 @@ static struct sa1111_driver ps2_driver = {
}, },
.devid = SA1111_DEVID_PS2, .devid = SA1111_DEVID_PS2,
.probe = ps2_probe, .probe = ps2_probe,
.remove = ps2_remove, .remove = __devexit_p(ps2_remove),
}; };
static int __init ps2_init(void) static int __init ps2_init(void)
......
/* /*
* drivers/input/tablet/wacom.h * drivers/input/tablet/wacom.h
* *
* USB Wacom Graphire and Wacom Intuos tablet support * USB Wacom tablet support
* *
* Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk>
...@@ -69,6 +69,9 @@ ...@@ -69,6 +69,9 @@
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
* v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
* v1.51 (pc) - Added support for Intuos4 * v1.51 (pc) - Added support for Intuos4
* v1.52 (pc) - Query Wacom data upon system resume
* - add defines for features->type
* - add new devices (0x9F, 0xE2, and 0XE3)
*/ */
/* /*
...@@ -89,9 +92,9 @@ ...@@ -89,9 +92,9 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v1.51" #define DRIVER_VERSION "v1.52"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_DESC "USB Wacom tablet driver"
#define DRIVER_LICENSE "GPL" #define DRIVER_LICENSE "GPL"
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
...@@ -133,6 +136,8 @@ extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_w ...@@ -133,6 +136,8 @@ extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_w
extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data); extern __u16 wacom_le16_to_cpu(unsigned char *data);
......
This diff is collapsed.
This diff is collapsed.
...@@ -9,12 +9,33 @@ ...@@ -9,12 +9,33 @@
#ifndef WACOM_WAC_H #ifndef WACOM_WAC_H
#define WACOM_WAC_H #define WACOM_WAC_H
/* maximum packet length for USB devices */
#define WACOM_PKGLEN_MAX 32
/* packet length for individual models */
#define WACOM_PKGLEN_PENPRTN 7
#define WACOM_PKGLEN_GRAPHIRE 8
#define WACOM_PKGLEN_BBFUN 9
#define WACOM_PKGLEN_INTUOS 10
#define WACOM_PKGLEN_PENABLED 8
#define WACOM_PKGLEN_TPC1FG 5
#define WACOM_PKGLEN_TPC2FG 14
/* device IDs */
#define STYLUS_DEVICE_ID 0x02 #define STYLUS_DEVICE_ID 0x02
#define TOUCH_DEVICE_ID 0x03 #define TOUCH_DEVICE_ID 0x03
#define CURSOR_DEVICE_ID 0x06 #define CURSOR_DEVICE_ID 0x06
#define ERASER_DEVICE_ID 0x0A #define ERASER_DEVICE_ID 0x0A
#define PAD_DEVICE_ID 0x0F #define PAD_DEVICE_ID 0x0F
/* wacom data packet report IDs */
#define WACOM_REPORT_PENABLED 2
#define WACOM_REPORT_INTUOSREAD 5
#define WACOM_REPORT_INTUOSWRITE 6
#define WACOM_REPORT_INTUOSPAD 12
#define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13
enum { enum {
PENPARTNER = 0, PENPARTNER = 0,
GRAPHIRE, GRAPHIRE,
...@@ -32,6 +53,7 @@ enum { ...@@ -32,6 +53,7 @@ enum {
WACOM_BEE, WACOM_BEE,
WACOM_MO, WACOM_MO,
TABLETPC, TABLETPC,
TABLETPC2FG,
MAX_TYPE MAX_TYPE
}; };
...@@ -43,8 +65,11 @@ struct wacom_features { ...@@ -43,8 +65,11 @@ struct wacom_features {
int pressure_max; int pressure_max;
int distance_max; int distance_max;
int type; int type;
int touch_x_max; int device_type;
int touch_y_max; int x_phy;
int y_phy;
unsigned char unit;
unsigned char unitExpo;
}; };
struct wacom_wac { struct wacom_wac {
......
...@@ -450,6 +450,18 @@ config TOUCHSCREEN_USB_COMPOSITE ...@@ -450,6 +450,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called usbtouchscreen. module will be called usbtouchscreen.
config TOUCHSCREEN_MC13783
tristate "Freescale MC13783 touchscreen input driver"
depends on MFD_MC13783
help
Say Y here if you have an Freescale MC13783 PMIC on your
board and want to use its touchscreen
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mc13783_ts.
config TOUCHSCREEN_USB_EGALAX config TOUCHSCREEN_USB_EGALAX
default y default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
......
...@@ -18,6 +18,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
......
/*
* Driver for the Freescale Semiconductor MC13783 touchscreen.
*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2009 Sascha Hauer, Pengutronix
*
* Initial development of this code was funded by
* Phytec Messtechnik GmbH, http://www.phytec.de/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/mfd/mc13783.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/sched.h>
#include <linux/init.h>
#define MC13783_TS_NAME "mc13783-ts"
#define DEFAULT_SAMPLE_TOLERANCE 300
static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(sample_tolerance,
"If the minimal and maximal value read out for one axis (out "
"of three) differ by this value (default: "
__stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
"is supposed to be wrong and is discarded. Set to 0 to "
"disable this check.");
struct mc13783_ts_priv {
struct input_dev *idev;
struct mc13783 *mc13783;
struct delayed_work work;
struct workqueue_struct *workq;
unsigned int sample[4];
};
static irqreturn_t mc13783_ts_handler(int irq, void *data)
{
struct mc13783_ts_priv *priv = data;
mc13783_ackirq(priv->mc13783, irq);
/*
* Kick off reading coordinates. Note that if work happens already
* be queued for future execution (it rearms itself) it will not
* be rescheduled for immediate execution here. However the rearm
* delay is HZ / 50 which is acceptable.
*/
queue_delayed_work(priv->workq, &priv->work, 0);
return IRQ_HANDLED;
}
#define sort3(a0, a1, a2) ({ \
if (a0 > a1) \
swap(a0, a1); \
if (a1 > a2) \
swap(a1, a2); \
if (a0 > a1) \
swap(a0, a1); \
})
static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
{
struct input_dev *idev = priv->idev;
int x0, x1, x2, y0, y1, y2;
int cr0, cr1;
/*
* the values are 10-bit wide only, but the two least significant
* bits are for future 12 bit use and reading yields 0
*/
x0 = priv->sample[0] & 0xfff;
x1 = priv->sample[1] & 0xfff;
x2 = priv->sample[2] & 0xfff;
y0 = priv->sample[3] & 0xfff;
y1 = (priv->sample[0] >> 12) & 0xfff;
y2 = (priv->sample[1] >> 12) & 0xfff;
cr0 = (priv->sample[2] >> 12) & 0xfff;
cr1 = (priv->sample[3] >> 12) & 0xfff;
dev_dbg(&idev->dev,
"x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
x0, x1, x2, y0, y1, y2, cr0, cr1);
sort3(x0, x1, x2);
sort3(y0, y1, y2);
cr0 = (cr0 + cr1) / 2;
if (!cr0 || !sample_tolerance ||
(x2 - x0 < sample_tolerance &&
y2 - y0 < sample_tolerance)) {
/* report the median coordinate and average pressure */
if (cr0) {
input_report_abs(idev, ABS_X, x1);
input_report_abs(idev, ABS_Y, y1);
dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
x1, y1, 0x1000 - cr0);
queue_delayed_work(priv->workq, &priv->work, HZ / 50);
} else
dev_dbg(&idev->dev, "report release\n");
input_report_abs(idev, ABS_PRESSURE,
cr0 ? 0x1000 - cr0 : cr0);
input_report_key(idev, BTN_TOUCH, cr0);
input_sync(idev);
} else
dev_dbg(&idev->dev, "discard event\n");
}
static void mc13783_ts_work(struct work_struct *work)
{
struct mc13783_ts_priv *priv =
container_of(work, struct mc13783_ts_priv, work.work);
unsigned int mode = MC13783_ADC_MODE_TS;
unsigned int channel = 12;
if (mc13783_adc_do_conversion(priv->mc13783,
mode, channel, priv->sample) == 0)
mc13783_ts_report_sample(priv);
}
static int mc13783_ts_open(struct input_dev *dev)
{
struct mc13783_ts_priv *priv = input_get_drvdata(dev);
int ret;
mc13783_lock(priv->mc13783);
mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
mc13783_ts_handler, MC13783_TS_NAME, priv);
if (ret)
goto out;
ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
if (ret)
mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
out:
mc13783_unlock(priv->mc13783);
return ret;
}
static void mc13783_ts_close(struct input_dev *dev)
{
struct mc13783_ts_priv *priv = input_get_drvdata(dev);
mc13783_lock(priv->mc13783);
mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
MC13783_ADC0_TSMOD_MASK, 0);
mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
mc13783_unlock(priv->mc13783);
cancel_delayed_work_sync(&priv->work);
}
static int __init mc13783_ts_probe(struct platform_device *pdev)
{
struct mc13783_ts_priv *priv;
struct input_dev *idev;
int ret = -ENOMEM;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
idev = input_allocate_device();
if (!priv || !idev)
goto err_free_mem;
INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
priv->idev = idev;
/*
* We need separate workqueue because mc13783_adc_do_conversion
* uses keventd and thus would deadlock.
*/
priv->workq = create_singlethread_workqueue("mc13783_ts");
if (!priv->workq)
goto err_free_mem;
idev->name = MC13783_TS_NAME;
idev->dev.parent = &pdev->dev;
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
idev->open = mc13783_ts_open;
idev->close = mc13783_ts_close;
input_set_drvdata(idev, priv);
ret = input_register_device(priv->idev);
if (ret) {
dev_err(&pdev->dev,
"register input device failed with %d\n", ret);
goto err_destroy_wq;
}
platform_set_drvdata(pdev, priv);
return 0;
err_destroy_wq:
destroy_workqueue(priv->workq);
err_free_mem:
input_free_device(idev);
kfree(priv);
return ret;
}
static int __devexit mc13783_ts_remove(struct platform_device *pdev)
{
struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
destroy_workqueue(priv->workq);
input_unregister_device(priv->idev);
kfree(priv);
return 0;
}
static struct platform_driver mc13783_ts_driver = {
.remove = __devexit_p(mc13783_ts_remove),
.driver = {
.owner = THIS_MODULE,
.name = MC13783_TS_NAME,
},
};
static int __init mc13783_ts_init(void)
{
return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
}
module_init(mc13783_ts_init);
static void __exit mc13783_ts_exit(void)
{
platform_driver_unregister(&mc13783_ts_driver);
}
module_exit(mc13783_ts_exit);
MODULE_DESCRIPTION("MC13783 input touchscreen driver");
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" MC13783_TS_NAME);
...@@ -39,6 +39,10 @@ void i8042_lock_chip(void); ...@@ -39,6 +39,10 @@ void i8042_lock_chip(void);
void i8042_unlock_chip(void); void i8042_unlock_chip(void);
int i8042_command(unsigned char *param, int command); int i8042_command(unsigned char *param, int command);
bool i8042_check_port_owner(const struct serio *); bool i8042_check_port_owner(const struct serio *);
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio));
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio));
#else #else
...@@ -52,7 +56,7 @@ void i8042_unlock_chip(void) ...@@ -52,7 +56,7 @@ void i8042_unlock_chip(void)
int i8042_command(unsigned char *param, int command) int i8042_command(unsigned char *param, int command)
{ {
return -ENOSYS; return -ENODEV;
} }
bool i8042_check_port_owner(const struct serio *serio) bool i8042_check_port_owner(const struct serio *serio)
...@@ -60,6 +64,18 @@ bool i8042_check_port_owner(const struct serio *serio) ...@@ -60,6 +64,18 @@ bool i8042_check_port_owner(const struct serio *serio)
return false; return false;
} }
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
return -ENODEV;
}
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
return -ENODEV;
}
#endif #endif
#endif #endif
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