Commit 2d9f0d96 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Merge branch 'next' into for-linus

Prepare first set of updates for 3.9 merge window.
parents 9937c026 005a69d6
* Freescale i.MX Keypad Port(KPP) device tree bindings
The KPP is designed to interface with a keypad matrix with 2-point contact
or 3-point contact keys. The KPP is designed to simplify the software task
of scanning a keypad matrix. The KPP is capable of detecting, debouncing,
and decoding one or multiple keys pressed simultaneously on a keypad.
Required SoC Specific Properties:
- compatible: Should be "fsl,<soc>-kpp".
- reg: Physical base address of the KPP and length of memory mapped
region.
- interrupts: The KPP interrupt number to the CPU(s).
- clocks: The clock provided by the SoC to the KPP. Some SoCs use dummy
clock(The clock for the KPP is provided by the SoCs automatically).
Required Board Specific Properties:
- pinctrl-names: The definition can be found at
pinctrl/pinctrl-bindings.txt.
- pinctrl-0: The definition can be found at
pinctrl/pinctrl-bindings.txt.
- linux,keymap: The definition can be found at
bindings/input/matrix-keymap.txt.
Example:
kpp: kpp@73f94000 {
compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
reg = <0x73f94000 0x4000>;
interrupts = <60>;
clocks = <&clks 0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_kpp_1>;
linux,keymap = <0x00000067 /* KEY_UP */
0x0001006c /* KEY_DOWN */
0x00020072 /* KEY_VOLUMEDOWN */
0x00030066 /* KEY_HOME */
0x0100006a /* KEY_RIGHT */
0x01010069 /* KEY_LEFT */
0x0102001c /* KEY_ENTER */
0x01030073 /* KEY_VOLUMEUP */
0x02000040 /* KEY_F6 */
0x02010042 /* KEY_F8 */
0x02020043 /* KEY_F9 */
0x02030044 /* KEY_F10 */
0x0300003b /* KEY_F1 */
0x0301003c /* KEY_F2 */
0x0302003d /* KEY_F3 */
0x03030074>; /* KEY_POWER */
};
* Tegra keyboard controller * Tegra keyboard controller
The key controller has maximum 24 pins to make matrix keypad. Any pin
can be configured as row or column. The maximum column pin can be 8
and maximum row pins can be 16 for Tegra20/Tegra30.
Required properties: Required properties:
- compatible: "nvidia,tegra20-kbc" - compatible: "nvidia,tegra20-kbc"
- reg: Register base address of KBC.
- interrupts: Interrupt number for the KBC.
- nvidia,kbc-row-pins: The KBC pins which are configured as row. This is an
array of pin numbers which is used as rows.
- nvidia,kbc-col-pins: The KBC pins which are configured as column. This is an
array of pin numbers which is used as column.
- linux,keymap: The keymap for keys as described in the binding document
devicetree/bindings/input/matrix-keymap.txt.
Optional properties, in addition to those specified by the shared Optional properties, in addition to those specified by the shared
matrix-keyboard bindings: matrix-keyboard bindings:
...@@ -19,5 +30,16 @@ Example: ...@@ -19,5 +30,16 @@ Example:
keyboard: keyboard { keyboard: keyboard {
compatible = "nvidia,tegra20-kbc"; compatible = "nvidia,tegra20-kbc";
reg = <0x7000e200 0x100>; reg = <0x7000e200 0x100>;
interrupts = <0 85 0x04>;
nvidia,ghost-filter; nvidia,ghost-filter;
nvidia,debounce-delay-ms = <640>;
nvidia,kbc-row-pins = <0 1 2>; /* pin 0, 1, 2 as rows */
nvidia,kbc-col-pins = <11 12 13>; /* pin 11, 12, 13 as columns */
linux,keymap = <0x00000074
0x00010067
0x00020066
0x01010068
0x02000069
0x02010070
0x02020071>;
}; };
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
menu "Input device support" menu "Input device support"
depends on !S390 && !UML depends on !UML
config INPUT config INPUT
tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
......
...@@ -18,6 +18,7 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) ...@@ -18,6 +18,7 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
{ {
if (dev->absinfo && test_bit(src, dev->absbit)) { if (dev->absinfo && test_bit(src, dev->absbit)) {
dev->absinfo[dst] = dev->absinfo[src]; dev->absinfo[dst] = dev->absinfo[src];
dev->absinfo[dst].fuzz = 0;
dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
} }
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* the Free Software Foundation. * the Free Software Foundation.
*/ */
/* #define WK0701_DEBUG */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define RESERVE 20000 #define RESERVE 20000
#define SYNC_PULSE 1306000 #define SYNC_PULSE 1306000
...@@ -67,6 +67,7 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w) ...@@ -67,6 +67,7 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w)
{ {
int i; int i;
int val1, val2, val3, val4, val5, val6, val7, val8; int val1, val2, val3, val4, val5, val6, val7, val8;
int magic, magic_bit;
int crc1, crc2; int crc1, crc2;
for (crc1 = crc2 = i = 0; i < 10; i++) { for (crc1 = crc2 = i = 0; i < 10; i++) {
...@@ -102,17 +103,12 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w) ...@@ -102,17 +103,12 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w)
val8 = (w->buf[18] & 1) << 8 | (w->buf[19] << 4) | w->buf[20]; val8 = (w->buf[18] & 1) << 8 | (w->buf[19] << 4) | w->buf[20];
val8 *= (w->buf[18] & 2) - 1; /*sign */ val8 *= (w->buf[18] & 2) - 1; /*sign */
#ifdef WK0701_DEBUG magic = (w->buf[21] << 4) | w->buf[22];
{ magic_bit = (w->buf[24] & 8) >> 3;
int magic, magic_bit; pr_debug("%4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n",
magic = (w->buf[21] << 4) | w->buf[22]; val1, val2, val3, val4, val5, val6, val7, val8,
magic_bit = (w->buf[24] & 8) >> 3; magic, magic_bit);
printk(KERN_DEBUG
"walkera0701: %4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n",
val1, val2, val3, val4, val5, val6, val7, val8, magic,
magic_bit);
}
#endif
input_report_abs(w->input_dev, ABS_X, val2); input_report_abs(w->input_dev, ABS_X, val2);
input_report_abs(w->input_dev, ABS_Y, val1); input_report_abs(w->input_dev, ABS_Y, val1);
input_report_abs(w->input_dev, ABS_Z, val6); input_report_abs(w->input_dev, ABS_Z, val6);
...@@ -187,6 +183,9 @@ static int walkera0701_open(struct input_dev *dev) ...@@ -187,6 +183,9 @@ static int walkera0701_open(struct input_dev *dev)
{ {
struct walkera_dev *w = input_get_drvdata(dev); struct walkera_dev *w = input_get_drvdata(dev);
if (parport_claim(w->pardevice))
return -EBUSY;
parport_enable_irq(w->parport); parport_enable_irq(w->parport);
return 0; return 0;
} }
...@@ -197,40 +196,51 @@ static void walkera0701_close(struct input_dev *dev) ...@@ -197,40 +196,51 @@ static void walkera0701_close(struct input_dev *dev)
parport_disable_irq(w->parport); parport_disable_irq(w->parport);
hrtimer_cancel(&w->timer); hrtimer_cancel(&w->timer);
parport_release(w->pardevice);
} }
static int walkera0701_connect(struct walkera_dev *w, int parport) static int walkera0701_connect(struct walkera_dev *w, int parport)
{ {
int err = -ENODEV; int error;
w->parport = parport_find_number(parport); w->parport = parport_find_number(parport);
if (w->parport == NULL) if (!w->parport) {
pr_err("parport %d does not exist\n", parport);
return -ENODEV; return -ENODEV;
}
if (w->parport->irq == -1) { if (w->parport->irq == -1) {
printk(KERN_ERR "walkera0701: parport without interrupt\n"); pr_err("parport %d does not have interrupt assigned\n",
goto init_err; parport);
error = -EINVAL;
goto err_put_parport;
} }
err = -EBUSY;
w->pardevice = parport_register_device(w->parport, "walkera0701", w->pardevice = parport_register_device(w->parport, "walkera0701",
NULL, NULL, walkera0701_irq_handler, NULL, NULL, walkera0701_irq_handler,
PARPORT_DEV_EXCL, w); PARPORT_DEV_EXCL, w);
if (!w->pardevice) if (!w->pardevice) {
goto init_err; pr_err("failed to register parport device\n");
error = -EIO;
if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) goto err_put_parport;
goto init_err1; }
if (parport_claim(w->pardevice)) if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) {
goto init_err1; pr_err("failed to negotiate parport mode\n");
error = -EIO;
goto err_unregister_device;
}
hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
w->timer.function = timer_handler; w->timer.function = timer_handler;
w->input_dev = input_allocate_device(); w->input_dev = input_allocate_device();
if (!w->input_dev) if (!w->input_dev) {
goto init_err2; pr_err("failed to allocate input device\n");
error = -ENOMEM;
goto err_unregister_device;
}
input_set_drvdata(w->input_dev, w); input_set_drvdata(w->input_dev, w);
w->input_dev->name = "Walkera WK-0701 TX"; w->input_dev->name = "Walkera WK-0701 TX";
...@@ -241,6 +251,7 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) ...@@ -241,6 +251,7 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
w->input_dev->id.vendor = 0x0001; w->input_dev->id.vendor = 0x0001;
w->input_dev->id.product = 0x0001; w->input_dev->id.product = 0x0001;
w->input_dev->id.version = 0x0100; w->input_dev->id.version = 0x0100;
w->input_dev->dev.parent = w->parport->dev;
w->input_dev->open = walkera0701_open; w->input_dev->open = walkera0701_open;
w->input_dev->close = walkera0701_close; w->input_dev->close = walkera0701_close;
...@@ -254,27 +265,26 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) ...@@ -254,27 +265,26 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0); input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0); input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
err = input_register_device(w->input_dev); error = input_register_device(w->input_dev);
if (err) if (error) {
goto init_err3; pr_err("failed to register input device\n");
goto err_free_input_dev;
}
return 0; return 0;
init_err3: err_free_input_dev:
input_free_device(w->input_dev); input_free_device(w->input_dev);
init_err2: err_unregister_device:
parport_release(w->pardevice);
init_err1:
parport_unregister_device(w->pardevice); parport_unregister_device(w->pardevice);
init_err: err_put_parport:
parport_put_port(w->parport); parport_put_port(w->parport);
return err; return error;
} }
static void walkera0701_disconnect(struct walkera_dev *w) static void walkera0701_disconnect(struct walkera_dev *w)
{ {
input_unregister_device(w->input_dev); input_unregister_device(w->input_dev);
parport_release(w->pardevice);
parport_unregister_device(w->pardevice); parport_unregister_device(w->pardevice);
parport_put_port(w->parport); parport_put_port(w->parport);
} }
......
...@@ -224,7 +224,7 @@ config KEYBOARD_TCA6416 ...@@ -224,7 +224,7 @@ config KEYBOARD_TCA6416
config KEYBOARD_TCA8418 config KEYBOARD_TCA8418
tristate "TCA8418 Keypad Support" tristate "TCA8418 Keypad Support"
depends on I2C depends on I2C && GENERIC_HARDIRQS
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
help help
This driver implements basic keypad functionality This driver implements basic keypad functionality
...@@ -303,7 +303,7 @@ config KEYBOARD_HP7XX ...@@ -303,7 +303,7 @@ config KEYBOARD_HP7XX
config KEYBOARD_LM8323 config KEYBOARD_LM8323
tristate "LM8323 keypad chip" tristate "LM8323 keypad chip"
depends on I2C depends on I2C && GENERIC_HARDIRQS
depends on LEDS_CLASS depends on LEDS_CLASS
help help
If you say yes here you get support for the National Semiconductor If you say yes here you get support for the National Semiconductor
...@@ -420,7 +420,7 @@ config KEYBOARD_NOMADIK ...@@ -420,7 +420,7 @@ config KEYBOARD_NOMADIK
config KEYBOARD_TEGRA config KEYBOARD_TEGRA
tristate "NVIDIA Tegra internal matrix keyboard controller support" tristate "NVIDIA Tegra internal matrix keyboard controller support"
depends on ARCH_TEGRA depends on ARCH_TEGRA && OF
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
help help
Say Y here if you want to use a matrix keyboard connected directly Say Y here if you want to use a matrix keyboard connected directly
...@@ -479,6 +479,16 @@ config KEYBOARD_SAMSUNG ...@@ -479,6 +479,16 @@ config KEYBOARD_SAMSUNG
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 samsung-keypad. module will be called samsung-keypad.
config KEYBOARD_GOLDFISH_EVENTS
depends on GOLDFISH
tristate "Generic Input Event device for Goldfish"
help
Say Y here to get an input event device for the Goldfish virtual
device emulator.
To compile this driver as a module, choose M here: the
module will be called goldfish-events.
config KEYBOARD_STOWAWAY config KEYBOARD_STOWAWAY
tristate "Stowaway keyboard" tristate "Stowaway keyboard"
select SERIO select SERIO
......
...@@ -13,6 +13,7 @@ obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
......
...@@ -676,6 +676,39 @@ static inline void atkbd_disable(struct atkbd *atkbd) ...@@ -676,6 +676,39 @@ static inline void atkbd_disable(struct atkbd *atkbd)
serio_continue_rx(atkbd->ps2dev.serio); serio_continue_rx(atkbd->ps2dev.serio);
} }
static int atkbd_activate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
/*
* Enable the keyboard to receive keystrokes.
*/
if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
dev_err(&ps2dev->serio->dev,
"Failed to enable keyboard on %s\n",
ps2dev->serio->phys);
return -1;
}
return 0;
}
/*
* atkbd_deactivate() resets and disables the keyboard from sending
* keystrokes.
*/
static void atkbd_deactivate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_DIS))
dev_err(&ps2dev->serio->dev,
"Failed to deactivate keyboard on %s\n",
ps2dev->serio->phys);
}
/* /*
* atkbd_probe() probes for an AT keyboard on a serio port. * atkbd_probe() probes for an AT keyboard on a serio port.
*/ */
...@@ -726,11 +759,17 @@ static int atkbd_probe(struct atkbd *atkbd) ...@@ -726,11 +759,17 @@ static int atkbd_probe(struct atkbd *atkbd)
if (atkbd->id == 0xaca1 && atkbd->translated) { if (atkbd->id == 0xaca1 && atkbd->translated) {
dev_err(&ps2dev->serio->dev, dev_err(&ps2dev->serio->dev,
"NCD terminal keyboards are only supported on non-translating controlelrs. " "NCD terminal keyboards are only supported on non-translating controllers. "
"Use i8042.direct=1 to disable translation.\n"); "Use i8042.direct=1 to disable translation.\n");
return -1; return -1;
} }
/*
* Make sure nothing is coming from the keyboard and disturbs our
* internal state.
*/
atkbd_deactivate(atkbd);
return 0; return 0;
} }
...@@ -825,24 +864,6 @@ static int atkbd_reset_state(struct atkbd *atkbd) ...@@ -825,24 +864,6 @@ static int atkbd_reset_state(struct atkbd *atkbd)
return 0; return 0;
} }
static int atkbd_activate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
/*
* Enable the keyboard to receive keystrokes.
*/
if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
dev_err(&ps2dev->serio->dev,
"Failed to enable keyboard on %s\n",
ps2dev->serio->phys);
return -1;
}
return 0;
}
/* /*
* atkbd_cleanup() restores the keyboard state so that BIOS is happy after a * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
* reboot. * reboot.
...@@ -1150,7 +1171,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1150,7 +1171,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
atkbd_reset_state(atkbd); atkbd_reset_state(atkbd);
atkbd_activate(atkbd);
} else { } else {
atkbd->set = 2; atkbd->set = 2;
...@@ -1165,6 +1185,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1165,6 +1185,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
goto fail3; goto fail3;
atkbd_enable(atkbd); atkbd_enable(atkbd);
if (serio->write)
atkbd_activate(atkbd);
err = input_register_device(atkbd->dev); err = input_register_device(atkbd->dev);
if (err) if (err)
...@@ -1208,8 +1230,6 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -1208,8 +1230,6 @@ static int atkbd_reconnect(struct serio *serio)
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
goto out; goto out;
atkbd_activate(atkbd);
/* /*
* Restore LED state and repeat rate. While input core * Restore LED state and repeat rate. While input core
* will do this for us at resume time reconnect may happen * will do this for us at resume time reconnect may happen
...@@ -1223,7 +1243,17 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -1223,7 +1243,17 @@ static int atkbd_reconnect(struct serio *serio)
} }
/*
* Reset our state machine in case reconnect happened in the middle
* of multi-byte scancode.
*/
atkbd->xl_bit = 0;
atkbd->emul = 0;
atkbd_enable(atkbd); atkbd_enable(atkbd);
if (atkbd->write)
atkbd_activate(atkbd);
retval = 0; retval = 0;
out: out:
......
/*
* Copyright (C) 2007 Google, Inc.
* Copyright (C) 2012 Intel, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/io.h>
enum {
REG_READ = 0x00,
REG_SET_PAGE = 0x00,
REG_LEN = 0x04,
REG_DATA = 0x08,
PAGE_NAME = 0x00000,
PAGE_EVBITS = 0x10000,
PAGE_ABSDATA = 0x20000 | EV_ABS,
};
struct event_dev {
struct input_dev *input;
int irq;
void __iomem *addr;
char name[0];
};
static irqreturn_t events_interrupt(int irq, void *dev_id)
{
struct event_dev *edev = dev_id;
unsigned type, code, value;
type = __raw_readl(edev->addr + REG_READ);
code = __raw_readl(edev->addr + REG_READ);
value = __raw_readl(edev->addr + REG_READ);
input_event(edev->input, type, code, value);
input_sync(edev->input);
return IRQ_HANDLED;
}
static void events_import_bits(struct event_dev *edev,
unsigned long bits[], unsigned type, size_t count)
{
void __iomem *addr = edev->addr;
int i, j;
size_t size;
uint8_t val;
__raw_writel(PAGE_EVBITS | type, addr + REG_SET_PAGE);
size = __raw_readl(addr + REG_LEN) * 8;
if (size < count)
count = size;
addr += REG_DATA;
for (i = 0; i < count; i += 8) {
val = __raw_readb(addr++);
for (j = 0; j < 8; j++)
if (val & 1 << j)
set_bit(i + j, bits);
}
}
static void events_import_abs_params(struct event_dev *edev)
{
struct input_dev *input_dev = edev->input;
void __iomem *addr = edev->addr;
u32 val[4];
int count;
int i, j;
__raw_writel(PAGE_ABSDATA, addr + REG_SET_PAGE);
count = __raw_readl(addr + REG_LEN) / sizeof(val);
if (count > ABS_MAX)
count = ABS_MAX;
for (i = 0; i < count; i++) {
if (!test_bit(i, input_dev->absbit))
continue;
for (j = 0; j < ARRAY_SIZE(val); j++) {
int offset = (i * ARRAY_SIZE(val) + j) * sizeof(u32);
val[j] = __raw_readl(edev->addr + REG_DATA + offset);
}
input_set_abs_params(input_dev, i,
val[0], val[1], val[2], val[3]);
}
}
static int events_probe(struct platform_device *pdev)
{
struct input_dev *input_dev;
struct event_dev *edev;
struct resource *res;
unsigned keymapnamelen;
void __iomem *addr;
int irq;
int i;
int error;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
addr = devm_ioremap(&pdev->dev, res->start, 4096);
if (!addr)
return -ENOMEM;
__raw_writel(PAGE_NAME, addr + REG_SET_PAGE);
keymapnamelen = __raw_readl(addr + REG_LEN);
edev = devm_kzalloc(&pdev->dev,
sizeof(struct event_dev) + keymapnamelen + 1,
GFP_KERNEL);
if (!edev)
return -ENOMEM;
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
edev->input = input_dev;
edev->addr = addr;
edev->irq = irq;
for (i = 0; i < keymapnamelen; i++)
edev->name[i] = __raw_readb(edev->addr + REG_DATA + i);
pr_debug("events_probe() keymap=%s\n", edev->name);
input_dev->name = edev->name;
input_dev->id.bustype = BUS_HOST;
events_import_bits(edev, input_dev->evbit, EV_SYN, EV_MAX);
events_import_bits(edev, input_dev->keybit, EV_KEY, KEY_MAX);
events_import_bits(edev, input_dev->relbit, EV_REL, REL_MAX);
events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX);
events_import_bits(edev, input_dev->mscbit, EV_MSC, MSC_MAX);
events_import_bits(edev, input_dev->ledbit, EV_LED, LED_MAX);
events_import_bits(edev, input_dev->sndbit, EV_SND, SND_MAX);
events_import_bits(edev, input_dev->ffbit, EV_FF, FF_MAX);
events_import_bits(edev, input_dev->swbit, EV_SW, SW_MAX);
events_import_abs_params(edev);
error = devm_request_irq(&pdev->dev, edev->irq, events_interrupt, 0,
"goldfish-events-keypad", edev);
if (error)
return error;
error = input_register_device(input_dev);
if (error)
return error;
return 0;
}
static struct platform_driver events_driver = {
.probe = events_probe,
.driver = {
.owner = THIS_MODULE,
.name = "goldfish_events",
},
};
module_platform_driver(events_driver);
MODULE_AUTHOR("Brian Swetland");
MODULE_DESCRIPTION("Goldfish Event Device");
MODULE_LICENSE("GPL");
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -414,15 +415,23 @@ static int imx_keypad_open(struct input_dev *dev) ...@@ -414,15 +415,23 @@ static int imx_keypad_open(struct input_dev *dev)
return -EIO; return -EIO;
} }
#ifdef CONFIG_OF
static struct of_device_id imx_keypad_of_match[] = {
{ .compatible = "fsl,imx21-kpp", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
#endif
static int imx_keypad_probe(struct platform_device *pdev) static int imx_keypad_probe(struct platform_device *pdev)
{ {
const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
struct imx_keypad *keypad; struct imx_keypad *keypad;
struct input_dev *input_dev; struct input_dev *input_dev;
struct resource *res; struct resource *res;
int irq, error, i; int irq, error, i, row, col;
if (keymap_data == NULL) { if (!keymap_data && !pdev->dev.of_node) {
dev_err(&pdev->dev, "no keymap defined\n"); dev_err(&pdev->dev, "no keymap defined\n");
return -EINVAL; return -EINVAL;
} }
...@@ -480,22 +489,6 @@ static int imx_keypad_probe(struct platform_device *pdev) ...@@ -480,22 +489,6 @@ static int imx_keypad_probe(struct platform_device *pdev)
goto failed_unmap; goto failed_unmap;
} }
/* Search for rows and cols enabled */
for (i = 0; i < keymap_data->keymap_size; i++) {
keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]);
keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]);
}
if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) ||
keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
dev_err(&pdev->dev,
"invalid key data (too many rows or colums)\n");
error = -EINVAL;
goto failed_clock_put;
}
dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
/* Init the Input device */ /* Init the Input device */
input_dev->name = pdev->name; input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST; input_dev->id.bustype = BUS_HOST;
...@@ -512,6 +505,19 @@ static int imx_keypad_probe(struct platform_device *pdev) ...@@ -512,6 +505,19 @@ static int imx_keypad_probe(struct platform_device *pdev)
goto failed_clock_put; goto failed_clock_put;
} }
/* Search for rows and cols enabled */
for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
if (keypad->keycodes[i] != KEY_RESERVED) {
keypad->rows_en_mask |= 1 << row;
keypad->cols_en_mask |= 1 << col;
}
}
}
dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
__set_bit(EV_REP, input_dev->evbit); __set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad); input_set_drvdata(input_dev, keypad);
...@@ -631,6 +637,7 @@ static struct platform_driver imx_keypad_driver = { ...@@ -631,6 +637,7 @@ static struct platform_driver imx_keypad_driver = {
.name = "imx-keypad", .name = "imx-keypad",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &imx_kbd_pm_ops, .pm = &imx_kbd_pm_ops,
.of_match_table = of_match_ptr(imx_keypad_of_match),
}, },
.probe = imx_keypad_probe, .probe = imx_keypad_probe,
.remove = imx_keypad_remove, .remove = imx_keypad_remove,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/leds.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
...@@ -39,6 +40,11 @@ ...@@ -39,6 +40,11 @@
#define QT2160_CMD_GPIOS 6 #define QT2160_CMD_GPIOS 6
#define QT2160_CMD_SUBVER 7 #define QT2160_CMD_SUBVER 7
#define QT2160_CMD_CALIBRATE 10 #define QT2160_CMD_CALIBRATE 10
#define QT2160_CMD_DRIVE_X 70
#define QT2160_CMD_PWMEN_X 74
#define QT2160_CMD_PWM_DUTY 76
#define QT2160_NUM_LEDS_X 8
#define QT2160_CYCLE_INTERVAL (2*HZ) #define QT2160_CYCLE_INTERVAL (2*HZ)
...@@ -49,6 +55,17 @@ static unsigned char qt2160_key2code[] = { ...@@ -49,6 +55,17 @@ static unsigned char qt2160_key2code[] = {
KEY_C, KEY_D, KEY_E, KEY_F, KEY_C, KEY_D, KEY_E, KEY_F,
}; };
#ifdef CONFIG_LEDS_CLASS
struct qt2160_led {
struct qt2160_data *qt2160;
struct led_classdev cdev;
struct work_struct work;
char name[32];
int id;
enum led_brightness new_brightness;
};
#endif
struct qt2160_data { struct qt2160_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
...@@ -56,8 +73,61 @@ struct qt2160_data { ...@@ -56,8 +73,61 @@ struct qt2160_data {
spinlock_t lock; /* Protects canceling/rescheduling of dwork */ spinlock_t lock; /* Protects canceling/rescheduling of dwork */
unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
u16 key_matrix; u16 key_matrix;
#ifdef CONFIG_LEDS_CLASS
struct qt2160_led leds[QT2160_NUM_LEDS_X];
struct mutex led_lock;
#endif
}; };
static int qt2160_read(struct i2c_client *client, u8 reg);
static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
#ifdef CONFIG_LEDS_CLASS
static void qt2160_led_work(struct work_struct *work)
{
struct qt2160_led *led = container_of(work, struct qt2160_led, work);
struct qt2160_data *qt2160 = led->qt2160;
struct i2c_client *client = qt2160->client;
int value = led->new_brightness;
u32 drive, pwmen;
mutex_lock(&qt2160->led_lock);
drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
if (value != LED_OFF) {
drive |= (1 << led->id);
pwmen |= (1 << led->id);
} else {
drive &= ~(1 << led->id);
pwmen &= ~(1 << led->id);
}
qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
/*
* Changing this register will change the brightness
* of every LED in the qt2160. It's a HW limitation.
*/
if (value != LED_OFF)
qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
mutex_unlock(&qt2160->led_lock);
}
static void qt2160_led_set(struct led_classdev *cdev,
enum led_brightness value)
{
struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
led->new_brightness = value;
schedule_work(&led->work);
}
#endif /* CONFIG_LEDS_CLASS */
static int qt2160_read_block(struct i2c_client *client, static int qt2160_read_block(struct i2c_client *client,
u8 inireg, u8 *buffer, unsigned int count) u8 inireg, u8 *buffer, unsigned int count)
{ {
...@@ -216,6 +286,63 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) ...@@ -216,6 +286,63 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
return ret; return ret;
} }
#ifdef CONFIG_LEDS_CLASS
static int qt2160_register_leds(struct qt2160_data *qt2160)
{
struct i2c_client *client = qt2160->client;
int ret;
int i;
mutex_init(&qt2160->led_lock);
for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
struct qt2160_led *led = &qt2160->leds[i];
snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
led->cdev.name = led->name;
led->cdev.brightness_set = qt2160_led_set;
led->cdev.brightness = LED_OFF;
led->id = i;
led->qt2160 = qt2160;
INIT_WORK(&led->work, qt2160_led_work);
ret = led_classdev_register(&client->dev, &led->cdev);
if (ret < 0)
return ret;
}
/* Tur off LEDs */
qt2160_write(client, QT2160_CMD_DRIVE_X, 0);
qt2160_write(client, QT2160_CMD_PWMEN_X, 0);
qt2160_write(client, QT2160_CMD_PWM_DUTY, 0);
return 0;
}
static void qt2160_unregister_leds(struct qt2160_data *qt2160)
{
int i;
for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
led_classdev_unregister(&qt2160->leds[i].cdev);
cancel_work_sync(&qt2160->leds[i].work);
}
}
#else
static inline int qt2160_register_leds(struct qt2160_data *qt2160)
{
return 0;
}
static inline void qt2160_unregister_leds(struct qt2160_data *qt2160)
{
}
#endif
static bool qt2160_identify(struct i2c_client *client) static bool qt2160_identify(struct i2c_client *client)
{ {
...@@ -249,7 +376,7 @@ static bool qt2160_identify(struct i2c_client *client) ...@@ -249,7 +376,7 @@ static bool qt2160_identify(struct i2c_client *client)
} }
static int qt2160_probe(struct i2c_client *client, static int qt2160_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct qt2160_data *qt2160; struct qt2160_data *qt2160;
struct input_dev *input; struct input_dev *input;
...@@ -314,11 +441,17 @@ static int qt2160_probe(struct i2c_client *client, ...@@ -314,11 +441,17 @@ static int qt2160_probe(struct i2c_client *client,
} }
} }
error = qt2160_register_leds(qt2160);
if (error) {
dev_err(&client->dev, "Failed to register leds\n");
goto err_free_irq;
}
error = input_register_device(qt2160->input); error = input_register_device(qt2160->input);
if (error) { if (error) {
dev_err(&client->dev, dev_err(&client->dev,
"Failed to register input device\n"); "Failed to register input device\n");
goto err_free_irq; goto err_unregister_leds;
} }
i2c_set_clientdata(client, qt2160); i2c_set_clientdata(client, qt2160);
...@@ -326,6 +459,8 @@ static int qt2160_probe(struct i2c_client *client, ...@@ -326,6 +459,8 @@ static int qt2160_probe(struct i2c_client *client,
return 0; return 0;
err_unregister_leds:
qt2160_unregister_leds(qt2160);
err_free_irq: err_free_irq:
if (client->irq) if (client->irq)
free_irq(client->irq, qt2160); free_irq(client->irq, qt2160);
...@@ -339,6 +474,8 @@ static int qt2160_remove(struct i2c_client *client) ...@@ -339,6 +474,8 @@ static int qt2160_remove(struct i2c_client *client)
{ {
struct qt2160_data *qt2160 = i2c_get_clientdata(client); struct qt2160_data *qt2160 = i2c_get_clientdata(client);
qt2160_unregister_leds(qt2160);
/* Release IRQ so no queue will be scheduled */ /* Release IRQ so no queue will be scheduled */
if (client->irq) if (client->irq)
free_irq(client->irq, qt2160); free_irq(client->irq, qt2160);
......
This diff is collapsed.
...@@ -232,7 +232,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = { ...@@ -232,7 +232,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = {
.ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY {x,y,z} */ .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY {x,y,z} */
.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK, .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
.fifo_mode = FIFO_STREAM, .fifo_mode = ADXL_FIFO_STREAM,
.watermark = 0, .watermark = 0,
}; };
...@@ -732,7 +732,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ...@@ -732,7 +732,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
mutex_init(&ac->mutex); mutex_init(&ac->mutex);
input_dev->name = "ADXL34x accelerometer"; input_dev->name = "ADXL34x accelerometer";
revid = ac->bops->read(dev, DEVID); revid = AC_READ(ac, DEVID);
switch (revid) { switch (revid) {
case ID_ADXL345: case ID_ADXL345:
...@@ -809,7 +809,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ...@@ -809,7 +809,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS)
ac->fifo_delay = false; ac->fifo_delay = false;
ac->bops->write(dev, POWER_CTL, 0); AC_WRITE(ac, POWER_CTL, 0);
err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
...@@ -827,7 +827,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ...@@ -827,7 +827,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
if (err) if (err)
goto err_remove_attr; goto err_remove_attr;
AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold);
AC_WRITE(ac, OFSX, pdata->x_axis_offset); AC_WRITE(ac, OFSX, pdata->x_axis_offset);
ac->hwcal.x = pdata->x_axis_offset; ac->hwcal.x = pdata->x_axis_offset;
AC_WRITE(ac, OFSY, pdata->y_axis_offset); AC_WRITE(ac, OFSY, pdata->y_axis_offset);
......
...@@ -46,18 +46,6 @@ ...@@ -46,18 +46,6 @@
#define BMA150_POLL_MAX 200 #define BMA150_POLL_MAX 200
#define BMA150_POLL_MIN 0 #define BMA150_POLL_MIN 0
#define BMA150_BW_25HZ 0
#define BMA150_BW_50HZ 1
#define BMA150_BW_100HZ 2
#define BMA150_BW_190HZ 3
#define BMA150_BW_375HZ 4
#define BMA150_BW_750HZ 5
#define BMA150_BW_1500HZ 6
#define BMA150_RANGE_2G 0
#define BMA150_RANGE_4G 1
#define BMA150_RANGE_8G 2
#define BMA150_MODE_NORMAL 0 #define BMA150_MODE_NORMAL 0
#define BMA150_MODE_SLEEP 2 #define BMA150_MODE_SLEEP 2
#define BMA150_MODE_WAKE_UP 3 #define BMA150_MODE_WAKE_UP 3
...@@ -372,7 +360,7 @@ static int bma150_open(struct bma150_data *bma150) ...@@ -372,7 +360,7 @@ static int bma150_open(struct bma150_data *bma150)
int error; int error;
error = pm_runtime_get_sync(&bma150->client->dev); error = pm_runtime_get_sync(&bma150->client->dev);
if (error && error != -ENOSYS) if (error < 0 && error != -ENOSYS)
return error; return error;
/* /*
......
...@@ -43,7 +43,6 @@ struct vibra_info { ...@@ -43,7 +43,6 @@ struct vibra_info {
struct device *dev; struct device *dev;
struct input_dev *input_dev; struct input_dev *input_dev;
struct workqueue_struct *workqueue;
struct work_struct play_work; struct work_struct play_work;
bool enabled; bool enabled;
...@@ -143,19 +142,7 @@ static int vibra_play(struct input_dev *input, void *data, ...@@ -143,19 +142,7 @@ static int vibra_play(struct input_dev *input, void *data,
if (!info->speed) if (!info->speed)
info->speed = effect->u.rumble.weak_magnitude >> 9; info->speed = effect->u.rumble.weak_magnitude >> 9;
info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1;
queue_work(info->workqueue, &info->play_work); schedule_work(&info->play_work);
return 0;
}
static int twl4030_vibra_open(struct input_dev *input)
{
struct vibra_info *info = input_get_drvdata(input);
info->workqueue = create_singlethread_workqueue("vibra");
if (info->workqueue == NULL) {
dev_err(&input->dev, "couldn't create workqueue\n");
return -ENOMEM;
}
return 0; return 0;
} }
...@@ -164,9 +151,6 @@ static void twl4030_vibra_close(struct input_dev *input) ...@@ -164,9 +151,6 @@ static void twl4030_vibra_close(struct input_dev *input)
struct vibra_info *info = input_get_drvdata(input); struct vibra_info *info = input_get_drvdata(input);
cancel_work_sync(&info->play_work); cancel_work_sync(&info->play_work);
INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */
destroy_workqueue(info->workqueue);
info->workqueue = NULL;
if (info->enabled) if (info->enabled)
vibra_disable(info); vibra_disable(info);
...@@ -219,7 +203,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev) ...@@ -219,7 +203,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
info = kzalloc(sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
...@@ -227,11 +211,10 @@ static int twl4030_vibra_probe(struct platform_device *pdev) ...@@ -227,11 +211,10 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node); info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
INIT_WORK(&info->play_work, vibra_play_work); INIT_WORK(&info->play_work, vibra_play_work);
info->input_dev = input_allocate_device(); info->input_dev = devm_input_allocate_device(&pdev->dev);
if (info->input_dev == NULL) { if (info->input_dev == NULL) {
dev_err(&pdev->dev, "couldn't allocate input device\n"); dev_err(&pdev->dev, "couldn't allocate input device\n");
ret = -ENOMEM; return -ENOMEM;
goto err_kzalloc;
} }
input_set_drvdata(info->input_dev, info); input_set_drvdata(info->input_dev, info);
...@@ -239,14 +222,13 @@ static int twl4030_vibra_probe(struct platform_device *pdev) ...@@ -239,14 +222,13 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
info->input_dev->name = "twl4030:vibrator"; info->input_dev->name = "twl4030:vibrator";
info->input_dev->id.version = 1; info->input_dev->id.version = 1;
info->input_dev->dev.parent = pdev->dev.parent; info->input_dev->dev.parent = pdev->dev.parent;
info->input_dev->open = twl4030_vibra_open;
info->input_dev->close = twl4030_vibra_close; info->input_dev->close = twl4030_vibra_close;
__set_bit(FF_RUMBLE, info->input_dev->ffbit); __set_bit(FF_RUMBLE, info->input_dev->ffbit);
ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
if (ret < 0) { if (ret < 0) {
dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n");
goto err_ialloc; return ret;
} }
ret = input_register_device(info->input_dev); ret = input_register_device(info->input_dev);
...@@ -262,28 +244,11 @@ static int twl4030_vibra_probe(struct platform_device *pdev) ...@@ -262,28 +244,11 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
err_iff: err_iff:
input_ff_destroy(info->input_dev); input_ff_destroy(info->input_dev);
err_ialloc:
input_free_device(info->input_dev);
err_kzalloc:
kfree(info);
return ret; return ret;
} }
static int twl4030_vibra_remove(struct platform_device *pdev)
{
struct vibra_info *info = platform_get_drvdata(pdev);
/* this also free ff-memless and calls close if needed */
input_unregister_device(info->input_dev);
kfree(info);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver twl4030_vibra_driver = { static struct platform_driver twl4030_vibra_driver = {
.probe = twl4030_vibra_probe, .probe = twl4030_vibra_probe,
.remove = twl4030_vibra_remove,
.driver = { .driver = {
.name = "twl4030-vibra", .name = "twl4030-vibra",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -275,7 +275,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -275,7 +275,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
info = kzalloc(sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) { if (!info) {
dev_err(&pdev->dev, "couldn't allocate memory\n"); dev_err(&pdev->dev, "couldn't allocate memory\n");
return -ENOMEM; return -ENOMEM;
...@@ -309,53 +309,23 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -309,53 +309,23 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
if ((!info->vibldrv_res && !info->viblmotor_res) || if ((!info->vibldrv_res && !info->viblmotor_res) ||
(!info->vibrdrv_res && !info->vibrmotor_res)) { (!info->vibrdrv_res && !info->vibrmotor_res)) {
dev_err(info->dev, "invalid vibra driver/motor resistance\n"); dev_err(info->dev, "invalid vibra driver/motor resistance\n");
ret = -EINVAL; return -EINVAL;
goto err_kzalloc;
} }
info->irq = platform_get_irq(pdev, 0); info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) { if (info->irq < 0) {
dev_err(info->dev, "invalid irq\n"); dev_err(info->dev, "invalid irq\n");
ret = -EINVAL; return -EINVAL;
goto err_kzalloc;
} }
mutex_init(&info->mutex); mutex_init(&info->mutex);
info->input_dev = input_allocate_device(); ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
if (info->input_dev == NULL) { twl6040_vib_irq_handler, 0,
dev_err(info->dev, "couldn't allocate input device\n"); "twl6040_irq_vib", info);
ret = -ENOMEM;
goto err_kzalloc;
}
input_set_drvdata(info->input_dev, info);
info->input_dev->name = "twl6040:vibrator";
info->input_dev->id.version = 1;
info->input_dev->dev.parent = pdev->dev.parent;
info->input_dev->close = twl6040_vibra_close;
__set_bit(FF_RUMBLE, info->input_dev->ffbit);
ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
if (ret < 0) {
dev_err(info->dev, "couldn't register vibrator to FF\n");
goto err_ialloc;
}
ret = input_register_device(info->input_dev);
if (ret < 0) {
dev_err(info->dev, "couldn't register input device\n");
goto err_iff;
}
platform_set_drvdata(pdev, info);
ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
"twl6040_irq_vib", info);
if (ret) { if (ret) {
dev_err(info->dev, "VIB IRQ request failed: %d\n", ret); dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
goto err_irq; return ret;
} }
info->supplies[0].supply = "vddvibl"; info->supplies[0].supply = "vddvibl";
...@@ -368,7 +338,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -368,7 +338,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
ARRAY_SIZE(info->supplies), info->supplies); ARRAY_SIZE(info->supplies), info->supplies);
if (ret) { if (ret) {
dev_err(info->dev, "couldn't get regulators %d\n", ret); dev_err(info->dev, "couldn't get regulators %d\n", ret);
goto err_regulator; return ret;
} }
if (vddvibl_uV) { if (vddvibl_uV) {
...@@ -377,7 +347,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -377,7 +347,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(info->dev, "failed to set VDDVIBL volt %d\n", dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
ret); ret);
goto err_voltage; goto err_regulator;
} }
} }
...@@ -387,34 +357,49 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -387,34 +357,49 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(info->dev, "failed to set VDDVIBR volt %d\n", dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
ret); ret);
goto err_voltage; goto err_regulator;
} }
} }
info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0); INIT_WORK(&info->play_work, vibra_play_work);
if (info->workqueue == NULL) {
dev_err(info->dev, "couldn't create workqueue\n"); info->input_dev = input_allocate_device();
if (info->input_dev == NULL) {
dev_err(info->dev, "couldn't allocate input device\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_voltage; goto err_regulator;
} }
INIT_WORK(&info->play_work, vibra_play_work);
input_set_drvdata(info->input_dev, info);
info->input_dev->name = "twl6040:vibrator";
info->input_dev->id.version = 1;
info->input_dev->dev.parent = pdev->dev.parent;
info->input_dev->close = twl6040_vibra_close;
__set_bit(FF_RUMBLE, info->input_dev->ffbit);
ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
if (ret < 0) {
dev_err(info->dev, "couldn't register vibrator to FF\n");
goto err_ialloc;
}
ret = input_register_device(info->input_dev);
if (ret < 0) {
dev_err(info->dev, "couldn't register input device\n");
goto err_iff;
}
platform_set_drvdata(pdev, info);
return 0; return 0;
err_voltage:
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
err_regulator:
free_irq(info->irq, info);
err_irq:
input_unregister_device(info->input_dev);
info->input_dev = NULL;
err_iff: err_iff:
if (info->input_dev) input_ff_destroy(info->input_dev);
input_ff_destroy(info->input_dev);
err_ialloc: err_ialloc:
input_free_device(info->input_dev); input_free_device(info->input_dev);
err_kzalloc: err_regulator:
kfree(info); regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
return ret; return ret;
} }
...@@ -423,10 +408,7 @@ static int twl6040_vibra_remove(struct platform_device *pdev) ...@@ -423,10 +408,7 @@ static int twl6040_vibra_remove(struct platform_device *pdev)
struct vibra_info *info = platform_get_drvdata(pdev); struct vibra_info *info = platform_get_drvdata(pdev);
input_unregister_device(info->input_dev); input_unregister_device(info->input_dev);
free_irq(info->irq, info);
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
destroy_workqueue(info->workqueue);
kfree(info);
return 0; return 0;
} }
......
...@@ -86,7 +86,7 @@ static int wm831x_on_probe(struct platform_device *pdev) ...@@ -86,7 +86,7 @@ static int wm831x_on_probe(struct platform_device *pdev)
wm831x_on->wm831x = wm831x; wm831x_on->wm831x = wm831x;
INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on); INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on);
wm831x_on->dev = input_allocate_device(); wm831x_on->dev = devm_input_allocate_device(&pdev->dev);
if (!wm831x_on->dev) { if (!wm831x_on->dev) {
dev_err(&pdev->dev, "Can't allocate input dev\n"); dev_err(&pdev->dev, "Can't allocate input dev\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -119,7 +119,6 @@ static int wm831x_on_probe(struct platform_device *pdev) ...@@ -119,7 +119,6 @@ static int wm831x_on_probe(struct platform_device *pdev)
err_irq: err_irq:
free_irq(irq, wm831x_on); free_irq(irq, wm831x_on);
err_input_dev: err_input_dev:
input_free_device(wm831x_on->dev);
err: err:
return ret; return ret;
} }
...@@ -131,7 +130,6 @@ static int wm831x_on_remove(struct platform_device *pdev) ...@@ -131,7 +130,6 @@ static int wm831x_on_remove(struct platform_device *pdev)
free_irq(irq, wm831x_on); free_irq(irq, wm831x_on);
cancel_delayed_work_sync(&wm831x_on->work); cancel_delayed_work_sync(&wm831x_on->work);
input_unregister_device(wm831x_on->dev);
return 0; return 0;
} }
......
...@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS ...@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS
If unsure, say Y. If unsure, say Y.
config MOUSE_PS2_CYPRESS
bool "Cypress PS/2 mouse protocol extension" if EXPERT
default y
depends on MOUSE_PS2
help
Say Y here if you have a Cypress PS/2 Trackpad connected to
your system.
If unsure, say Y.
config MOUSE_PS2_LIFEBOOK config MOUSE_PS2_LIFEBOOK
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
default y default y
...@@ -193,6 +203,18 @@ config MOUSE_BCM5974 ...@@ -193,6 +203,18 @@ config MOUSE_BCM5974
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 bcm5974. module will be called bcm5974.
config MOUSE_CYAPA
tristate "Cypress APA I2C Trackpad support"
depends on I2C
help
This driver adds support for Cypress All Points Addressable (APA)
I2C Trackpads, including the ones used in 2012 Samsung Chromebooks.
Say Y here if you have a Cypress APA I2C Trackpad.
To compile this driver as a module, choose M here: the module will be
called cyapa.
config MOUSE_INPORT config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse" tristate "InPort/MS/ATIXL busmouse"
depends on ISA depends on ISA
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
...@@ -32,3 +33,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o ...@@ -32,3 +33,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o
This diff is collapsed.
...@@ -12,35 +12,146 @@ ...@@ -12,35 +12,146 @@
#ifndef _ALPS_H #ifndef _ALPS_H
#define _ALPS_H #define _ALPS_H
#define ALPS_PROTO_V1 0 #define ALPS_PROTO_V1 1
#define ALPS_PROTO_V2 1 #define ALPS_PROTO_V2 2
#define ALPS_PROTO_V3 2 #define ALPS_PROTO_V3 3
#define ALPS_PROTO_V4 3 #define ALPS_PROTO_V4 4
/**
* struct alps_model_info - touchpad ID table
* @signature: E7 response string to match.
* @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response
* (aka command mode response) identifies the firmware minor version. This
* can be used to distinguish different hardware models which are not
* uniquely identifiable through their E7 responses.
* @proto_version: Indicates V1/V2/V3/...
* @byte0: Helps figure out whether a position report packet matches the
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
*
* Many (but not all) ALPS touchpads can be identified by looking at the
* values returned in the "E7 report" and/or the "EC report." This table
* lists a number of such touchpads.
*/
struct alps_model_info { struct alps_model_info {
unsigned char signature[3]; unsigned char signature[3];
unsigned char command_mode_resp; /* v3/v4 only */ unsigned char command_mode_resp;
unsigned char proto_version; unsigned char proto_version;
unsigned char byte0, mask0; unsigned char byte0, mask0;
unsigned char flags; unsigned char flags;
}; };
/**
* struct alps_nibble_commands - encodings for register accesses
* @command: PS/2 command used for the nibble
* @data: Data supplied as an argument to the PS/2 command, if applicable
*
* The ALPS protocol uses magic sequences to transmit binary data to the
* touchpad, as it is generally not OK to send arbitrary bytes out the
* PS/2 port. Each of the sequences in this table sends one nibble of the
* register address or (write) data. Different versions of the ALPS protocol
* use slightly different encodings.
*/
struct alps_nibble_commands { struct alps_nibble_commands {
int command; int command;
unsigned char data; unsigned char data;
}; };
/**
* struct alps_fields - decoded version of the report packet
* @x_map: Bitmap of active X positions for MT.
* @y_map: Bitmap of active Y positions for MT.
* @fingers: Number of fingers for MT.
* @x: X position for ST.
* @y: Y position for ST.
* @z: Z position for ST.
* @first_mp: Packet is the first of a multi-packet report.
* @is_mp: Packet is part of a multi-packet report.
* @left: Left touchpad button is active.
* @right: Right touchpad button is active.
* @middle: Middle touchpad button is active.
* @ts_left: Left trackstick button is active.
* @ts_right: Right trackstick button is active.
* @ts_middle: Middle trackstick button is active.
*/
struct alps_fields {
unsigned int x_map;
unsigned int y_map;
unsigned int fingers;
unsigned int x;
unsigned int y;
unsigned int z;
unsigned int first_mp:1;
unsigned int is_mp:1;
unsigned int left:1;
unsigned int right:1;
unsigned int middle:1;
unsigned int ts_left:1;
unsigned int ts_right:1;
unsigned int ts_middle:1;
};
/**
* struct alps_data - private data structure for the ALPS driver
* @dev2: "Relative" device used to report trackstick or mouse activity.
* @phys: Physical path for the relative device.
* @nibble_commands: Command mapping used for touchpad register accesses.
* @addr_command: Command used to tell the touchpad that a register address
* follows.
* @proto_version: Indicates V1/V2/V3/...
* @byte0: Helps figure out whether a position report packet matches the
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
* @x_max: Largest possible X position value.
* @y_max: Largest possible Y position value.
* @x_bits: Number of X bits in the MT bitmap.
* @y_bits: Number of Y bits in the MT bitmap.
* @hw_init: Protocol-specific hardware init function.
* @process_packet: Protocol-specific function to process a report packet.
* @decode_fields: Protocol-specific function to read packet bitfields.
* @set_abs_params: Protocol-specific function to configure the input_dev.
* @prev_fin: Finger bit from previous packet.
* @multi_packet: Multi-packet data in progress.
* @multi_data: Saved multi-packet data.
* @x1: First X coordinate from last MT report.
* @x2: Second X coordinate from last MT report.
* @y1: First Y coordinate from last MT report.
* @y2: Second Y coordinate from last MT report.
* @fingers: Number of fingers from last MT report.
* @quirks: Bitmap of ALPS_QUIRK_*.
* @timer: Timer for flushing out the final report packet in the stream.
*/
struct alps_data { struct alps_data {
struct input_dev *dev2; /* Relative device */ struct input_dev *dev2;
char phys[32]; /* Phys */ char phys[32];
const struct alps_model_info *i;/* Info */
/* these are autodetected when the device is identified */
const struct alps_nibble_commands *nibble_commands; const struct alps_nibble_commands *nibble_commands;
int addr_command; /* Command to set register address */ int addr_command;
int prev_fin; /* Finger bit from previous packet */ unsigned char proto_version;
int multi_packet; /* Multi-packet data in progress */ unsigned char byte0, mask0;
unsigned char multi_data[6]; /* Saved multi-packet data */ unsigned char flags;
int x1, x2, y1, y2; /* Coordinates from last MT report */ int x_max;
int fingers; /* Number of fingers from MT report */ int y_max;
int x_bits;
int y_bits;
int (*hw_init)(struct psmouse *psmouse);
void (*process_packet)(struct psmouse *psmouse);
void (*decode_fields)(struct alps_fields *f, unsigned char *p);
void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
int prev_fin;
int multi_packet;
unsigned char multi_data[6];
int x1, x2, y1, y2;
int fingers;
u8 quirks; u8 quirks;
struct timer_list timer; struct timer_list timer;
}; };
......
This diff is collapsed.
This diff is collapsed.
#ifndef _CYPRESS_PS2_H
#define _CYPRESS_PS2_H
#include "psmouse.h"
#define CMD_BITS_MASK 0x03
#define COMPOSIT(x, s) (((x) & CMD_BITS_MASK) << (s))
#define ENCODE_CMD(aa, bb, cc, dd) \
(COMPOSIT((aa), 6) | COMPOSIT((bb), 4) | COMPOSIT((cc), 2) | COMPOSIT((dd), 0))
#define CYTP_CMD_ABS_NO_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 0)
#define CYTP_CMD_ABS_WITH_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 1)
#define CYTP_CMD_SMBUS_MODE ENCODE_CMD(0, 1, 1, 0)
#define CYTP_CMD_STANDARD_MODE ENCODE_CMD(0, 2, 0, 0) /* not implemented yet. */
#define CYTP_CMD_CYPRESS_REL_MODE ENCODE_CMD(1, 1, 1, 1) /* not implemented yet. */
#define CYTP_CMD_READ_CYPRESS_ID ENCODE_CMD(0, 0, 0, 0)
#define CYTP_CMD_READ_TP_METRICS ENCODE_CMD(0, 0, 0, 1)
#define CYTP_CMD_SET_HSCROLL_WIDTH(w) ENCODE_CMD(1, 1, 0, (w))
#define CYTP_CMD_SET_HSCROLL_MASK ENCODE_CMD(1, 1, 0, 0)
#define CYTP_CMD_SET_VSCROLL_WIDTH(w) ENCODE_CMD(1, 2, 0, (w))
#define CYTP_CMD_SET_VSCROLL_MASK ENCODE_CMD(1, 2, 0, 0)
#define CYTP_CMD_SET_PALM_GEOMETRY(e) ENCODE_CMD(1, 2, 1, (e))
#define CYTP_CMD_PALM_GEMMETRY_MASK ENCODE_CMD(1, 2, 1, 0)
#define CYTP_CMD_SET_PALM_SENSITIVITY(s) ENCODE_CMD(1, 2, 2, (s))
#define CYTP_CMD_PALM_SENSITIVITY_MASK ENCODE_CMD(1, 2, 2, 0)
#define CYTP_CMD_SET_MOUSE_SENSITIVITY(s) ENCODE_CMD(1, 3, ((s) >> 2), (s))
#define CYTP_CMD_MOUSE_SENSITIVITY_MASK ENCODE_CMD(1, 3, 0, 0)
#define CYTP_CMD_REQUEST_BASELINE_STATUS ENCODE_CMD(2, 0, 0, 1)
#define CYTP_CMD_REQUEST_RECALIBRATION ENCODE_CMD(2, 0, 0, 3)
#define DECODE_CMD_AA(x) (((x) >> 6) & CMD_BITS_MASK)
#define DECODE_CMD_BB(x) (((x) >> 4) & CMD_BITS_MASK)
#define DECODE_CMD_CC(x) (((x) >> 2) & CMD_BITS_MASK)
#define DECODE_CMD_DD(x) ((x) & CMD_BITS_MASK)
/* Cypress trackpad working mode. */
#define CYTP_BIT_ABS_PRESSURE (1 << 3)
#define CYTP_BIT_ABS_NO_PRESSURE (1 << 2)
#define CYTP_BIT_CYPRESS_REL (1 << 1)
#define CYTP_BIT_STANDARD_REL (1 << 0)
#define CYTP_BIT_REL_MASK (CYTP_BIT_CYPRESS_REL | CYTP_BIT_STANDARD_REL)
#define CYTP_BIT_ABS_MASK (CYTP_BIT_ABS_PRESSURE | CYTP_BIT_ABS_NO_PRESSURE)
#define CYTP_BIT_ABS_REL_MASK (CYTP_BIT_ABS_MASK | CYTP_BIT_REL_MASK)
#define CYTP_BIT_HIGH_RATE (1 << 4)
/*
* report mode bit is set, firmware working in Remote Mode.
* report mode bit is cleared, firmware working in Stream Mode.
*/
#define CYTP_BIT_REPORT_MODE (1 << 5)
/* scrolling width values for set HSCROLL and VSCROLL width command. */
#define SCROLL_WIDTH_NARROW 1
#define SCROLL_WIDTH_NORMAL 2
#define SCROLL_WIDTH_WIDE 3
#define PALM_GEOMETRY_ENABLE 1
#define PALM_GEOMETRY_DISABLE 0
#define TP_METRICS_MASK 0x80
#define FW_VERSION_MASX 0x7f
#define FW_VER_HIGH_MASK 0x70
#define FW_VER_LOW_MASK 0x0f
/* Times to retry a ps2_command and millisecond delay between tries. */
#define CYTP_PS2_CMD_TRIES 3
#define CYTP_PS2_CMD_DELAY 500
/* time out for PS/2 command only in milliseconds. */
#define CYTP_CMD_TIMEOUT 200
#define CYTP_DATA_TIMEOUT 30
#define CYTP_EXT_CMD 0xe8
#define CYTP_PS2_RETRY 0xfe
#define CYTP_PS2_ERROR 0xfc
#define CYTP_RESP_RETRY 0x01
#define CYTP_RESP_ERROR 0xfe
#define CYTP_105001_WIDTH 97 /* Dell XPS 13 */
#define CYTP_105001_HIGH 59
#define CYTP_DEFAULT_WIDTH (CYTP_105001_WIDTH)
#define CYTP_DEFAULT_HIGH (CYTP_105001_HIGH)
#define CYTP_ABS_MAX_X 1600
#define CYTP_ABS_MAX_Y 900
#define CYTP_MAX_PRESSURE 255
#define CYTP_MIN_PRESSURE 0
/* header byte bits of relative package. */
#define BTN_LEFT_BIT 0x01
#define BTN_RIGHT_BIT 0x02
#define BTN_MIDDLE_BIT 0x04
#define REL_X_SIGN_BIT 0x10
#define REL_Y_SIGN_BIT 0x20
/* header byte bits of absolute package. */
#define ABS_VSCROLL_BIT 0x10
#define ABS_HSCROLL_BIT 0x20
#define ABS_MULTIFINGER_TAP 0x04
#define ABS_EDGE_MOTION_MASK 0x80
#define DFLT_RESP_BITS_VALID 0x88 /* SMBus bit should not be set. */
#define DFLT_RESP_SMBUS_BIT 0x80
#define DFLT_SMBUS_MODE 0x80
#define DFLT_PS2_MODE 0x00
#define DFLT_RESP_BIT_MODE 0x40
#define DFLT_RESP_REMOTE_MODE 0x40
#define DFLT_RESP_STREAM_MODE 0x00
#define DFLT_RESP_BIT_REPORTING 0x20
#define DFLT_RESP_BIT_SCALING 0x10
#define TP_METRICS_BIT_PALM 0x80
#define TP_METRICS_BIT_STUBBORN 0x40
#define TP_METRICS_BIT_2F_JITTER 0x30
#define TP_METRICS_BIT_1F_JITTER 0x0c
#define TP_METRICS_BIT_APA 0x02
#define TP_METRICS_BIT_MTG 0x01
#define TP_METRICS_BIT_ABS_PKT_FORMAT_SET 0xf0
#define TP_METRICS_BIT_2F_SPIKE 0x0c
#define TP_METRICS_BIT_1F_SPIKE 0x03
/* bits of first byte response of E9h-Status Request command. */
#define RESP_BTN_RIGHT_BIT 0x01
#define RESP_BTN_MIDDLE_BIT 0x02
#define RESP_BTN_LEFT_BIT 0x04
#define RESP_SCALING_BIT 0x10
#define RESP_ENABLE_BIT 0x20
#define RESP_REMOTE_BIT 0x40
#define RESP_SMBUS_BIT 0x80
#define CYTP_MAX_MT_SLOTS 2
struct cytp_contact {
int x;
int y;
int z; /* also named as touch pressure. */
};
/* The structure of Cypress Trackpad event data. */
struct cytp_report_data {
int contact_cnt;
struct cytp_contact contacts[CYTP_MAX_MT_SLOTS];
unsigned int left:1;
unsigned int right:1;
unsigned int middle:1;
unsigned int tap:1; /* multi-finger tap detected. */
};
/* The structure of Cypress Trackpad device private data. */
struct cytp_data {
int fw_version;
int pkt_size;
int mode;
int tp_min_pressure;
int tp_max_pressure;
int tp_width; /* X direction physical size in mm. */
int tp_high; /* Y direction physical size in mm. */
int tp_max_abs_x; /* Max X absolute units that can be reported. */
int tp_max_abs_y; /* Max Y absolute units that can be reported. */
int tp_res_x; /* X resolution in units/mm. */
int tp_res_y; /* Y resolution in units/mm. */
int tp_metrics_supported;
};
#ifdef CONFIG_MOUSE_PS2_CYPRESS
int cypress_detect(struct psmouse *psmouse, bool set_properties);
int cypress_init(struct psmouse *psmouse);
bool cypress_supported(void);
#else
inline int cypress_detect(struct psmouse *psmouse, bool set_properties)
{
return -ENOSYS;
}
inline int cypress_init(struct psmouse *psmouse)
{
return -ENOSYS;
}
inline bool cypress_supported(void)
{
return 0;
}
#endif /* CONFIG_MOUSE_PS2_CYPRESS */
#endif /* _CYPRESS_PS2_H */
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "touchkit_ps2.h" #include "touchkit_ps2.h"
#include "elantech.h" #include "elantech.h"
#include "sentelic.h" #include "sentelic.h"
#include "cypress_ps2.h"
#define DRIVER_DESC "PS/2 mouse driver" #define DRIVER_DESC "PS/2 mouse driver"
...@@ -758,6 +759,28 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -758,6 +759,28 @@ static int psmouse_extensions(struct psmouse *psmouse,
synaptics_reset(psmouse); synaptics_reset(psmouse);
} }
/*
* Try Cypress Trackpad.
* Must try it before Finger Sensing Pad because Finger Sensing Pad probe
* upsets some modules of Cypress Trackpads.
*/
if (max_proto > PSMOUSE_IMEX &&
cypress_detect(psmouse, set_properties) == 0) {
if (cypress_supported()) {
if (cypress_init(psmouse) == 0)
return PSMOUSE_CYPRESS;
/*
* Finger Sensing Pad probe upsets some modules of
* Cypress Trackpad, must avoid Finger Sensing Pad
* probe if Cypress Trackpad device detected.
*/
return PSMOUSE_PS2;
}
max_proto = PSMOUSE_IMEX;
}
/* /*
* Try ALPS TouchPad * Try ALPS TouchPad
*/ */
...@@ -896,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -896,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.alias = "thinkps", .alias = "thinkps",
.detect = thinking_detect, .detect = thinking_detect,
}, },
#ifdef CONFIG_MOUSE_PS2_CYPRESS
{
.type = PSMOUSE_CYPRESS,
.name = "CyPS/2",
.alias = "cypress",
.detect = cypress_detect,
.init = cypress_init,
},
#endif
{ {
.type = PSMOUSE_GENPS, .type = PSMOUSE_GENPS,
.name = "GenPS/2", .name = "GenPS/2",
......
...@@ -95,6 +95,7 @@ enum psmouse_type { ...@@ -95,6 +95,7 @@ enum psmouse_type {
PSMOUSE_ELANTECH, PSMOUSE_ELANTECH,
PSMOUSE_FSP, PSMOUSE_FSP,
PSMOUSE_SYNAPTICS_RELATIVE, PSMOUSE_SYNAPTICS_RELATIVE,
PSMOUSE_CYPRESS,
PSMOUSE_AUTO /* This one should always be last */ PSMOUSE_AUTO /* This one should always be last */
}; };
......
...@@ -722,11 +722,13 @@ static void synaptics_report_mt_data(struct psmouse *psmouse, ...@@ -722,11 +722,13 @@ static void synaptics_report_mt_data(struct psmouse *psmouse,
default: default:
/* /*
* If the finger slot contained in SGM is valid, and either * If the finger slot contained in SGM is valid, and either
* hasn't changed, or is new, then report SGM in MTB slot 0. * hasn't changed, or is new, or the old SGM has now moved to
* AGM, then report SGM in MTB slot 0.
* Otherwise, empty MTB slot 0. * Otherwise, empty MTB slot 0.
*/ */
if (mt_state->sgm != -1 && if (mt_state->sgm != -1 &&
(mt_state->sgm == old->sgm || old->sgm == -1)) (mt_state->sgm == old->sgm ||
old->sgm == -1 || mt_state->agm == old->sgm))
synaptics_report_slot(dev, 0, sgm); synaptics_report_slot(dev, 0, sgm);
else else
synaptics_report_slot(dev, 0, NULL); synaptics_report_slot(dev, 0, NULL);
...@@ -735,9 +737,31 @@ static void synaptics_report_mt_data(struct psmouse *psmouse, ...@@ -735,9 +737,31 @@ static void synaptics_report_mt_data(struct psmouse *psmouse,
* If the finger slot contained in AGM is valid, and either * If the finger slot contained in AGM is valid, and either
* hasn't changed, or is new, then report AGM in MTB slot 1. * hasn't changed, or is new, then report AGM in MTB slot 1.
* Otherwise, empty MTB slot 1. * Otherwise, empty MTB slot 1.
*
* However, in the case where the AGM is new, make sure that
* that it is either the same as the old SGM, or there was no
* SGM.
*
* Otherwise, if the SGM was just 1, and the new AGM is 2, then
* the new AGM will keep the old SGM's tracking ID, which can
* cause apparent drumroll. This happens if in the following
* valid finger sequence:
*
* Action SGM AGM (MTB slot:Contact)
* 1. Touch contact 0 (0:0)
* 2. Touch contact 1 (0:0, 1:1)
* 3. Lift contact 0 (1:1)
* 4. Touch contacts 2,3 (0:2, 1:3)
*
* In step 4, contact 3, in AGM must not be given the same
* tracking ID as contact 1 had in step 3. To avoid this,
* the first agm with contact 3 is dropped and slot 1 is
* invalidated (tracking ID = -1).
*/ */
if (mt_state->agm != -1 && if (mt_state->agm != -1 &&
(mt_state->agm == old->agm || old->agm == -1)) (mt_state->agm == old->agm ||
(old->agm == -1 &&
(old->sgm == -1 || mt_state->agm == old->sgm))))
synaptics_report_slot(dev, 1, agm); synaptics_report_slot(dev, 1, agm);
else else
synaptics_report_slot(dev, 1, NULL); synaptics_report_slot(dev, 1, NULL);
...@@ -1247,11 +1271,11 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -1247,11 +1271,11 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
input_mt_init_slots(dev, 2, 0);
set_abs_position_params(dev, priv, ABS_MT_POSITION_X, set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y); ABS_MT_POSITION_Y);
/* Image sensors can report per-contact pressure */ /* Image sensors can report per-contact pressure */
input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
input_mt_init_slots(dev, 2, INPUT_MT_POINTER);
/* Image sensors can signal 4 and 5 finger clicks */ /* Image sensors can signal 4 and 5 finger clicks */
__set_bit(BTN_TOOL_QUADTAP, dev->keybit); __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
......
...@@ -236,6 +236,7 @@ config SERIO_PS2MULT ...@@ -236,6 +236,7 @@ config SERIO_PS2MULT
config SERIO_ARC_PS2 config SERIO_ARC_PS2
tristate "ARC PS/2 support" tristate "ARC PS/2 support"
depends on GENERIC_HARDIRQS
help help
Say Y here if you have an ARC FPGA platform with a PS/2 Say Y here if you have an ARC FPGA platform with a PS/2
controller in it. controller in it.
......
This diff is collapsed.
...@@ -78,6 +78,7 @@ enum { ...@@ -78,6 +78,7 @@ enum {
INTUOS5L, INTUOS5L,
WACOM_21UX2, WACOM_21UX2,
WACOM_22HD, WACOM_22HD,
DTK,
WACOM_24HD, WACOM_24HD,
CINTIQ, CINTIQ,
WACOM_BEE, WACOM_BEE,
...@@ -135,7 +136,6 @@ struct wacom_wac { ...@@ -135,7 +136,6 @@ struct wacom_wac {
int pid; int pid;
int battery_capacity; int battery_capacity;
int num_contacts_left; int num_contacts_left;
int *slots;
}; };
#endif #endif
...@@ -359,7 +359,7 @@ config TOUCHSCREEN_MCS5000 ...@@ -359,7 +359,7 @@ config TOUCHSCREEN_MCS5000
config TOUCHSCREEN_MMS114 config TOUCHSCREEN_MMS114
tristate "MELFAS MMS114 touchscreen" tristate "MELFAS MMS114 touchscreen"
depends on I2C depends on I2C && GENERIC_HARDIRQS
help help
Say Y here if you have the MELFAS MMS114 touchscreen controller Say Y here if you have the MELFAS MMS114 touchscreen controller
chip in your system. chip in your system.
......
...@@ -193,7 +193,6 @@ static struct spi_driver cyttsp_spi_driver = { ...@@ -193,7 +193,6 @@ static struct spi_driver cyttsp_spi_driver = {
module_spi_driver(cyttsp_spi_driver); module_spi_driver(cyttsp_spi_driver);
MODULE_ALIAS("spi:cyttsp");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
MODULE_AUTHOR("Cypress"); MODULE_AUTHOR("Cypress");
......
This diff is collapsed.
...@@ -120,6 +120,7 @@ static void stmpe_work(struct work_struct *work) ...@@ -120,6 +120,7 @@ static void stmpe_work(struct work_struct *work)
__stmpe_reset_fifo(ts->stmpe); __stmpe_reset_fifo(ts->stmpe);
input_report_abs(ts->idev, ABS_PRESSURE, 0); input_report_abs(ts->idev, ABS_PRESSURE, 0);
input_report_key(ts->idev, BTN_TOUCH, 0);
input_sync(ts->idev); input_sync(ts->idev);
} }
...@@ -153,6 +154,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) ...@@ -153,6 +154,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
input_report_abs(ts->idev, ABS_X, x); input_report_abs(ts->idev, ABS_X, x);
input_report_abs(ts->idev, ABS_Y, y); input_report_abs(ts->idev, ABS_Y, y);
input_report_abs(ts->idev, ABS_PRESSURE, z); input_report_abs(ts->idev, ABS_PRESSURE, z);
input_report_key(ts->idev, BTN_TOUCH, 1);
input_sync(ts->idev); input_sync(ts->idev);
/* flush the FIFO after we have read out our values. */ /* flush the FIFO after we have read out our values. */
......
...@@ -753,3 +753,4 @@ module_spi_driver(tsc2005_driver); ...@@ -753,3 +753,4 @@ module_spi_driver(tsc2005_driver);
MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:tsc2005");
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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