Commit 9f7a9b11 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull input updates from Dmitry Torokhov:

 - three new touchscreen drivers: EETI EXC3000, HiDeep, and Samsung
   S6SY761

 - the timer API conversion (setup_timer() -> timer_setup())

 - a few drivers swiytched to using managed API for creating custom
   device attributes

 - other assorted fixed and cleanups.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (50 commits)
  Input: gamecon - mark expected switch fall-throughs
  Input: sidewinder - mark expected switch fall-throughs
  Input: spaceball - mark expected switch fall-throughs
  Input: uinput - unlock on allocation failure in ioctl
  Input: add support for the Samsung S6SY761 touchscreen
  Input: add support for HiDeep touchscreen
  Input: st1232 - remove obsolete platform device support
  Input: convert autorepeat timer to use timer_setup()
  media: ttpci: remove autorepeat handling and use timer_setup
  Input: cyttsp4 - avoid overflows when calculating memory sizes
  Input: mxs-lradc - remove redundant assignment to pointer input
  Input: add I2C attached EETI EXC3000 multi touch driver
  Input: goodix - support gt1151 touchpanel
  Input: ps2-gpio - actually abort probe when connected to sleeping GPIOs
  Input: hil_mlc - convert to using timer_setup()
  Input: hp_sdc - convert to using timer_setup()
  Input: touchsceen - convert timers to use timer_setup()
  Input: keyboard - convert timers to use timer_setup()
  Input: uinput - fold header into the driver proper
  Input: uinput - remove uinput_allocate_device()
  ...
parents 4e4510fe c2514106
Device-Tree bindings for GPIO attached mice
This simply uses standard GPIO handles to define a simple mouse connected
to 5-7 GPIO lines.
Required properties:
- compatible: must be "gpio-mouse"
- scan-interval-ms: The scanning interval in milliseconds
- up-gpios: GPIO line phandle to the line indicating "up"
- down-gpios: GPIO line phandle to the line indicating "down"
- left-gpios: GPIO line phandle to the line indicating "left"
- right-gpios: GPIO line phandle to the line indicating "right"
Optional properties:
- button-left-gpios: GPIO line handle to the left mouse button
- button-middle-gpios: GPIO line handle to the middle mouse button
- button-right-gpios: GPIO line handle to the right mouse button
Example:
#include <dt-bindings/gpio/gpio.h>
gpio-mouse {
compatible = "gpio-mouse";
scan-interval-ms = <50>;
up-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
down-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
left-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
right-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
button-left-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
button-middle-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
button-right-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
* EETI EXC3000 Multiple Touch Controller
Required properties:
- compatible: must be "eeti,exc3000"
- reg: i2c slave address
- interrupt-parent: the phandle for the interrupt controller
- interrupts: touch controller interrupt
- touchscreen-size-x: See touchscreen.txt
- touchscreen-size-y: See touchscreen.txt
Optional properties:
- touchscreen-inverted-x: See touchscreen.txt
- touchscreen-inverted-y: See touchscreen.txt
- touchscreen-swapped-x-y: See touchscreen.txt
Example:
touchscreen@2a {
compatible = "eeti,exc3000";
reg = <0x2a>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
touchscreen-size-x = <4096>;
touchscreen-size-y = <4096>;
touchscreen-inverted-x;
touchscreen-swapped-x-y;
};
...@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller ...@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
Required properties: Required properties:
- compatible : Should be "goodix,gt911" - compatible : Should be "goodix,gt1151"
or "goodix,gt911"
or "goodix,gt9110" or "goodix,gt9110"
or "goodix,gt912" or "goodix,gt912"
or "goodix,gt927" or "goodix,gt927"
......
* HiDeep Finger and Stylus touchscreen controller
Required properties:
- compatible : must be "hideep,hideep-ts"
- reg : I2C slave address, (e.g. 0x6C).
- interrupt-parent : Interrupt controller to which the chip is connected.
- interrupts : Interrupt to which the chip is connected.
Optional properties:
- vdd-supply : It is the controller supply for controlling
main voltage(3.3V) through the regulator.
- vid-supply : It is the controller supply for controlling
IO voltage(1.8V) through the regulator.
- reset-gpios : Define for reset gpio pin.
It is to use for reset IC.
- touchscreen-size-x : X axis size of touchscreen
- touchscreen-size-y : Y axis size of touchscreen
- linux,keycodes : Specifies an array of numeric keycode values to
be used for reporting button presses. The array can
contain up to 3 entries.
Example:
#include "dt-bindings/input/input.h"
i2c@00000000 {
/* ... */
touchscreen@6c {
compatible = "hideep,hideep-ts";
reg = <0x6c>;
interrupt-parent = <&gpx1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&ldo15_reg>";
vid-supply = <&ldo18_reg>;
reset-gpios = <&gpx1 5 0>;
touchscreen-size-x = <1080>;
touchscreen-size-y = <1920>;
linux,keycodes = <KEY_HOME>, <KEY_MENU>, <KEY_BACK>;
};
};
* Samsung S6SY761 touchscreen controller
Required properties:
- compatible : must be "samsung,s6sy761"
- reg : I2C slave address, (e.g. 0x48)
- interrupt-parent : the phandle to the interrupt controller which provides
the interrupt
- interrupts : interrupt specification
- avdd-supply : analogic power supply
- vdd-supply : power supply
Optional properties:
- touchscreen-size-x : see touchscreen.txt. This property is embedded in the
device. If defined it forces a different x resolution.
- touchscreen-size-y : see touchscreen.txt. This property is embedded in the
device. If defined it forces a different y resolution.
Example:
i2c@00000000 {
/* ... */
touchscreen@48 {
compatible = "samsung,s6sy761";
reg = <0x48>;
interrupt-parent = <&gpa1>;
interrupts = <1 IRQ_TYPE_NONE>;
avdd-supply = <&ldo30_reg>;
vdd-supply = <&ldo31_reg>;
touchscreen-size-x = <4096>;
touchscreen-size-y = <4096>;
};
};
...@@ -137,6 +137,7 @@ gw Gateworks Corporation ...@@ -137,6 +137,7 @@ gw Gateworks Corporation
hannstar HannStar Display Corporation hannstar HannStar Display Corporation
haoyu Haoyu Microelectronic Co. Ltd. haoyu Haoyu Microelectronic Co. Ltd.
hardkernel Hardkernel Co., Ltd hardkernel Hardkernel Co., Ltd
hideep HiDeep Inc.
himax Himax Technologies, Inc. himax Himax Technologies, Inc.
hisilicon Hisilicon Limited. hisilicon Hisilicon Limited.
hit Hitachi Ltd. hit Hitachi Ltd.
......
...@@ -412,10 +412,10 @@ static void ml_play_effects(struct ml_device *ml) ...@@ -412,10 +412,10 @@ static void ml_play_effects(struct ml_device *ml)
ml_schedule_timer(ml); ml_schedule_timer(ml);
} }
static void ml_effect_timer(unsigned long timer_data) static void ml_effect_timer(struct timer_list *t)
{ {
struct input_dev *dev = (struct input_dev *)timer_data; struct ml_device *ml = from_timer(ml, t, timer);
struct ml_device *ml = dev->ff->private; struct input_dev *dev = ml->dev;
unsigned long flags; unsigned long flags;
pr_debug("timer: updating effects\n"); pr_debug("timer: updating effects\n");
...@@ -526,7 +526,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data, ...@@ -526,7 +526,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
ml->private = data; ml->private = data;
ml->play_effect = play_effect; ml->play_effect = play_effect;
ml->gain = 0xffff; ml->gain = 0xffff;
setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev); timer_setup(&ml->timer, ml_effect_timer, 0);
set_bit(FF_GAIN, dev->ffbit); set_bit(FF_GAIN, dev->ffbit);
......
...@@ -76,7 +76,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code) ...@@ -76,7 +76,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code)
{ {
if (test_bit(EV_REP, dev->evbit) && if (test_bit(EV_REP, dev->evbit) &&
dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
dev->timer.data) { dev->timer.function) {
dev->repeat_key = code; dev->repeat_key = code;
mod_timer(&dev->timer, mod_timer(&dev->timer,
jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
...@@ -179,9 +179,9 @@ static void input_pass_event(struct input_dev *dev, ...@@ -179,9 +179,9 @@ static void input_pass_event(struct input_dev *dev,
* dev->event_lock here to avoid racing with input_event * dev->event_lock here to avoid racing with input_event
* which may cause keys get "stuck". * which may cause keys get "stuck".
*/ */
static void input_repeat_key(unsigned long data) static void input_repeat_key(struct timer_list *t)
{ {
struct input_dev *dev = (void *) data; struct input_dev *dev = from_timer(dev, t, timer);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
...@@ -1784,7 +1784,7 @@ struct input_dev *input_allocate_device(void) ...@@ -1784,7 +1784,7 @@ struct input_dev *input_allocate_device(void)
device_initialize(&dev->dev); device_initialize(&dev->dev);
mutex_init(&dev->mutex); mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock); spin_lock_init(&dev->event_lock);
init_timer(&dev->timer); timer_setup(&dev->timer, NULL, 0);
INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node); INIT_LIST_HEAD(&dev->node);
...@@ -2047,8 +2047,7 @@ static void devm_input_device_unregister(struct device *dev, void *res) ...@@ -2047,8 +2047,7 @@ static void devm_input_device_unregister(struct device *dev, void *res)
*/ */
void input_enable_softrepeat(struct input_dev *dev, int delay, int period) void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
{ {
dev->timer.data = (unsigned long) dev; dev->timer.function = (TIMER_FUNC_TYPE)input_repeat_key;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = delay; dev->rep[REP_DELAY] = delay;
dev->rep[REP_PERIOD] = period; dev->rep[REP_PERIOD] = period;
} }
......
...@@ -654,6 +654,7 @@ static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, ...@@ -654,6 +654,7 @@ static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type,
input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04);
input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02);
/* fall through */
case GC_PSX_NEGCON: case GC_PSX_NEGCON:
case GC_PSX_ANALOG: case GC_PSX_ANALOG:
...@@ -887,6 +888,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -887,6 +888,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
case GC_SNES: case GC_SNES:
for (i = 4; i < 8; i++) for (i = 4; i < 8; i++)
__set_bit(gc_snes_btn[i], input_dev->keybit); __set_bit(gc_snes_btn[i], input_dev->keybit);
/* fall through */
case GC_NES: case GC_NES:
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
__set_bit(gc_snes_btn[i], input_dev->keybit); __set_bit(gc_snes_btn[i], input_dev->keybit);
...@@ -894,6 +896,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -894,6 +896,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
case GC_MULTI2: case GC_MULTI2:
__set_bit(BTN_THUMB, input_dev->keybit); __set_bit(BTN_THUMB, input_dev->keybit);
/* fall through */
case GC_MULTI: case GC_MULTI:
__set_bit(BTN_TRIGGER, input_dev->keybit); __set_bit(BTN_TRIGGER, input_dev->keybit);
break; break;
......
...@@ -672,16 +672,16 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -672,16 +672,16 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
switch (i * m) { switch (i * m) {
case 60: case 60:
sw->number++; sw->number++; /* fall through */
case 45: /* Ambiguous packet length */ case 45: /* Ambiguous packet length */
if (j <= 40) { /* ID length less or eq 40 -> FSP */ if (j <= 40) { /* ID length less or eq 40 -> FSP */
case 43: case 43:
sw->type = SW_ID_FSP; sw->type = SW_ID_FSP;
break; break;
} }
sw->number++; sw->number++; /* fall through */
case 30: case 30:
sw->number++; sw->number++; /* fall through */
case 15: case 15:
sw->type = SW_ID_GP; sw->type = SW_ID_GP;
break; break;
...@@ -697,9 +697,9 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -697,9 +697,9 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sw->type = SW_ID_PP; sw->type = SW_ID_PP;
break; break;
case 66: case 66:
sw->bits = 3; sw->bits = 3; /* fall through */
case 198: case 198:
sw->length = 22; sw->length = 22; /* fall through */
case 64: case 64:
sw->type = SW_ID_3DP; sw->type = SW_ID_3DP;
if (j == 160) if (j == 160)
......
...@@ -162,6 +162,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, ...@@ -162,6 +162,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio,
break; break;
} }
spaceball->escape = 0; spaceball->escape = 0;
/* fall through */
case 'M': case 'M':
case 'Q': case 'Q':
case 'S': case 'S':
...@@ -169,6 +170,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, ...@@ -169,6 +170,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio,
spaceball->escape = 0; spaceball->escape = 0;
data &= 0x1f; data &= 0x1f;
} }
/* fall through */
default: default:
if (spaceball->escape) if (spaceball->escape)
spaceball->escape = 0; spaceball->escape = 0;
...@@ -234,11 +236,13 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) ...@@ -234,11 +236,13 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) | input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) |
BIT_MASK(BTN_B) | BIT_MASK(BTN_C) | BIT_MASK(BTN_B) | BIT_MASK(BTN_C) |
BIT_MASK(BTN_MODE); BIT_MASK(BTN_MODE);
/* fall through */
default: default:
input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) | input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) |
BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_3) | BIT_MASK(BTN_4) |
BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) |
BIT_MASK(BTN_7) | BIT_MASK(BTN_8); BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
/* fall through */
case SPACEBALL_3003C: case SPACEBALL_3003C:
input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) | input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) |
BIT_MASK(BTN_8); BIT_MASK(BTN_8);
......
...@@ -127,10 +127,9 @@ static inline void bfin_kpad_clear_irq(void) ...@@ -127,10 +127,9 @@ static inline void bfin_kpad_clear_irq(void)
bfin_write_KPAD_ROWCOL(0xFFFF); bfin_write_KPAD_ROWCOL(0xFFFF);
} }
static void bfin_kpad_timer(unsigned long data) static void bfin_kpad_timer(struct timer_list *t)
{ {
struct platform_device *pdev = (struct platform_device *) data; struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer);
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
if (bfin_kpad_get_keypressed(bf54x_kpad)) { if (bfin_kpad_get_keypressed(bf54x_kpad)) {
/* Try again later */ /* Try again later */
...@@ -298,7 +297,7 @@ static int bfin_kpad_probe(struct platform_device *pdev) ...@@ -298,7 +297,7 @@ static int bfin_kpad_probe(struct platform_device *pdev)
/* Init Keypad Key Up/Release test timer */ /* Init Keypad Key Up/Release test timer */
setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0);
bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE));
......
...@@ -419,9 +419,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) ...@@ -419,9 +419,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void gpio_keys_irq_timer(unsigned long _data) static void gpio_keys_irq_timer(struct timer_list *t)
{ {
struct gpio_button_data *bdata = (struct gpio_button_data *)_data; struct gpio_button_data *bdata = from_timer(bdata, t, release_timer);
struct input_dev *input = bdata->input; struct input_dev *input = bdata->input;
unsigned long flags; unsigned long flags;
...@@ -582,8 +582,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -582,8 +582,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
} }
bdata->release_delay = button->debounce_interval; bdata->release_delay = button->debounce_interval;
setup_timer(&bdata->release_timer, timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0);
gpio_keys_irq_timer, (unsigned long)bdata);
isr = gpio_keys_irq_isr; isr = gpio_keys_irq_isr;
irqflags = 0; irqflags = 0;
......
...@@ -184,9 +184,9 @@ static void imx_keypad_fire_events(struct imx_keypad *keypad, ...@@ -184,9 +184,9 @@ static void imx_keypad_fire_events(struct imx_keypad *keypad,
/* /*
* imx_keypad_check_for_events is the timer handler. * imx_keypad_check_for_events is the timer handler.
*/ */
static void imx_keypad_check_for_events(unsigned long data) static void imx_keypad_check_for_events(struct timer_list *t)
{ {
struct imx_keypad *keypad = (struct imx_keypad *) data; struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer);
unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS]; unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
unsigned short reg_val; unsigned short reg_val;
bool state_changed, is_zero_matrix; bool state_changed, is_zero_matrix;
...@@ -456,8 +456,8 @@ static int imx_keypad_probe(struct platform_device *pdev) ...@@ -456,8 +456,8 @@ static int imx_keypad_probe(struct platform_device *pdev)
keypad->irq = irq; keypad->irq = irq;
keypad->stable_count = 0; keypad->stable_count = 0;
setup_timer(&keypad->check_matrix_timer, timer_setup(&keypad->check_matrix_timer,
imx_keypad_check_for_events, (unsigned long) keypad); imx_keypad_check_for_events, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res); keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
......
...@@ -210,9 +210,9 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) ...@@ -210,9 +210,9 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
/* /*
* LoCoMo timer checking for released keys * LoCoMo timer checking for released keys
*/ */
static void locomokbd_timer_callback(unsigned long data) static void locomokbd_timer_callback(struct timer_list *t)
{ {
struct locomokbd *locomokbd = (struct locomokbd *) data; struct locomokbd *locomokbd = from_timer(locomokbd, t, timer);
locomokbd_scankeyboard(locomokbd); locomokbd_scankeyboard(locomokbd);
} }
...@@ -264,8 +264,7 @@ static int locomokbd_probe(struct locomo_dev *dev) ...@@ -264,8 +264,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
spin_lock_init(&locomokbd->lock); spin_lock_init(&locomokbd->lock);
setup_timer(&locomokbd->timer, locomokbd_timer_callback, timer_setup(&locomokbd->timer, locomokbd_timer_callback, 0);
(unsigned long)locomokbd);
locomokbd->suspend_jiffies = jiffies; locomokbd->suspend_jiffies = jiffies;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#undef NEW_BOARD_LEARNING_MODE #undef NEW_BOARD_LEARNING_MODE
static void omap_kp_tasklet(unsigned long); static void omap_kp_tasklet(unsigned long);
static void omap_kp_timer(unsigned long); static void omap_kp_timer(struct timer_list *);
static unsigned char keypad_state[8]; static unsigned char keypad_state[8];
static DEFINE_MUTEX(kp_enable_mutex); static DEFINE_MUTEX(kp_enable_mutex);
...@@ -74,7 +74,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) ...@@ -74,7 +74,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void omap_kp_timer(unsigned long data) static void omap_kp_timer(struct timer_list *unused)
{ {
tasklet_schedule(&kp_tasklet); tasklet_schedule(&kp_tasklet);
} }
...@@ -233,7 +233,7 @@ static int omap_kp_probe(struct platform_device *pdev) ...@@ -233,7 +233,7 @@ static int omap_kp_probe(struct platform_device *pdev)
col_idx = 0; col_idx = 0;
row_idx = 0; row_idx = 0;
setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp); timer_setup(&omap_kp->timer, omap_kp_timer, 0);
/* get the irq and init timer*/ /* get the irq and init timer*/
kp_tasklet.data = (unsigned long) omap_kp; kp_tasklet.data = (unsigned long) omap_kp;
......
...@@ -45,9 +45,9 @@ struct pwrkey_drv_data { ...@@ -45,9 +45,9 @@ struct pwrkey_drv_data {
struct input_dev *input; struct input_dev *input;
}; };
static void imx_imx_snvs_check_for_events(unsigned long data) static void imx_imx_snvs_check_for_events(struct timer_list *t)
{ {
struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data; struct pwrkey_drv_data *pdata = from_timer(pdata, t, check_timer);
struct input_dev *input = pdata->input; struct input_dev *input = pdata->input;
u32 state; u32 state;
...@@ -134,8 +134,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) ...@@ -134,8 +134,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
/* clear the unexpected interrupt before driver ready */ /* clear the unexpected interrupt before driver ready */
regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
setup_timer(&pdata->check_timer, timer_setup(&pdata->check_timer, imx_imx_snvs_check_for_events, 0);
imx_imx_snvs_check_for_events, (unsigned long) pdata);
input = devm_input_allocate_device(&pdev->dev); input = devm_input_allocate_device(&pdev->dev);
if (!input) { if (!input) {
......
...@@ -251,9 +251,9 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) ...@@ -251,9 +251,9 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
writel(val, kbc->mmio + KBC_CONTROL_0); writel(val, kbc->mmio + KBC_CONTROL_0);
} }
static void tegra_kbc_keypress_timer(unsigned long data) static void tegra_kbc_keypress_timer(struct timer_list *t)
{ {
struct tegra_kbc *kbc = (struct tegra_kbc *)data; struct tegra_kbc *kbc = from_timer(kbc, t, timer);
unsigned long flags; unsigned long flags;
u32 val; u32 val;
unsigned int i; unsigned int i;
...@@ -655,7 +655,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) ...@@ -655,7 +655,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); timer_setup(&kbc->timer, tegra_kbc_keypress_timer, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
kbc->mmio = devm_ioremap_resource(&pdev->dev, res); kbc->mmio = devm_ioremap_resource(&pdev->dev, res);
......
...@@ -796,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ...@@ -796,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
if (pdata->watermark) { if (pdata->watermark) {
ac->int_mask |= WATERMARK; ac->int_mask |= WATERMARK;
if (!FIFO_MODE(pdata->fifo_mode)) if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS)
ac->pdata.fifo_mode |= FIFO_STREAM; ac->pdata.fifo_mode |= FIFO_STREAM;
} else { } else {
ac->int_mask |= DATA_READY; ac->int_mask |= DATA_READY;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
* 0.1 20/06/2002 * 0.1 20/06/2002
* - first public version * - first public version
*/ */
#include <uapi/linux/uinput.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -38,10 +39,47 @@ ...@@ -38,10 +39,47 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/uinput.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include "../input-compat.h" #include "../input-compat.h"
#define UINPUT_NAME "uinput"
#define UINPUT_BUFFER_SIZE 16
#define UINPUT_NUM_REQUESTS 16
enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
struct uinput_request {
unsigned int id;
unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
int retval;
struct completion done;
union {
unsigned int effect_id;
struct {
struct ff_effect *effect;
struct ff_effect *old;
} upload;
} u;
};
struct uinput_device {
struct input_dev *dev;
struct mutex mutex;
enum uinput_state state;
wait_queue_head_t waitq;
unsigned char ready;
unsigned char head;
unsigned char tail;
struct input_event buff[UINPUT_BUFFER_SIZE];
unsigned int ff_effects_max;
struct uinput_request *requests[UINPUT_NUM_REQUESTS];
wait_queue_head_t requests_waitq;
spinlock_t requests_lock;
};
static int uinput_dev_event(struct input_dev *dev, static int uinput_dev_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
...@@ -149,7 +187,11 @@ static int uinput_request_submit(struct uinput_device *udev, ...@@ -149,7 +187,11 @@ static int uinput_request_submit(struct uinput_device *udev,
if (retval) if (retval)
goto out; goto out;
wait_for_completion(&request->done); if (!wait_for_completion_timeout(&request->done, 30 * HZ)) {
retval = -ETIMEDOUT;
goto out;
}
retval = request->retval; retval = request->retval;
out: out:
...@@ -320,6 +362,10 @@ static int uinput_create_device(struct uinput_device *udev) ...@@ -320,6 +362,10 @@ static int uinput_create_device(struct uinput_device *udev)
dev->flush = uinput_dev_flush; dev->flush = uinput_dev_flush;
} }
dev->event = uinput_dev_event;
input_set_drvdata(udev->dev, udev);
error = input_register_device(udev->dev); error = input_register_device(udev->dev);
if (error) if (error)
goto fail2; goto fail2;
...@@ -402,18 +448,6 @@ static int uinput_validate_absbits(struct input_dev *dev) ...@@ -402,18 +448,6 @@ static int uinput_validate_absbits(struct input_dev *dev)
return 0; return 0;
} }
static int uinput_allocate_device(struct uinput_device *udev)
{
udev->dev = input_allocate_device();
if (!udev->dev)
return -ENOMEM;
udev->dev->event = uinput_dev_event;
input_set_drvdata(udev->dev, udev);
return 0;
}
static int uinput_dev_setup(struct uinput_device *udev, static int uinput_dev_setup(struct uinput_device *udev,
struct uinput_setup __user *arg) struct uinput_setup __user *arg)
{ {
...@@ -489,9 +523,9 @@ static int uinput_setup_device_legacy(struct uinput_device *udev, ...@@ -489,9 +523,9 @@ static int uinput_setup_device_legacy(struct uinput_device *udev,
return -EINVAL; return -EINVAL;
if (!udev->dev) { if (!udev->dev) {
retval = uinput_allocate_device(udev); udev->dev = input_allocate_device();
if (retval) if (!udev->dev)
return retval; return -ENOMEM;
} }
dev = udev->dev; dev = udev->dev;
...@@ -822,162 +856,163 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, ...@@ -822,162 +856,163 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
return retval; return retval;
if (!udev->dev) { if (!udev->dev) {
retval = uinput_allocate_device(udev); udev->dev = input_allocate_device();
if (retval) if (!udev->dev) {
retval = -ENOMEM;
goto out; goto out;
}
} }
switch (cmd) { switch (cmd) {
case UI_GET_VERSION: case UI_GET_VERSION:
if (put_user(UINPUT_VERSION, if (put_user(UINPUT_VERSION, (unsigned int __user *)p))
(unsigned int __user *)p)) retval = -EFAULT;
retval = -EFAULT; goto out;
goto out;
case UI_DEV_CREATE: case UI_DEV_CREATE:
retval = uinput_create_device(udev); retval = uinput_create_device(udev);
goto out; goto out;
case UI_DEV_DESTROY: case UI_DEV_DESTROY:
uinput_destroy_device(udev); uinput_destroy_device(udev);
goto out; goto out;
case UI_DEV_SETUP: case UI_DEV_SETUP:
retval = uinput_dev_setup(udev, p); retval = uinput_dev_setup(udev, p);
goto out; goto out;
/* UI_ABS_SETUP is handled in the variable size ioctls */ /* UI_ABS_SETUP is handled in the variable size ioctls */
case UI_SET_EVBIT: case UI_SET_EVBIT:
retval = uinput_set_bit(arg, evbit, EV_MAX); retval = uinput_set_bit(arg, evbit, EV_MAX);
goto out; goto out;
case UI_SET_KEYBIT: case UI_SET_KEYBIT:
retval = uinput_set_bit(arg, keybit, KEY_MAX); retval = uinput_set_bit(arg, keybit, KEY_MAX);
goto out; goto out;
case UI_SET_RELBIT: case UI_SET_RELBIT:
retval = uinput_set_bit(arg, relbit, REL_MAX); retval = uinput_set_bit(arg, relbit, REL_MAX);
goto out; goto out;
case UI_SET_ABSBIT: case UI_SET_ABSBIT:
retval = uinput_set_bit(arg, absbit, ABS_MAX); retval = uinput_set_bit(arg, absbit, ABS_MAX);
goto out; goto out;
case UI_SET_MSCBIT: case UI_SET_MSCBIT:
retval = uinput_set_bit(arg, mscbit, MSC_MAX); retval = uinput_set_bit(arg, mscbit, MSC_MAX);
goto out; goto out;
case UI_SET_LEDBIT: case UI_SET_LEDBIT:
retval = uinput_set_bit(arg, ledbit, LED_MAX); retval = uinput_set_bit(arg, ledbit, LED_MAX);
goto out; goto out;
case UI_SET_SNDBIT:
retval = uinput_set_bit(arg, sndbit, SND_MAX);
goto out;
case UI_SET_SNDBIT: case UI_SET_FFBIT:
retval = uinput_set_bit(arg, sndbit, SND_MAX); retval = uinput_set_bit(arg, ffbit, FF_MAX);
goto out;
case UI_SET_SWBIT:
retval = uinput_set_bit(arg, swbit, SW_MAX);
goto out;
case UI_SET_PROPBIT:
retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
goto out;
case UI_SET_PHYS:
if (udev->state == UIST_CREATED) {
retval = -EINVAL;
goto out; goto out;
}
case UI_SET_FFBIT: phys = strndup_user(p, 1024);
retval = uinput_set_bit(arg, ffbit, FF_MAX); if (IS_ERR(phys)) {
retval = PTR_ERR(phys);
goto out; goto out;
}
kfree(udev->dev->phys);
udev->dev->phys = phys;
goto out;
case UI_SET_SWBIT: case UI_BEGIN_FF_UPLOAD:
retval = uinput_set_bit(arg, swbit, SW_MAX); retval = uinput_ff_upload_from_user(p, &ff_up);
if (retval)
goto out; goto out;
case UI_SET_PROPBIT: req = uinput_request_find(udev, ff_up.request_id);
retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); if (!req || req->code != UI_FF_UPLOAD ||
!req->u.upload.effect) {
retval = -EINVAL;
goto out; goto out;
}
case UI_SET_PHYS: ff_up.retval = 0;
if (udev->state == UIST_CREATED) { ff_up.effect = *req->u.upload.effect;
retval = -EINVAL; if (req->u.upload.old)
goto out; ff_up.old = *req->u.upload.old;
} else
memset(&ff_up.old, 0, sizeof(struct ff_effect));
phys = strndup_user(p, 1024); retval = uinput_ff_upload_to_user(p, &ff_up);
if (IS_ERR(phys)) { goto out;
retval = PTR_ERR(phys);
goto out;
}
kfree(udev->dev->phys); case UI_BEGIN_FF_ERASE:
udev->dev->phys = phys; if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
retval = -EFAULT;
goto out; goto out;
}
case UI_BEGIN_FF_UPLOAD: req = uinput_request_find(udev, ff_erase.request_id);
retval = uinput_ff_upload_from_user(p, &ff_up); if (!req || req->code != UI_FF_ERASE) {
if (retval) retval = -EINVAL;
goto out;
req = uinput_request_find(udev, ff_up.request_id);
if (!req || req->code != UI_FF_UPLOAD ||
!req->u.upload.effect) {
retval = -EINVAL;
goto out;
}
ff_up.retval = 0;
ff_up.effect = *req->u.upload.effect;
if (req->u.upload.old)
ff_up.old = *req->u.upload.old;
else
memset(&ff_up.old, 0, sizeof(struct ff_effect));
retval = uinput_ff_upload_to_user(p, &ff_up);
goto out; goto out;
}
case UI_BEGIN_FF_ERASE: ff_erase.retval = 0;
if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { ff_erase.effect_id = req->u.effect_id;
retval = -EFAULT; if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
goto out; retval = -EFAULT;
}
req = uinput_request_find(udev, ff_erase.request_id);
if (!req || req->code != UI_FF_ERASE) {
retval = -EINVAL;
goto out;
}
ff_erase.retval = 0;
ff_erase.effect_id = req->u.effect_id;
if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
retval = -EFAULT;
goto out;
}
goto out; goto out;
}
case UI_END_FF_UPLOAD: goto out;
retval = uinput_ff_upload_from_user(p, &ff_up);
if (retval)
goto out;
req = uinput_request_find(udev, ff_up.request_id); case UI_END_FF_UPLOAD:
if (!req || req->code != UI_FF_UPLOAD || retval = uinput_ff_upload_from_user(p, &ff_up);
!req->u.upload.effect) { if (retval)
retval = -EINVAL; goto out;
goto out;
}
req->retval = ff_up.retval; req = uinput_request_find(udev, ff_up.request_id);
complete(&req->done); if (!req || req->code != UI_FF_UPLOAD ||
!req->u.upload.effect) {
retval = -EINVAL;
goto out; goto out;
}
case UI_END_FF_ERASE: req->retval = ff_up.retval;
if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { complete(&req->done);
retval = -EFAULT; goto out;
goto out;
}
req = uinput_request_find(udev, ff_erase.request_id); case UI_END_FF_ERASE:
if (!req || req->code != UI_FF_ERASE) { if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
retval = -EINVAL; retval = -EFAULT;
goto out; goto out;
} }
req->retval = ff_erase.retval; req = uinput_request_find(udev, ff_erase.request_id);
complete(&req->done); if (!req || req->code != UI_FF_ERASE) {
retval = -EINVAL;
goto out; goto out;
}
req->retval = ff_erase.retval;
complete(&req->done);
goto out;
} }
size = _IOC_SIZE(cmd); size = _IOC_SIZE(cmd);
......
...@@ -1587,10 +1587,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) ...@@ -1587,10 +1587,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
return PSMOUSE_GOOD_DATA; return PSMOUSE_GOOD_DATA;
} }
static void alps_flush_packet(unsigned long data) static void alps_flush_packet(struct timer_list *t)
{ {
struct psmouse *psmouse = (struct psmouse *)data; struct alps_data *priv = from_timer(priv, t, timer);
struct alps_data *priv = psmouse->private; struct psmouse *psmouse = priv->psmouse;
serio_pause_rx(psmouse->ps2dev.serio); serio_pause_rx(psmouse->ps2dev.serio);
...@@ -2702,7 +2702,7 @@ static int alps_set_protocol(struct psmouse *psmouse, ...@@ -2702,7 +2702,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
{ {
psmouse->private = priv; psmouse->private = priv;
setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); timer_setup(&priv->timer, alps_flush_packet, 0);
priv->proto_version = protocol->version; priv->proto_version = protocol->version;
priv->byte0 = protocol->byte0; priv->byte0 = protocol->byte0;
......
...@@ -227,6 +227,7 @@ ...@@ -227,6 +227,7 @@
struct byd_data { struct byd_data {
struct timer_list timer; struct timer_list timer;
struct psmouse *psmouse;
s32 abs_x; s32 abs_x;
s32 abs_y; s32 abs_y;
typeof(jiffies) last_touch_time; typeof(jiffies) last_touch_time;
...@@ -251,10 +252,10 @@ static void byd_report_input(struct psmouse *psmouse) ...@@ -251,10 +252,10 @@ static void byd_report_input(struct psmouse *psmouse)
input_sync(dev); input_sync(dev);
} }
static void byd_clear_touch(unsigned long data) static void byd_clear_touch(struct timer_list *t)
{ {
struct psmouse *psmouse = (struct psmouse *)data; struct byd_data *priv = from_timer(priv, t, timer);
struct byd_data *priv = psmouse->private; struct psmouse *psmouse = priv->psmouse;
serio_pause_rx(psmouse->ps2dev.serio); serio_pause_rx(psmouse->ps2dev.serio);
priv->touch = false; priv->touch = false;
...@@ -478,7 +479,8 @@ int byd_init(struct psmouse *psmouse) ...@@ -478,7 +479,8 @@ int byd_init(struct psmouse *psmouse)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
setup_timer(&priv->timer, byd_clear_touch, (unsigned long) psmouse); priv->psmouse = psmouse;
timer_setup(&priv->timer, byd_clear_touch, 0);
psmouse->private = priv; psmouse->private = priv;
psmouse->disconnect = byd_disconnect; psmouse->disconnect = byd_disconnect;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -1141,10 +1142,13 @@ static int elan_probe(struct i2c_client *client, ...@@ -1141,10 +1142,13 @@ static int elan_probe(struct i2c_client *client,
return error; return error;
/* /*
* Systems using device tree should set up interrupt via DTS, * Platform code (ACPI, DTS) should normally set up interrupt
* the rest will use the default falling edge interrupts. * for us, but in case it did not let's fall back to using falling
* edge to be compatible with older Chromebooks.
*/ */
irqflags = dev->of_node ? 0 : IRQF_TRIGGER_FALLING; irqflags = irq_get_trigger_type(client->irq);
if (!irqflags)
irqflags = IRQF_TRIGGER_FALLING;
error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr, error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr,
irqflags | IRQF_ONESHOT, irqflags | IRQF_ONESHOT,
...@@ -1255,7 +1259,6 @@ static const struct acpi_device_id elan_acpi_id[] = { ...@@ -1255,7 +1259,6 @@ static const struct acpi_device_id elan_acpi_id[] = {
{ "ELAN0602", 0 }, { "ELAN0602", 0 },
{ "ELAN0605", 0 }, { "ELAN0605", 0 },
{ "ELAN0608", 0 }, { "ELAN0608", 0 },
{ "ELAN0605", 0 },
{ "ELAN0609", 0 }, { "ELAN0609", 0 },
{ "ELAN060B", 0 }, { "ELAN060B", 0 },
{ "ELAN060C", 0 }, { "ELAN060C", 0 },
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Driver for simulating a mouse on GPIO lines. * Driver for simulating a mouse on GPIO lines.
* *
* Copyright (C) 2007 Atmel Corporation * Copyright (C) 2007 Atmel Corporation
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
* *
* 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
...@@ -11,9 +12,35 @@ ...@@ -11,9 +12,35 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input-polldev.h> #include <linux/input-polldev.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/gpio_mouse.h> #include <linux/property.h>
#include <linux/of.h>
/**
* struct gpio_mouse
* @scan_ms: the scan interval in milliseconds.
* @up: GPIO line for up value.
* @down: GPIO line for down value.
* @left: GPIO line for left value.
* @right: GPIO line for right value.
* @bleft: GPIO line for left button.
* @bmiddle: GPIO line for middle button.
* @bright: GPIO line for right button.
*
* This struct must be added to the platform_device in the board code.
* It is used by the gpio_mouse driver to setup GPIO lines and to
* calculate mouse movement.
*/
struct gpio_mouse {
u32 scan_ms;
struct gpio_desc *up;
struct gpio_desc *down;
struct gpio_desc *left;
struct gpio_desc *right;
struct gpio_desc *bleft;
struct gpio_desc *bmiddle;
struct gpio_desc *bright;
};
/* /*
* Timer function which is run every scan_ms ms when the device is opened. * Timer function which is run every scan_ms ms when the device is opened.
...@@ -21,24 +48,22 @@ ...@@ -21,24 +48,22 @@
*/ */
static void gpio_mouse_scan(struct input_polled_dev *dev) static void gpio_mouse_scan(struct input_polled_dev *dev)
{ {
struct gpio_mouse_platform_data *gpio = dev->private; struct gpio_mouse *gpio = dev->private;
struct input_dev *input = dev->input; struct input_dev *input = dev->input;
int x, y; int x, y;
if (gpio->bleft >= 0) if (gpio->bleft)
input_report_key(input, BTN_LEFT, input_report_key(input, BTN_LEFT,
gpio_get_value(gpio->bleft) ^ gpio->polarity); gpiod_get_value(gpio->bleft));
if (gpio->bmiddle >= 0) if (gpio->bmiddle)
input_report_key(input, BTN_MIDDLE, input_report_key(input, BTN_MIDDLE,
gpio_get_value(gpio->bmiddle) ^ gpio->polarity); gpiod_get_value(gpio->bmiddle));
if (gpio->bright >= 0) if (gpio->bright)
input_report_key(input, BTN_RIGHT, input_report_key(input, BTN_RIGHT,
gpio_get_value(gpio->bright) ^ gpio->polarity); gpiod_get_value(gpio->bright));
x = (gpio_get_value(gpio->right) ^ gpio->polarity) x = gpiod_get_value(gpio->right) - gpiod_get_value(gpio->left);
- (gpio_get_value(gpio->left) ^ gpio->polarity); y = gpiod_get_value(gpio->down) - gpiod_get_value(gpio->up);
y = (gpio_get_value(gpio->down) ^ gpio->polarity)
- (gpio_get_value(gpio->up) ^ gpio->polarity);
input_report_rel(input, REL_X, x); input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y); input_report_rel(input, REL_Y, y);
...@@ -47,65 +72,61 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) ...@@ -47,65 +72,61 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
static int gpio_mouse_probe(struct platform_device *pdev) static int gpio_mouse_probe(struct platform_device *pdev)
{ {
struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev;
struct gpio_mouse *gmouse;
struct input_polled_dev *input_poll; struct input_polled_dev *input_poll;
struct input_dev *input; struct input_dev *input;
int pin, i; int ret;
int error;
gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
if (!pdata) { if (!gmouse)
dev_err(&pdev->dev, "no platform data\n"); return -ENOMEM;
error = -ENXIO;
goto out; /* Assign some default scanning time */
} ret = device_property_read_u32(dev, "scan-interval-ms",
&gmouse->scan_ms);
if (pdata->scan_ms < 0) { if (ret || gmouse->scan_ms == 0) {
dev_err(&pdev->dev, "invalid scan time\n"); dev_warn(dev, "invalid scan time, set to 50 ms\n");
error = -EINVAL; gmouse->scan_ms = 50;
goto out;
}
for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
pin = pdata->pins[i];
if (pin < 0) {
if (i <= GPIO_MOUSE_PIN_RIGHT) {
/* Mouse direction is required. */
dev_err(&pdev->dev,
"missing GPIO for directions\n");
error = -EINVAL;
goto out_free_gpios;
}
if (i == GPIO_MOUSE_PIN_BLEFT)
dev_dbg(&pdev->dev, "no left button defined\n");
} else {
error = gpio_request(pin, "gpio_mouse");
if (error) {
dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
pin, i);
goto out_free_gpios;
}
gpio_direction_input(pin);
}
} }
input_poll = input_allocate_polled_device(); gmouse->up = devm_gpiod_get(dev, "up", GPIOD_IN);
if (IS_ERR(gmouse->up))
return PTR_ERR(gmouse->up);
gmouse->down = devm_gpiod_get(dev, "down", GPIOD_IN);
if (IS_ERR(gmouse->down))
return PTR_ERR(gmouse->down);
gmouse->left = devm_gpiod_get(dev, "left", GPIOD_IN);
if (IS_ERR(gmouse->left))
return PTR_ERR(gmouse->left);
gmouse->right = devm_gpiod_get(dev, "right", GPIOD_IN);
if (IS_ERR(gmouse->right))
return PTR_ERR(gmouse->right);
gmouse->bleft = devm_gpiod_get_optional(dev, "button-left", GPIOD_IN);
if (IS_ERR(gmouse->bleft))
return PTR_ERR(gmouse->bleft);
gmouse->bmiddle = devm_gpiod_get_optional(dev, "button-middle",
GPIOD_IN);
if (IS_ERR(gmouse->bmiddle))
return PTR_ERR(gmouse->bmiddle);
gmouse->bright = devm_gpiod_get_optional(dev, "button-right",
GPIOD_IN);
if (IS_ERR(gmouse->bright))
return PTR_ERR(gmouse->bright);
input_poll = devm_input_allocate_polled_device(dev);
if (!input_poll) { if (!input_poll) {
dev_err(&pdev->dev, "not enough memory for input device\n"); dev_err(dev, "not enough memory for input device\n");
error = -ENOMEM; return -ENOMEM;
goto out_free_gpios;
} }
platform_set_drvdata(pdev, input_poll); platform_set_drvdata(pdev, input_poll);
/* set input-polldev handlers */ /* set input-polldev handlers */
input_poll->private = pdata; input_poll->private = gmouse;
input_poll->poll = gpio_mouse_scan; input_poll->poll = gpio_mouse_scan;
input_poll->poll_interval = pdata->scan_ms; input_poll->poll_interval = gmouse->scan_ms;
input = input_poll->input; input = input_poll->input;
input->name = pdev->name; input->name = pdev->name;
...@@ -114,63 +135,39 @@ static int gpio_mouse_probe(struct platform_device *pdev) ...@@ -114,63 +135,39 @@ static int gpio_mouse_probe(struct platform_device *pdev)
input_set_capability(input, EV_REL, REL_X); input_set_capability(input, EV_REL, REL_X);
input_set_capability(input, EV_REL, REL_Y); input_set_capability(input, EV_REL, REL_Y);
if (pdata->bleft >= 0) if (gmouse->bleft)
input_set_capability(input, EV_KEY, BTN_LEFT); input_set_capability(input, EV_KEY, BTN_LEFT);
if (pdata->bmiddle >= 0) if (gmouse->bmiddle)
input_set_capability(input, EV_KEY, BTN_MIDDLE); input_set_capability(input, EV_KEY, BTN_MIDDLE);
if (pdata->bright >= 0) if (gmouse->bright)
input_set_capability(input, EV_KEY, BTN_RIGHT); input_set_capability(input, EV_KEY, BTN_RIGHT);
error = input_register_polled_device(input_poll); ret = input_register_polled_device(input_poll);
if (error) { if (ret) {
dev_err(&pdev->dev, "could not register input device\n"); dev_err(dev, "could not register input device\n");
goto out_free_polldev; return ret;
} }
dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",
pdata->scan_ms, gmouse->scan_ms,
pdata->bleft < 0 ? "" : "left ", gmouse->bleft ? "" : "left ",
pdata->bmiddle < 0 ? "" : "middle ", gmouse->bmiddle ? "" : "middle ",
pdata->bright < 0 ? "" : "right"); gmouse->bright ? "" : "right");
return 0; return 0;
out_free_polldev:
input_free_polled_device(input_poll);
out_free_gpios:
while (--i >= 0) {
pin = pdata->pins[i];
if (pin)
gpio_free(pin);
}
out:
return error;
} }
static int gpio_mouse_remove(struct platform_device *pdev) static const struct of_device_id gpio_mouse_of_match[] = {
{ { .compatible = "gpio-mouse", },
struct input_polled_dev *input = platform_get_drvdata(pdev); { },
struct gpio_mouse_platform_data *pdata = input->private; };
int pin, i; MODULE_DEVICE_TABLE(of, gpio_mouse_of_match);
input_unregister_polled_device(input);
input_free_polled_device(input);
for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
pin = pdata->pins[i];
if (pin >= 0)
gpio_free(pin);
}
return 0;
}
static struct platform_driver gpio_mouse_device_driver = { static struct platform_driver gpio_mouse_device_driver = {
.probe = gpio_mouse_probe, .probe = gpio_mouse_probe,
.remove = gpio_mouse_remove,
.driver = { .driver = {
.name = "gpio_mouse", .name = "gpio_mouse",
.of_match_table = gpio_mouse_of_match,
} }
}; };
module_platform_driver(gpio_mouse_device_driver); module_platform_driver(gpio_mouse_device_driver);
...@@ -179,4 +176,3 @@ MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); ...@@ -179,4 +176,3 @@ 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 */
...@@ -73,7 +73,7 @@ enum rmi_f54_report_type { ...@@ -73,7 +73,7 @@ enum rmi_f54_report_type {
F54_MAX_REPORT_TYPE, F54_MAX_REPORT_TYPE,
}; };
const char *rmi_f54_report_type_names[] = { static const char * const rmi_f54_report_type_names[] = {
[F54_REPORT_NONE] = "Unknown", [F54_REPORT_NONE] = "Unknown",
[F54_8BIT_IMAGE] = "Normalized 8-Bit Image", [F54_8BIT_IMAGE] = "Normalized 8-Bit Image",
[F54_16BIT_IMAGE] = "Normalized 16-Bit Image", [F54_16BIT_IMAGE] = "Normalized 16-Bit Image",
......
...@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused) ...@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused)
/************************* Keepalive timer task *********************/ /************************* Keepalive timer task *********************/
static void hil_mlcs_timer(unsigned long data) static void hil_mlcs_timer(struct timer_list *unused)
{ {
hil_mlcs_probe = 1; hil_mlcs_probe = 1;
tasklet_schedule(&hil_mlcs_tasklet); tasklet_schedule(&hil_mlcs_tasklet);
...@@ -998,7 +998,7 @@ int hil_mlc_unregister(hil_mlc *mlc) ...@@ -998,7 +998,7 @@ int hil_mlc_unregister(hil_mlc *mlc)
static int __init hil_mlc_init(void) static int __init hil_mlc_init(void)
{ {
setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0); timer_setup(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
mod_timer(&hil_mlcs_kicker, jiffies + HZ); mod_timer(&hil_mlcs_kicker, jiffies + HZ);
tasklet_enable(&hil_mlcs_tasklet); tasklet_enable(&hil_mlcs_tasklet);
......
...@@ -794,7 +794,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) ...@@ -794,7 +794,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
/************************* Keepalive timer task *********************/ /************************* Keepalive timer task *********************/
static void hp_sdc_kicker(unsigned long data) static void hp_sdc_kicker(struct timer_list *unused)
{ {
tasklet_schedule(&hp_sdc.task); tasklet_schedule(&hp_sdc.task);
/* Re-insert the periodic task. */ /* Re-insert the periodic task. */
...@@ -909,9 +909,8 @@ static int __init hp_sdc_init(void) ...@@ -909,9 +909,8 @@ static int __init hp_sdc_init(void)
down(&s_sync); /* Wait for t_sync to complete */ down(&s_sync); /* Wait for t_sync to complete */
/* Create the keepalive task */ /* Create the keepalive task */
init_timer(&hp_sdc.kicker); timer_setup(&hp_sdc.kicker, hp_sdc_kicker, 0);
hp_sdc.kicker.expires = jiffies + HZ; hp_sdc.kicker.expires = jiffies + HZ;
hp_sdc.kicker.function = &hp_sdc_kicker;
add_timer(&hp_sdc.kicker); add_timer(&hp_sdc.kicker);
hp_sdc.dev_err = 0; hp_sdc.dev_err = 0;
......
...@@ -366,6 +366,7 @@ static int ps2_gpio_probe(struct platform_device *pdev) ...@@ -366,6 +366,7 @@ static int ps2_gpio_probe(struct platform_device *pdev)
gpiod_cansleep(drvdata->gpio_clk)) { gpiod_cansleep(drvdata->gpio_clk)) {
dev_err(dev, "GPIO data or clk are connected via slow bus\n"); dev_err(dev, "GPIO data or clk are connected via slow bus\n");
error = -EINVAL; error = -EINVAL;
goto err_free_serio;
} }
drvdata->irq = platform_get_irq(pdev, 0); drvdata->irq = platform_get_irq(pdev, 0);
......
...@@ -47,6 +47,8 @@ struct ps2if { ...@@ -47,6 +47,8 @@ struct ps2if {
struct serio *io; struct serio *io;
struct sa1111_dev *dev; struct sa1111_dev *dev;
void __iomem *base; void __iomem *base;
int rx_irq;
int tx_irq;
unsigned int open; unsigned int open;
spinlock_t lock; spinlock_t lock;
unsigned int head; unsigned int head;
...@@ -64,22 +66,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id) ...@@ -64,22 +66,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
struct ps2if *ps2if = dev_id; struct ps2if *ps2if = dev_id;
unsigned int scancode, flag, status; unsigned int scancode, flag, status;
status = sa1111_readl(ps2if->base + PS2STAT); status = readl_relaxed(ps2if->base + PS2STAT);
while (status & PS2STAT_RXF) { while (status & PS2STAT_RXF) {
if (status & PS2STAT_STP) if (status & PS2STAT_STP)
sa1111_writel(PS2STAT_STP, ps2if->base + PS2STAT); writel_relaxed(PS2STAT_STP, ps2if->base + PS2STAT);
flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
(status & PS2STAT_RXP ? 0 : SERIO_PARITY); (status & PS2STAT_RXP ? 0 : SERIO_PARITY);
scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff; scancode = readl_relaxed(ps2if->base + PS2DATA) & 0xff;
if (hweight8(scancode) & 1) if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY; flag ^= SERIO_PARITY;
serio_interrupt(ps2if->io, scancode, flag); serio_interrupt(ps2if->io, scancode, flag);
status = sa1111_readl(ps2if->base + PS2STAT); status = readl_relaxed(ps2if->base + PS2STAT);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -94,12 +96,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) ...@@ -94,12 +96,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
unsigned int status; unsigned int status;
spin_lock(&ps2if->lock); spin_lock(&ps2if->lock);
status = sa1111_readl(ps2if->base + PS2STAT); status = readl_relaxed(ps2if->base + PS2STAT);
if (ps2if->head == ps2if->tail) { if (ps2if->head == ps2if->tail) {
disable_irq_nosync(irq); disable_irq_nosync(irq);
/* done */ /* done */
} else if (status & PS2STAT_TXE) { } else if (status & PS2STAT_TXE) {
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA); writel_relaxed(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
} }
spin_unlock(&ps2if->lock); spin_unlock(&ps2if->lock);
...@@ -122,11 +124,11 @@ static int ps2_write(struct serio *io, unsigned char val) ...@@ -122,11 +124,11 @@ static int ps2_write(struct serio *io, unsigned char val)
/* /*
* If the TX register is empty, we can go straight out. * If the TX register is empty, we can go straight out.
*/ */
if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) { if (readl_relaxed(ps2if->base + PS2STAT) & PS2STAT_TXE) {
sa1111_writel(val, ps2if->base + PS2DATA); writel_relaxed(val, ps2if->base + PS2DATA);
} else { } else {
if (ps2if->head == ps2if->tail) if (ps2if->head == ps2if->tail)
enable_irq(ps2if->dev->irq[1]); enable_irq(ps2if->tx_irq);
head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1); head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
if (head != ps2if->tail) { if (head != ps2if->tail) {
ps2if->buf[ps2if->head] = val; ps2if->buf[ps2if->head] = val;
...@@ -147,30 +149,30 @@ static int ps2_open(struct serio *io) ...@@ -147,30 +149,30 @@ static int ps2_open(struct serio *io)
if (ret) if (ret)
return ret; return ret;
ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0, ret = request_irq(ps2if->rx_irq, ps2_rxint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if); SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) { if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
ps2if->dev->irq[0], ret); ps2if->rx_irq, ret);
sa1111_disable_device(ps2if->dev); sa1111_disable_device(ps2if->dev);
return ret; return ret;
} }
ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0, ret = request_irq(ps2if->tx_irq, ps2_txint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if); SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) { if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
ps2if->dev->irq[1], ret); ps2if->tx_irq, ret);
free_irq(ps2if->dev->irq[0], ps2if); free_irq(ps2if->rx_irq, ps2if);
sa1111_disable_device(ps2if->dev); sa1111_disable_device(ps2if->dev);
return ret; return ret;
} }
ps2if->open = 1; ps2if->open = 1;
enable_irq_wake(ps2if->dev->irq[0]); enable_irq_wake(ps2if->rx_irq);
sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR); writel_relaxed(PS2CR_ENA, ps2if->base + PS2CR);
return 0; return 0;
} }
...@@ -178,14 +180,14 @@ static void ps2_close(struct serio *io) ...@@ -178,14 +180,14 @@ static void ps2_close(struct serio *io)
{ {
struct ps2if *ps2if = io->port_data; struct ps2if *ps2if = io->port_data;
sa1111_writel(0, ps2if->base + PS2CR); writel_relaxed(0, ps2if->base + PS2CR);
disable_irq_wake(ps2if->dev->irq[0]); disable_irq_wake(ps2if->rx_irq);
ps2if->open = 0; ps2if->open = 0;
free_irq(ps2if->dev->irq[1], ps2if); free_irq(ps2if->tx_irq, ps2if);
free_irq(ps2if->dev->irq[0], ps2if); free_irq(ps2if->rx_irq, ps2if);
sa1111_disable_device(ps2if->dev); sa1111_disable_device(ps2if->dev);
} }
...@@ -198,7 +200,7 @@ static void ps2_clear_input(struct ps2if *ps2if) ...@@ -198,7 +200,7 @@ static void ps2_clear_input(struct ps2if *ps2if)
int maxread = 100; int maxread = 100;
while (maxread--) { while (maxread--) {
if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff) if ((readl_relaxed(ps2if->base + PS2DATA) & 0xff) == 0xff)
break; break;
} }
} }
...@@ -208,11 +210,11 @@ static unsigned int ps2_test_one(struct ps2if *ps2if, ...@@ -208,11 +210,11 @@ static unsigned int ps2_test_one(struct ps2if *ps2if,
{ {
unsigned int val; unsigned int val;
sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR); writel_relaxed(PS2CR_ENA | mask, ps2if->base + PS2CR);
udelay(2); udelay(10);
val = sa1111_readl(ps2if->base + PS2STAT); val = readl_relaxed(ps2if->base + PS2STAT);
return val & (PS2STAT_KBC | PS2STAT_KBD); return val & (PS2STAT_KBC | PS2STAT_KBD);
} }
...@@ -243,7 +245,7 @@ static int ps2_test(struct ps2if *ps2if) ...@@ -243,7 +245,7 @@ static int ps2_test(struct ps2if *ps2if)
ret = -ENODEV; ret = -ENODEV;
} }
sa1111_writel(0, ps2if->base + PS2CR); writel_relaxed(0, ps2if->base + PS2CR);
return ret; return ret;
} }
...@@ -264,7 +266,6 @@ static int ps2_probe(struct sa1111_dev *dev) ...@@ -264,7 +266,6 @@ static int ps2_probe(struct sa1111_dev *dev)
goto free; goto free;
} }
serio->id.type = SERIO_8042; serio->id.type = SERIO_8042;
serio->write = ps2_write; serio->write = ps2_write;
serio->open = ps2_open; serio->open = ps2_open;
...@@ -279,6 +280,18 @@ static int ps2_probe(struct sa1111_dev *dev) ...@@ -279,6 +280,18 @@ static int ps2_probe(struct sa1111_dev *dev)
spin_lock_init(&ps2if->lock); spin_lock_init(&ps2if->lock);
ps2if->rx_irq = sa1111_get_irq(dev, 0);
if (ps2if->rx_irq <= 0) {
ret = ps2if->rx_irq ? : -ENXIO;
goto free;
}
ps2if->tx_irq = sa1111_get_irq(dev, 1);
if (ps2if->tx_irq <= 0) {
ret = ps2if->tx_irq ? : -ENXIO;
goto free;
}
/* /*
* Request the physical region for this PS2 port. * Request the physical region for this PS2 port.
*/ */
...@@ -297,8 +310,8 @@ static int ps2_probe(struct sa1111_dev *dev) ...@@ -297,8 +310,8 @@ static int ps2_probe(struct sa1111_dev *dev)
sa1111_enable_device(ps2if->dev); sa1111_enable_device(ps2if->dev);
/* Incoming clock is 8MHz */ /* Incoming clock is 8MHz */
sa1111_writel(0, ps2if->base + PS2CLKDIV); writel_relaxed(0, ps2if->base + PS2CLKDIV);
sa1111_writel(127, ps2if->base + PS2PRECNT); writel_relaxed(127, ps2if->base + PS2PRECNT);
/* /*
* Flush any pending input. * Flush any pending input.
......
...@@ -316,6 +316,16 @@ config TOUCHSCREEN_EGALAX_SERIAL ...@@ -316,6 +316,16 @@ config TOUCHSCREEN_EGALAX_SERIAL
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 egalax_ts_serial. module will be called egalax_ts_serial.
config TOUCHSCREEN_EXC3000
tristate "EETI EXC3000 multi-touch panel support"
depends on I2C
help
Say Y here to enable support for I2C connected EETI
EXC3000 multi-touch panels.
To compile this driver as a module, choose M here: the
module will be called exc3000.
config TOUCHSCREEN_FUJITSU config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen" tristate "Fujitsu serial touchscreen"
select SERIO select SERIO
...@@ -344,6 +354,17 @@ config TOUCHSCREEN_GOODIX ...@@ -344,6 +354,17 @@ config TOUCHSCREEN_GOODIX
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 goodix. module will be called goodix.
config TOUCHSCREEN_HIDEEP
tristate "HiDeep Touch IC"
depends on I2C
help
Say Y here if you have a touchscreen using HiDeep.
If unsure, say N.
To compile this driver as a moudle, choose M here : the
module will be called hideep_ts.
config TOUCHSCREEN_ILI210X config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen" tristate "Ilitek ILI210X based touchscreen"
depends on I2C depends on I2C
...@@ -383,6 +404,17 @@ config TOUCHSCREEN_S3C2410 ...@@ -383,6 +404,17 @@ config TOUCHSCREEN_S3C2410
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 s3c2410_ts. module will be called s3c2410_ts.
config TOUCHSCREEN_S6SY761
tristate "Samsung S6SY761 Touchscreen driver"
depends on I2C
help
Say Y if you have the Samsung S6SY761 driver
If unsure, say N
To compile this driver as module, choose M here: the
module will be called s6sy761.
config TOUCHSCREEN_GUNZE config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen" tristate "Gunze AHL-51S touchscreen"
select SERIO select SERIO
...@@ -949,7 +981,7 @@ config TOUCHSCREEN_USB_NEXIO ...@@ -949,7 +981,7 @@ config TOUCHSCREEN_USB_NEXIO
config TOUCHSCREEN_USB_EASYTOUCH config TOUCHSCREEN_USB_EASYTOUCH
default y default y
bool "EasyTouch USB Touch controller device support" if EMBEDDED bool "EasyTouch USB Touch controller device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE depends on TOUCHSCREEN_USB_COMPOSITE
help help
Say Y here if you have an EasyTouch USB Touch controller. Say Y here if you have an EasyTouch USB Touch controller.
......
...@@ -38,8 +38,10 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o ...@@ -38,8 +38,10 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
...@@ -65,6 +67,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o ...@@ -65,6 +67,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_S6SY761) += s6sy761.o
obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o
obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
......
...@@ -385,9 +385,9 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts) ...@@ -385,9 +385,9 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
input_sync(input_dev); input_sync(input_dev);
} }
static void ad7877_timer(unsigned long handle) static void ad7877_timer(struct timer_list *t)
{ {
struct ad7877 *ts = (void *)handle; struct ad7877 *ts = from_timer(ts, t, timer);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ts->lock, flags); spin_lock_irqsave(&ts->lock, flags);
...@@ -718,7 +718,7 @@ static int ad7877_probe(struct spi_device *spi) ...@@ -718,7 +718,7 @@ static int ad7877_probe(struct spi_device *spi)
ts->spi = spi; ts->spi = spi;
ts->input = input_dev; ts->input = input_dev;
setup_timer(&ts->timer, ad7877_timer, (unsigned long) ts); timer_setup(&ts->timer, ad7877_timer, 0);
mutex_init(&ts->mutex); mutex_init(&ts->mutex);
spin_lock_init(&ts->lock); spin_lock_init(&ts->lock);
......
...@@ -237,9 +237,9 @@ static void ad7879_ts_event_release(struct ad7879 *ts) ...@@ -237,9 +237,9 @@ static void ad7879_ts_event_release(struct ad7879 *ts)
input_sync(input_dev); input_sync(input_dev);
} }
static void ad7879_timer(unsigned long handle) static void ad7879_timer(struct timer_list *t)
{ {
struct ad7879 *ts = (void *)handle; struct ad7879 *ts = from_timer(ts, t, timer);
ad7879_ts_event_release(ts); ad7879_ts_event_release(ts);
} }
...@@ -524,13 +524,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts) ...@@ -524,13 +524,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts)
return 0; return 0;
} }
static void ad7879_cleanup_sysfs(void *_ts)
{
struct ad7879 *ts = _ts;
sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);
}
int ad7879_probe(struct device *dev, struct regmap *regmap, int ad7879_probe(struct device *dev, struct regmap *regmap,
int irq, u16 bustype, u8 devid) int irq, u16 bustype, u8 devid)
{ {
...@@ -577,7 +570,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, ...@@ -577,7 +570,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
ts->irq = irq; ts->irq = irq;
ts->regmap = regmap; ts->regmap = regmap;
setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); timer_setup(&ts->timer, ad7879_timer, 0);
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
input_dev->name = "AD7879 Touchscreen"; input_dev->name = "AD7879 Touchscreen";
...@@ -658,11 +651,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, ...@@ -658,11 +651,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
__ad7879_disable(ts); __ad7879_disable(ts);
err = sysfs_create_group(&dev->kobj, &ad7879_attr_group); err = devm_device_add_group(dev, &ad7879_attr_group);
if (err)
return err;
err = devm_add_action_or_reset(dev, ad7879_cleanup_sysfs, ts);
if (err) if (err)
return err; return err;
......
...@@ -208,9 +208,12 @@ static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm) ...@@ -208,9 +208,12 @@ static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
} }
} }
static void atmel_wm97xx_pen_timer(unsigned long data) static void atmel_wm97xx_pen_timer(struct timer_list *t)
{ {
atmel_wm97xx_acc_pen_up((struct wm97xx *)data); struct atmel_wm97xx *atmel_wm97xx = from_timer(atmel_wm97xx, t,
pen_timer);
atmel_wm97xx_acc_pen_up(atmel_wm97xx->wm);
} }
static int atmel_wm97xx_acc_startup(struct wm97xx *wm) static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
...@@ -348,8 +351,7 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev) ...@@ -348,8 +351,7 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev)
atmel_wm97xx->gpio_pen = atmel_gpio_line; atmel_wm97xx->gpio_pen = atmel_gpio_line;
atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen); atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, timer_setup(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 0);
(unsigned long)wm);
ret = request_irq(atmel_wm97xx->ac97c_irq, ret = request_irq(atmel_wm97xx->ac97c_irq,
atmel_wm97xx_channel_b_interrupt, atmel_wm97xx_channel_b_interrupt,
......
...@@ -201,13 +201,21 @@ static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) ...@@ -201,13 +201,21 @@ static int cyttsp4_si_get_cydata(struct cyttsp4 *cd)
void *p; void *p;
int rc; int rc;
if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) {
dev_err(cd->dev,
"%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n",
__func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs);
return -EINVAL;
}
si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs;
dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__,
si->si_ofs.cydata_size); si->si_ofs.cydata_size);
p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL);
if (p == NULL) { if (p == NULL) {
dev_err(cd->dev, "%s: fail alloc cydata memory\n", __func__); dev_err(cd->dev, "%s: failed to allocate cydata memory\n",
__func__);
return -ENOMEM; return -ENOMEM;
} }
si->si_ptrs.cydata = p; si->si_ptrs.cydata = p;
...@@ -270,11 +278,19 @@ static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) ...@@ -270,11 +278,19 @@ static int cyttsp4_si_get_test_data(struct cyttsp4 *cd)
void *p; void *p;
int rc; int rc;
if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) {
dev_err(cd->dev,
"%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n",
__func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs);
return -EINVAL;
}
si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs;
p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL);
if (p == NULL) { if (p == NULL) {
dev_err(cd->dev, "%s: fail alloc test memory\n", __func__); dev_err(cd->dev, "%s: failed to allocate test memory\n",
__func__);
return -ENOMEM; return -ENOMEM;
} }
si->si_ptrs.test = p; si->si_ptrs.test = p;
...@@ -321,14 +337,20 @@ static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) ...@@ -321,14 +337,20 @@ static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd)
void *p; void *p;
int rc; int rc;
if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) {
dev_err(cd->dev,
"%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n",
__func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs);
return -EINVAL;
}
si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs;
p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL);
if (p == NULL) { if (p == NULL) {
rc = -ENOMEM; dev_err(cd->dev, "%s: failed to allocate pcfg memory\n",
dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n", __func__);
__func__, rc); return -ENOMEM;
return rc;
} }
si->si_ptrs.pcfg = p; si->si_ptrs.pcfg = p;
...@@ -367,13 +389,20 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) ...@@ -367,13 +389,20 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
void *p; void *p;
int rc; int rc;
if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) {
dev_err(cd->dev,
"%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n",
__func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs);
return -EINVAL;
}
si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs;
p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL);
if (p == NULL) { if (p == NULL) {
dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__); dev_err(cd->dev, "%s: failed to allocate opcfg memory\n",
rc = -ENOMEM; __func__);
goto cyttsp4_si_get_opcfg_data_exit; return -ENOMEM;
} }
si->si_ptrs.opcfg = p; si->si_ptrs.opcfg = p;
...@@ -382,7 +411,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) ...@@ -382,7 +411,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
if (rc < 0) { if (rc < 0) {
dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", dev_err(cd->dev, "%s: fail read opcfg data r=%d\n",
__func__, rc); __func__, rc);
goto cyttsp4_si_get_opcfg_data_exit; return rc;
} }
si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs;
si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs;
...@@ -447,8 +476,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) ...@@ -447,8 +476,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg,
si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); si->si_ofs.opcfg_size, "sysinfo_opcfg_data");
cyttsp4_si_get_opcfg_data_exit: return 0;
return rc;
} }
static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) static int cyttsp4_si_get_ddata(struct cyttsp4 *cd)
...@@ -1237,9 +1265,9 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) ...@@ -1237,9 +1265,9 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd)
del_timer_sync(&cd->watchdog_timer); del_timer_sync(&cd->watchdog_timer);
} }
static void cyttsp4_watchdog_timer(unsigned long handle) static void cyttsp4_watchdog_timer(struct timer_list *t)
{ {
struct cyttsp4 *cd = (struct cyttsp4 *)handle; struct cyttsp4 *cd = from_timer(cd, t, watchdog_timer);
dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__); dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__);
...@@ -2074,8 +2102,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, ...@@ -2074,8 +2102,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
} }
/* Setup watchdog timer */ /* Setup watchdog timer */
setup_timer(&cd->watchdog_timer, cyttsp4_watchdog_timer, timer_setup(&cd->watchdog_timer, cyttsp4_watchdog_timer, 0);
(unsigned long)cd);
/* /*
* call startup directly to ensure that the device * call startup directly to ensure that the device
......
This diff is collapsed.
...@@ -1070,13 +1070,6 @@ static const struct attribute_group elants_attribute_group = { ...@@ -1070,13 +1070,6 @@ static const struct attribute_group elants_attribute_group = {
.attrs = elants_attributes, .attrs = elants_attributes,
}; };
static void elants_i2c_remove_sysfs_group(void *_data)
{
struct elants_data *ts = _data;
sysfs_remove_group(&ts->client->dev.kobj, &elants_attribute_group);
}
static int elants_i2c_power_on(struct elants_data *ts) static int elants_i2c_power_on(struct elants_data *ts)
{ {
int error; int error;
...@@ -1289,23 +1282,13 @@ static int elants_i2c_probe(struct i2c_client *client, ...@@ -1289,23 +1282,13 @@ static int elants_i2c_probe(struct i2c_client *client,
if (!client->dev.of_node) if (!client->dev.of_node)
device_init_wakeup(&client->dev, true); device_init_wakeup(&client->dev, true);
error = sysfs_create_group(&client->dev.kobj, &elants_attribute_group); error = devm_device_add_group(&client->dev, &elants_attribute_group);
if (error) { if (error) {
dev_err(&client->dev, "failed to create sysfs attributes: %d\n", dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
error); error);
return error; return error;
} }
error = devm_add_action(&client->dev,
elants_i2c_remove_sysfs_group, ts);
if (error) {
elants_i2c_remove_sysfs_group(ts);
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n",
error);
return error;
}
return 0; return 0;
} }
......
/*
* Driver for I2C connected EETI EXC3000 multiple touch controller
*
* Copyright (C) 2017 Ahmet Inan <inan@distec.de>
*
* minimal implementation based on egalax_ts.c and egalax_i2c.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/timer.h>
#include <asm/unaligned.h>
#define EXC3000_NUM_SLOTS 10
#define EXC3000_SLOTS_PER_FRAME 5
#define EXC3000_LEN_FRAME 66
#define EXC3000_LEN_POINT 10
#define EXC3000_MT_EVENT 6
#define EXC3000_TIMEOUT_MS 100
struct exc3000_data {
struct i2c_client *client;
struct input_dev *input;
struct touchscreen_properties prop;
struct timer_list timer;
u8 buf[2 * EXC3000_LEN_FRAME];
};
static void exc3000_report_slots(struct input_dev *input,
struct touchscreen_properties *prop,
const u8 *buf, int num)
{
for (; num--; buf += EXC3000_LEN_POINT) {
if (buf[0] & BIT(0)) {
input_mt_slot(input, buf[1]);
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
touchscreen_report_pos(input, prop,
get_unaligned_le16(buf + 2),
get_unaligned_le16(buf + 4),
true);
}
}
}
static void exc3000_timer(struct timer_list *t)
{
struct exc3000_data *data = from_timer(data, t, timer);
input_mt_sync_frame(data->input);
input_sync(data->input);
}
static int exc3000_read_frame(struct i2c_client *client, u8 *buf)
{
int ret;
ret = i2c_master_send(client, "'", 2);
if (ret < 0)
return ret;
if (ret != 2)
return -EIO;
ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME);
if (ret < 0)
return ret;
if (ret != EXC3000_LEN_FRAME)
return -EIO;
if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME ||
buf[2] != EXC3000_MT_EVENT)
return -EINVAL;
return 0;
}
static int exc3000_read_data(struct i2c_client *client,
u8 *buf, int *n_slots)
{
int error;
error = exc3000_read_frame(client, buf);
if (error)
return error;
*n_slots = buf[3];
if (!*n_slots || *n_slots > EXC3000_NUM_SLOTS)
return -EINVAL;
if (*n_slots > EXC3000_SLOTS_PER_FRAME) {
/* Read 2nd frame to get the rest of the contacts. */
error = exc3000_read_frame(client, buf + EXC3000_LEN_FRAME);
if (error)
return error;
/* 2nd chunk must have number of contacts set to 0. */
if (buf[EXC3000_LEN_FRAME + 3] != 0)
return -EINVAL;
}
return 0;
}
static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
{
struct exc3000_data *data = dev_id;
struct input_dev *input = data->input;
u8 *buf = data->buf;
int slots, total_slots;
int error;
error = exc3000_read_data(data->client, buf, &total_slots);
if (error) {
/* Schedule a timer to release "stuck" contacts */
mod_timer(&data->timer,
jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS));
goto out;
}
/*
* We read full state successfully, no contacts will be "stuck".
*/
del_timer_sync(&data->timer);
while (total_slots > 0) {
slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
exc3000_report_slots(input, &data->prop, buf + 4, slots);
total_slots -= slots;
buf += EXC3000_LEN_FRAME;
}
input_mt_sync_frame(input);
input_sync(input);
out:
return IRQ_HANDLED;
}
static int exc3000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct exc3000_data *data;
struct input_dev *input;
int error;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->client = client;
timer_setup(&data->timer, exc3000_timer, 0);
input = devm_input_allocate_device(&client->dev);
if (!input)
return -ENOMEM;
data->input = input;
input->name = "EETI EXC3000 Touch Screen";
input->id.bustype = BUS_I2C;
input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
touchscreen_parse_properties(input, true, &data->prop);
error = input_mt_init_slots(input, EXC3000_NUM_SLOTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error)
return error;
error = input_register_device(input);
if (error)
return error;
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, exc3000_interrupt, IRQF_ONESHOT,
client->name, data);
if (error)
return error;
return 0;
}
static const struct i2c_device_id exc3000_id[] = {
{ "exc3000", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, exc3000_id);
#ifdef CONFIG_OF
static const struct of_device_id exc3000_of_match[] = {
{ .compatible = "eeti,exc3000" },
{ }
};
MODULE_DEVICE_TABLE(of, exc3000_of_match);
#endif
static struct i2c_driver exc3000_driver = {
.driver = {
.name = "exc3000",
.of_match_table = of_match_ptr(exc3000_of_match),
},
.id_table = exc3000_id,
.probe = exc3000_probe,
};
module_i2c_driver(exc3000_driver);
MODULE_AUTHOR("Ahmet Inan <inan@distec.de>");
MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver");
MODULE_LICENSE("GPL v2");
...@@ -31,9 +31,18 @@ ...@@ -31,9 +31,18 @@
#include <linux/of.h> #include <linux/of.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
struct goodix_ts_data;
struct goodix_chip_data {
u16 config_addr;
int config_len;
int (*check_config)(struct goodix_ts_data *, const struct firmware *);
};
struct goodix_ts_data { struct goodix_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input_dev; struct input_dev *input_dev;
const struct goodix_chip_data *chip;
int abs_x_max; int abs_x_max;
int abs_y_max; int abs_y_max;
bool swapped_x_y; bool swapped_x_y;
...@@ -41,7 +50,6 @@ struct goodix_ts_data { ...@@ -41,7 +50,6 @@ struct goodix_ts_data {
bool inverted_y; bool inverted_y;
unsigned int max_touch_num; unsigned int max_touch_num;
unsigned int int_trigger_type; unsigned int int_trigger_type;
int cfg_len;
struct gpio_desc *gpiod_int; struct gpio_desc *gpiod_int;
struct gpio_desc *gpiod_rst; struct gpio_desc *gpiod_rst;
u16 id; u16 id;
...@@ -69,7 +77,8 @@ struct goodix_ts_data { ...@@ -69,7 +77,8 @@ struct goodix_ts_data {
#define GOODIX_CMD_SCREEN_OFF 0x05 #define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_READ_COOR_ADDR 0x814E #define GOODIX_READ_COOR_ADDR 0x814E
#define GOODIX_REG_CONFIG_DATA 0x8047 #define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140 #define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7) #define GOODIX_BUFFER_STATUS_READY BIT(7)
...@@ -79,6 +88,35 @@ struct goodix_ts_data { ...@@ -79,6 +88,35 @@ struct goodix_ts_data {
#define MAX_CONTACTS_LOC 5 #define MAX_CONTACTS_LOC 5
#define TRIGGER_LOC 6 #define TRIGGER_LOC 6
static int goodix_check_cfg_8(struct goodix_ts_data *ts,
const struct firmware *cfg);
static int goodix_check_cfg_16(struct goodix_ts_data *ts,
const struct firmware *cfg);
static const struct goodix_chip_data gt1x_chip_data = {
.config_addr = GOODIX_GT1X_REG_CONFIG_DATA,
.config_len = GOODIX_CONFIG_MAX_LENGTH,
.check_config = goodix_check_cfg_16,
};
static const struct goodix_chip_data gt911_chip_data = {
.config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
.config_len = GOODIX_CONFIG_911_LENGTH,
.check_config = goodix_check_cfg_8,
};
static const struct goodix_chip_data gt967_chip_data = {
.config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
.config_len = GOODIX_CONFIG_967_LENGTH,
.check_config = goodix_check_cfg_8,
};
static const struct goodix_chip_data gt9x_chip_data = {
.config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
.config_len = GOODIX_CONFIG_MAX_LENGTH,
.check_config = goodix_check_cfg_8,
};
static const unsigned long goodix_irq_flags[] = { static const unsigned long goodix_irq_flags[] = {
IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_EDGE_FALLING,
...@@ -177,22 +215,25 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value) ...@@ -177,22 +215,25 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
return goodix_i2c_write(client, reg, &value, sizeof(value)); return goodix_i2c_write(client, reg, &value, sizeof(value));
} }
static int goodix_get_cfg_len(u16 id) static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
{ {
switch (id) { switch (id) {
case 1151:
return &gt1x_chip_data;
case 911: case 911:
case 9271: case 9271:
case 9110: case 9110:
case 927: case 927:
case 928: case 928:
return GOODIX_CONFIG_911_LENGTH; return &gt911_chip_data;
case 912: case 912:
case 967: case 967:
return GOODIX_CONFIG_967_LENGTH; return &gt967_chip_data;
default: default:
return GOODIX_CONFIG_MAX_LENGTH; return &gt9x_chip_data;
} }
} }
...@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts) ...@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
ts->irq_flags, ts->client->name, ts); ts->irq_flags, ts->client->name, ts);
} }
/** static int goodix_check_cfg_8(struct goodix_ts_data *ts,
* goodix_check_cfg - Checks if config fw is valid const struct firmware *cfg)
*
* @ts: goodix_ts_data pointer
* @cfg: firmware config data
*/
static int goodix_check_cfg(struct goodix_ts_data *ts,
const struct firmware *cfg)
{ {
int i, raw_cfg_len; int i, raw_cfg_len = cfg->size - 2;
u8 check_sum = 0; u8 check_sum = 0;
if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
dev_err(&ts->client->dev,
"The length of the config fw is not correct");
return -EINVAL;
}
raw_cfg_len = cfg->size - 2;
for (i = 0; i < raw_cfg_len; i++) for (i = 0; i < raw_cfg_len; i++)
check_sum += cfg->data[i]; check_sum += cfg->data[i];
check_sum = (~check_sum) + 1; check_sum = (~check_sum) + 1;
...@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts, ...@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
return 0; return 0;
} }
static int goodix_check_cfg_16(struct goodix_ts_data *ts,
const struct firmware *cfg)
{
int i, raw_cfg_len = cfg->size - 3;
u16 check_sum = 0;
for (i = 0; i < raw_cfg_len; i += 2)
check_sum += get_unaligned_be16(&cfg->data[i]);
check_sum = (~check_sum) + 1;
if (check_sum != get_unaligned_be16(&cfg->data[raw_cfg_len])) {
dev_err(&ts->client->dev,
"The checksum of the config fw is not correct");
return -EINVAL;
}
if (cfg->data[raw_cfg_len + 2] != 1) {
dev_err(&ts->client->dev,
"Config fw must have Config_Fresh register set");
return -EINVAL;
}
return 0;
}
/**
* goodix_check_cfg - Checks if config fw is valid
*
* @ts: goodix_ts_data pointer
* @cfg: firmware config data
*/
static int goodix_check_cfg(struct goodix_ts_data *ts,
const struct firmware *cfg)
{
if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
dev_err(&ts->client->dev,
"The length of the config fw is not correct");
return -EINVAL;
}
return ts->chip->check_config(ts, cfg);
}
/** /**
* goodix_send_cfg - Write fw config to device * goodix_send_cfg - Write fw config to device
* *
...@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts, ...@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
if (error) if (error)
return error; return error;
error = goodix_i2c_write(ts->client, GOODIX_REG_CONFIG_DATA, cfg->data, error = goodix_i2c_write(ts->client, ts->chip->config_addr, cfg->data,
cfg->size); cfg->size);
if (error) { if (error) {
dev_err(&ts->client->dev, "Failed to write config data: %d", dev_err(&ts->client->dev, "Failed to write config data: %d",
...@@ -511,8 +581,8 @@ static void goodix_read_config(struct goodix_ts_data *ts) ...@@ -511,8 +581,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
u8 config[GOODIX_CONFIG_MAX_LENGTH]; u8 config[GOODIX_CONFIG_MAX_LENGTH];
int error; int error;
error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA, error = goodix_i2c_read(ts->client, ts->chip->config_addr,
config, ts->cfg_len); config, ts->chip->config_len);
if (error) { if (error) {
dev_warn(&ts->client->dev, dev_warn(&ts->client->dev,
"Error reading config (%d), using defaults\n", "Error reading config (%d), using defaults\n",
...@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client) ...@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client)
u8 test; u8 test;
while (retry++ < 2) { while (retry++ < 2) {
error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA, error = goodix_i2c_read(client, GOODIX_REG_ID,
&test, 1); &test, 1);
if (!error) if (!error)
return 0; return 0;
...@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client, ...@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client,
return error; return error;
} }
ts->cfg_len = goodix_get_cfg_len(ts->id); ts->chip = goodix_get_chip_data(ts->id);
if (ts->gpiod_int && ts->gpiod_rst) { if (ts->gpiod_int && ts->gpiod_rst) {
/* update device config */ /* update device config */
...@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); ...@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id goodix_of_match[] = { static const struct of_device_id goodix_of_match[] = {
{ .compatible = "goodix,gt1151" },
{ .compatible = "goodix,gt911" }, { .compatible = "goodix,gt911" },
{ .compatible = "goodix,gt9110" }, { .compatible = "goodix,gt9110" },
{ .compatible = "goodix,gt912" }, { .compatible = "goodix,gt912" },
......
This diff is collapsed.
...@@ -1433,13 +1433,6 @@ static const struct attribute_group mip4_attr_group = { ...@@ -1433,13 +1433,6 @@ static const struct attribute_group mip4_attr_group = {
.attrs = mip4_attrs, .attrs = mip4_attrs,
}; };
static void mip4_sysfs_remove(void *_data)
{
struct mip4_ts *ts = _data;
sysfs_remove_group(&ts->client->dev.kobj, &mip4_attr_group);
}
static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id) static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct mip4_ts *ts; struct mip4_ts *ts;
...@@ -1535,21 +1528,13 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1535,21 +1528,13 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
return error; return error;
} }
error = sysfs_create_group(&client->dev.kobj, &mip4_attr_group); error = devm_device_add_group(&client->dev, &mip4_attr_group);
if (error) { if (error) {
dev_err(&client->dev, dev_err(&client->dev,
"Failed to create sysfs attribute group: %d\n", error); "Failed to create sysfs attribute group: %d\n", error);
return error; return error;
} }
error = devm_add_action(&client->dev, mip4_sysfs_remove, ts);
if (error) {
mip4_sysfs_remove(ts);
dev_err(&client->dev,
"Failed to install sysfs remoce action: %d\n", error);
return error;
}
return 0; return 0;
} }
......
...@@ -584,7 +584,7 @@ static void mxs_lradc_ts_hw_init(struct mxs_lradc_ts *ts) ...@@ -584,7 +584,7 @@ static void mxs_lradc_ts_hw_init(struct mxs_lradc_ts *ts)
static int mxs_lradc_ts_register(struct mxs_lradc_ts *ts) static int mxs_lradc_ts_register(struct mxs_lradc_ts *ts)
{ {
struct input_dev *input = ts->ts_input; struct input_dev *input;
struct device *dev = ts->dev; struct device *dev = ts->dev;
input = devm_input_allocate_device(dev); input = devm_input_allocate_device(dev);
......
...@@ -943,13 +943,6 @@ static const struct attribute_group raydium_i2c_attribute_group = { ...@@ -943,13 +943,6 @@ static const struct attribute_group raydium_i2c_attribute_group = {
.attrs = raydium_i2c_attributes, .attrs = raydium_i2c_attributes,
}; };
static void raydium_i2c_remove_sysfs_group(void *_data)
{
struct raydium_data *ts = _data;
sysfs_remove_group(&ts->client->dev.kobj, &raydium_i2c_attribute_group);
}
static int raydium_i2c_power_on(struct raydium_data *ts) static int raydium_i2c_power_on(struct raydium_data *ts)
{ {
int error; int error;
...@@ -1120,7 +1113,7 @@ static int raydium_i2c_probe(struct i2c_client *client, ...@@ -1120,7 +1113,7 @@ static int raydium_i2c_probe(struct i2c_client *client,
return error; return error;
} }
error = sysfs_create_group(&client->dev.kobj, error = devm_device_add_group(&client->dev,
&raydium_i2c_attribute_group); &raydium_i2c_attribute_group);
if (error) { if (error) {
dev_err(&client->dev, "failed to create sysfs attributes: %d\n", dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
...@@ -1128,15 +1121,6 @@ static int raydium_i2c_probe(struct i2c_client *client, ...@@ -1128,15 +1121,6 @@ static int raydium_i2c_probe(struct i2c_client *client,
return error; return error;
} }
error = devm_add_action(&client->dev,
raydium_i2c_remove_sysfs_group, ts);
if (error) {
raydium_i2c_remove_sysfs_group(ts);
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n", error);
return error;
}
return 0; return 0;
} }
......
...@@ -1103,13 +1103,6 @@ static void rohm_ts_close(struct input_dev *input_dev) ...@@ -1103,13 +1103,6 @@ static void rohm_ts_close(struct input_dev *input_dev)
ts->initialized = false; ts->initialized = false;
} }
static void rohm_ts_remove_sysfs_group(void *_dev)
{
struct device *dev = _dev;
sysfs_remove_group(&dev->kobj, &rohm_ts_attr_group);
}
static int rohm_bu21023_i2c_probe(struct i2c_client *client, static int rohm_bu21023_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -1180,20 +1173,12 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client, ...@@ -1180,20 +1173,12 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client,
return error; return error;
} }
error = sysfs_create_group(&dev->kobj, &rohm_ts_attr_group); error = devm_device_add_group(dev, &rohm_ts_attr_group);
if (error) { if (error) {
dev_err(dev, "failed to create sysfs group: %d\n", error); dev_err(dev, "failed to create sysfs group: %d\n", error);
return error; return error;
} }
error = devm_add_action(dev, rohm_ts_remove_sysfs_group, dev);
if (error) {
rohm_ts_remove_sysfs_group(dev);
dev_err(dev, "Failed to add sysfs cleanup action: %d\n",
error);
return error;
}
return error; return error;
} }
......
This diff is collapsed.
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/platform_data/st1232_pdata.h>
#define ST1232_TS_NAME "st1232-ts" #define ST1232_TS_NAME "st1232-ts"
...@@ -152,10 +151,9 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) ...@@ -152,10 +151,9 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
} }
static int st1232_ts_probe(struct i2c_client *client, static int st1232_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct st1232_ts_data *ts; struct st1232_ts_data *ts;
struct st1232_pdata *pdata = dev_get_platdata(&client->dev);
struct input_dev *input_dev; struct input_dev *input_dev;
int error; int error;
...@@ -180,13 +178,7 @@ static int st1232_ts_probe(struct i2c_client *client, ...@@ -180,13 +178,7 @@ static int st1232_ts_probe(struct i2c_client *client,
ts->client = client; ts->client = client;
ts->input_dev = input_dev; ts->input_dev = input_dev;
if (pdata) ts->reset_gpio = of_get_gpio(client->dev.of_node, 0);
ts->reset_gpio = pdata->reset_gpio;
else if (client->dev.of_node)
ts->reset_gpio = of_get_gpio(client->dev.of_node, 0);
else
ts->reset_gpio = -ENODEV;
if (gpio_is_valid(ts->reset_gpio)) { if (gpio_is_valid(ts->reset_gpio)) {
error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL); error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL);
if (error) { if (error) {
...@@ -281,13 +273,11 @@ static const struct i2c_device_id st1232_ts_id[] = { ...@@ -281,13 +273,11 @@ static const struct i2c_device_id st1232_ts_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, st1232_ts_id); MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
#ifdef CONFIG_OF
static const struct of_device_id st1232_ts_dt_ids[] = { static const struct of_device_id st1232_ts_dt_ids[] = {
{ .compatible = "sitronix,st1232", }, { .compatible = "sitronix,st1232", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
#endif
static struct i2c_driver st1232_ts_driver = { static struct i2c_driver st1232_ts_driver = {
.probe = st1232_ts_probe, .probe = st1232_ts_probe,
...@@ -295,7 +285,7 @@ static struct i2c_driver st1232_ts_driver = { ...@@ -295,7 +285,7 @@ static struct i2c_driver st1232_ts_driver = {
.id_table = st1232_ts_id, .id_table = st1232_ts_id,
.driver = { .driver = {
.name = ST1232_TS_NAME, .name = ST1232_TS_NAME,
.of_match_table = of_match_ptr(st1232_ts_dt_ids), .of_match_table = st1232_ts_dt_ids,
.pm = &st1232_ts_pm_ops, .pm = &st1232_ts_pm_ops,
}, },
}; };
......
...@@ -725,8 +725,7 @@ static int stmfts_probe(struct i2c_client *client, ...@@ -725,8 +725,7 @@ static int stmfts_probe(struct i2c_client *client,
} }
} }
err = sysfs_create_group(&sdata->client->dev.kobj, err = devm_device_add_group(&client->dev, &stmfts_attribute_group);
&stmfts_attribute_group);
if (err) if (err)
return err; return err;
...@@ -738,7 +737,6 @@ static int stmfts_probe(struct i2c_client *client, ...@@ -738,7 +737,6 @@ static int stmfts_probe(struct i2c_client *client,
static int stmfts_remove(struct i2c_client *client) static int stmfts_remove(struct i2c_client *client)
{ {
pm_runtime_disable(&client->dev); pm_runtime_disable(&client->dev);
sysfs_remove_group(&client->dev.kobj, &stmfts_attribute_group);
return 0; return 0;
} }
......
...@@ -202,9 +202,9 @@ static irqreturn_t tsc200x_irq_thread(int irq, void *_ts) ...@@ -202,9 +202,9 @@ static irqreturn_t tsc200x_irq_thread(int irq, void *_ts)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void tsc200x_penup_timer(unsigned long data) static void tsc200x_penup_timer(struct timer_list *t)
{ {
struct tsc200x *ts = (struct tsc200x *)data; struct tsc200x *ts = from_timer(ts, t, penup_timer);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ts->lock, flags); spin_lock_irqsave(&ts->lock, flags);
...@@ -506,7 +506,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, ...@@ -506,7 +506,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
mutex_init(&ts->mutex); mutex_init(&ts->mutex);
spin_lock_init(&ts->lock); spin_lock_init(&ts->lock);
setup_timer(&ts->penup_timer, tsc200x_penup_timer, (unsigned long)ts); timer_setup(&ts->penup_timer, tsc200x_penup_timer, 0);
INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work); INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work);
......
...@@ -146,9 +146,9 @@ static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id) ...@@ -146,9 +146,9 @@ static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void w90p910_check_pen_up(unsigned long data) static void w90p910_check_pen_up(struct timer_list *t)
{ {
struct w90p910_ts *w90p910_ts = (struct w90p910_ts *) data; struct w90p910_ts *w90p910_ts = from_timer(w90p910_ts, t, timer);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&w90p910_ts->lock, flags); spin_lock_irqsave(&w90p910_ts->lock, flags);
...@@ -232,8 +232,7 @@ static int w90x900ts_probe(struct platform_device *pdev) ...@@ -232,8 +232,7 @@ static int w90x900ts_probe(struct platform_device *pdev)
w90p910_ts->input = input_dev; w90p910_ts->input = input_dev;
w90p910_ts->state = TS_IDLE; w90p910_ts->state = TS_IDLE;
spin_lock_init(&w90p910_ts->lock); spin_lock_init(&w90p910_ts->lock);
setup_timer(&w90p910_ts->timer, w90p910_check_pen_up, timer_setup(&w90p910_ts->timer, w90p910_check_pen_up, 0);
(unsigned long)w90p910_ts);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
......
...@@ -1106,7 +1106,7 @@ static int wdt87xx_ts_probe(struct i2c_client *client, ...@@ -1106,7 +1106,7 @@ static int wdt87xx_ts_probe(struct i2c_client *client,
return error; return error;
} }
error = sysfs_create_group(&client->dev.kobj, &wdt87xx_attr_group); error = devm_device_add_group(&client->dev, &wdt87xx_attr_group);
if (error) { if (error) {
dev_err(&client->dev, "create sysfs failed: %d\n", error); dev_err(&client->dev, "create sysfs failed: %d\n", error);
return error; return error;
...@@ -1115,13 +1115,6 @@ static int wdt87xx_ts_probe(struct i2c_client *client, ...@@ -1115,13 +1115,6 @@ static int wdt87xx_ts_probe(struct i2c_client *client,
return 0; return 0;
} }
static int wdt87xx_ts_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &wdt87xx_attr_group);
return 0;
}
static int __maybe_unused wdt87xx_suspend(struct device *dev) static int __maybe_unused wdt87xx_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
...@@ -1179,7 +1172,6 @@ MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); ...@@ -1179,7 +1172,6 @@ MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id);
static struct i2c_driver wdt87xx_driver = { static struct i2c_driver wdt87xx_driver = {
.probe = wdt87xx_ts_probe, .probe = wdt87xx_ts_probe,
.remove = wdt87xx_ts_remove,
.id_table = wdt87xx_dev_id, .id_table = wdt87xx_dev_id,
.driver = { .driver = {
.name = WDT87XX_NAME, .name = WDT87XX_NAME,
......
...@@ -94,7 +94,7 @@ struct infrared { ...@@ -94,7 +94,7 @@ struct infrared {
u8 inversion; u8 inversion;
u16 last_key; u16 last_key;
u16 last_toggle; u16 last_toggle;
u8 delay_timer_finished; bool keypressed;
}; };
......
...@@ -84,15 +84,16 @@ static u16 default_key_map [256] = { ...@@ -84,15 +84,16 @@ static u16 default_key_map [256] = {
/* key-up timer */ /* key-up timer */
static void av7110_emit_keyup(unsigned long parm) static void av7110_emit_keyup(struct timer_list *t)
{ {
struct infrared *ir = (struct infrared *) parm; struct infrared *ir = from_timer(ir, t, keyup_timer);
if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) if (!ir || !ir->keypressed)
return; return;
input_report_key(ir->input_dev, ir->last_key, 0); input_report_key(ir->input_dev, ir->last_key, 0);
input_sync(ir->input_dev); input_sync(ir->input_dev);
ir->keypressed = false;
} }
...@@ -152,29 +153,18 @@ static void av7110_emit_key(unsigned long parm) ...@@ -152,29 +153,18 @@ static void av7110_emit_key(unsigned long parm)
return; return;
} }
if (timer_pending(&ir->keyup_timer)) { if (ir->keypressed &&
del_timer(&ir->keyup_timer); (ir->last_key != keycode || toggle != ir->last_toggle))
if (ir->last_key != keycode || toggle != ir->last_toggle) { input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
ir->delay_timer_finished = 0;
input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
input_event(ir->input_dev, EV_KEY, keycode, 1);
input_sync(ir->input_dev);
} else if (ir->delay_timer_finished) {
input_event(ir->input_dev, EV_KEY, keycode, 2);
input_sync(ir->input_dev);
}
} else {
ir->delay_timer_finished = 0;
input_event(ir->input_dev, EV_KEY, keycode, 1);
input_sync(ir->input_dev);
}
input_event(ir->input_dev, EV_KEY, keycode, 1);
input_sync(ir->input_dev);
ir->keypressed = true;
ir->last_key = keycode; ir->last_key = keycode;
ir->last_toggle = toggle; ir->last_toggle = toggle;
ir->keyup_timer.expires = jiffies + UP_TIMEOUT; mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT);
add_timer(&ir->keyup_timer);
} }
...@@ -204,16 +194,6 @@ static void input_register_keys(struct infrared *ir) ...@@ -204,16 +194,6 @@ static void input_register_keys(struct infrared *ir)
ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
} }
/* called by the input driver after rep[REP_DELAY] ms */
static void input_repeat_key(unsigned long parm)
{
struct infrared *ir = (struct infrared *) parm;
ir->delay_timer_finished = 1;
}
/* check for configuration changes */ /* check for configuration changes */
int av7110_check_ir_config(struct av7110 *av7110, int force) int av7110_check_ir_config(struct av7110 *av7110, int force)
{ {
...@@ -333,8 +313,7 @@ int av7110_ir_init(struct av7110 *av7110) ...@@ -333,8 +313,7 @@ int av7110_ir_init(struct av7110 *av7110)
av_list[av_cnt++] = av7110; av_list[av_cnt++] = av7110;
av7110_check_ir_config(av7110, true); av7110_check_ir_config(av7110, true);
setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup, timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0);
(unsigned long)&av7110->ir);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) if (!input_dev)
...@@ -365,8 +344,13 @@ int av7110_ir_init(struct av7110 *av7110) ...@@ -365,8 +344,13 @@ int av7110_ir_init(struct av7110 *av7110)
input_free_device(input_dev); input_free_device(input_dev);
return err; return err;
} }
input_dev->timer.function = input_repeat_key;
input_dev->timer.data = (unsigned long) &av7110->ir; /*
* Input core's default autorepeat is 33 cps with 250 msec
* delay, let's adjust to numbers more suitable for remote
* control.
*/
input_enable_softrepeat(input_dev, 250, 125);
if (av_cnt == 1) { if (av_cnt == 1) {
e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops); e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
......
/*
* Driver for simulating a mouse on GPIO lines.
*
* Copyright (C) 2007 Atmel Corporation
*
* 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.
*/
#ifndef _GPIO_MOUSE_H
#define _GPIO_MOUSE_H
#define GPIO_MOUSE_POLARITY_ACT_HIGH 0x00
#define GPIO_MOUSE_POLARITY_ACT_LOW 0x01
#define GPIO_MOUSE_PIN_UP 0
#define GPIO_MOUSE_PIN_DOWN 1
#define GPIO_MOUSE_PIN_LEFT 2
#define GPIO_MOUSE_PIN_RIGHT 3
#define GPIO_MOUSE_PIN_BLEFT 4
#define GPIO_MOUSE_PIN_BMIDDLE 5
#define GPIO_MOUSE_PIN_BRIGHT 6
#define GPIO_MOUSE_PIN_MAX 7
/**
* struct gpio_mouse_platform_data
* @scan_ms: integer in ms specifying the scan periode.
* @polarity: Pin polarity, active high or low.
* @up: GPIO line for up value.
* @down: GPIO line for down value.
* @left: GPIO line for left value.
* @right: GPIO line for right value.
* @bleft: GPIO line for left button.
* @bmiddle: GPIO line for middle button.
* @bright: GPIO line for right button.
*
* This struct must be added to the platform_device in the board code.
* It is used by the gpio_mouse driver to setup GPIO lines and to
* calculate mouse movement.
*/
struct gpio_mouse_platform_data {
int scan_ms;
int polarity;
union {
struct {
int up;
int down;
int left;
int right;
int bleft;
int bmiddle;
int bright;
};
int pins[GPIO_MOUSE_PIN_MAX];
};
};
#endif /* _GPIO_MOUSE_H */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_ST1232_PDATA_H
#define _LINUX_ST1232_PDATA_H
/*
* Optional platform data
*
* Use this if you want the driver to drive the reset pin.
*/
struct st1232_pdata {
int reset_gpio;
};
#endif
/*
* User level driver support for input subsystem
*
* Heavily based on evdev.c by Vojtech Pavlik
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
*
* Changes/Revisions:
* 0.5 08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
* Benjamin Tissoires <benjamin.tissoires@redhat.com>)
* - add UI_DEV_SETUP ioctl
* - add UI_ABS_SETUP ioctl
* - add UI_GET_VERSION ioctl
* 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
* - add UI_GET_SYSNAME ioctl
* 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
* - update ff support for the changes in kernel interface
* - add UINPUT_VERSION
* 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
* - added force feedback support
* - added UI_SET_PHYS
* 0.1 20/06/2002
* - first public version
*/
#ifndef __UINPUT_H_
#define __UINPUT_H_
#include <uapi/linux/uinput.h>
#define UINPUT_NAME "uinput"
#define UINPUT_BUFFER_SIZE 16
#define UINPUT_NUM_REQUESTS 16
enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
struct uinput_request {
unsigned int id;
unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
int retval;
struct completion done;
union {
unsigned int effect_id;
struct {
struct ff_effect *effect;
struct ff_effect *old;
} upload;
} u;
};
struct uinput_device {
struct input_dev *dev;
struct mutex mutex;
enum uinput_state state;
wait_queue_head_t waitq;
unsigned char ready;
unsigned char head;
unsigned char tail;
struct input_event buff[UINPUT_BUFFER_SIZE];
unsigned int ff_effects_max;
struct uinput_request *requests[UINPUT_NUM_REQUESTS];
wait_queue_head_t requests_waitq;
spinlock_t requests_lock;
};
#endif /* __UINPUT_H_ */
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