You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"Two new touchpad drivers - Cypress APA I2C Trackpad and Cypress PS/2
touchpad and a big update to ALPS driver from Kevin Cernekee that adds
support for "Rushmore" touchpads and paves way for adding support for
"Dolphin" touchpads.
There is also a new input driver for Goldfish emulator and also
Android keyreset driver was folded into SysRq code.
A few more drivers were updated with device tree bindings and others
got some small cleanups and fixes."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (55 commits)
Input: cyttsp-spi - remove duplicate MODULE_ALIAS()
Input: tsc2005 - add MODULE_ALIAS
Input: tegra-kbc - require CONFIG_OF, remove platform data
Input: synaptics - initialize pointer emulation usage
Input: MT - do not apply filtering on emulated events
Input: bma150 - make some defines public and fix some comments
Input: bma150 - fix checking pm_runtime_get_sync() return value
Input: ALPS - enable trackstick on Rushmore touchpads
Input: ALPS - add support for "Rushmore" touchpads
Input: ALPS - make the V3 packet field decoder "pluggable"
Input: ALPS - move pixel and bitmap info into alps_data struct
Input: ALPS - fix command mode check
Input: ALPS - rework detection of Pinnacle AGx touchpads
Input: ALPS - move {addr,nibble}_command settings into alps_set_defaults()
Input: ALPS - use function pointers for different protocol handlers
Input: ALPS - rework detection sequence
Input: ALPS - introduce helper function for repeated commands
Input: ALPS - move alps_get_model() down below hw_init code
Input: ALPS - copy "model" info into alps_data struct
Input: ALPS - document the alps.h data structures
...
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
* 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 */
|
||||
};
|
||||
@@ -1,7 +1,18 @@
|
||||
* 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:
|
||||
- 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
|
||||
matrix-keyboard bindings:
|
||||
@@ -19,5 +30,16 @@ Example:
|
||||
keyboard: keyboard {
|
||||
compatible = "nvidia,tegra20-kbc";
|
||||
reg = <0x7000e200 0x100>;
|
||||
interrupts = <0 85 0x04>;
|
||||
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 @@
|
||||
#
|
||||
|
||||
menu "Input device support"
|
||||
depends on !S390 && !UML
|
||||
depends on !UML
|
||||
|
||||
config INPUT
|
||||
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)
|
||||
{
|
||||
if (dev->absinfo && test_bit(src, dev->absbit)) {
|
||||
dev->absinfo[dst] = dev->absinfo[src];
|
||||
dev->absinfo[dst].fuzz = 0;
|
||||
dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* #define WK0701_DEBUG */
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#define RESERVE 20000
|
||||
#define SYNC_PULSE 1306000
|
||||
@@ -67,6 +67,7 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w)
|
||||
{
|
||||
int i;
|
||||
int val1, val2, val3, val4, val5, val6, val7, val8;
|
||||
int magic, magic_bit;
|
||||
int crc1, crc2;
|
||||
|
||||
for (crc1 = crc2 = i = 0; i < 10; i++) {
|
||||
@@ -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] & 2) - 1; /*sign */
|
||||
|
||||
#ifdef WK0701_DEBUG
|
||||
{
|
||||
int magic, magic_bit;
|
||||
magic = (w->buf[21] << 4) | w->buf[22];
|
||||
magic_bit = (w->buf[24] & 8) >> 3;
|
||||
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
|
||||
pr_debug("%4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n",
|
||||
val1, val2, val3, val4, val5, val6, val7, val8,
|
||||
magic, magic_bit);
|
||||
|
||||
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_Z, val6);
|
||||
@@ -187,6 +183,9 @@ static int walkera0701_open(struct input_dev *dev)
|
||||
{
|
||||
struct walkera_dev *w = input_get_drvdata(dev);
|
||||
|
||||
if (parport_claim(w->pardevice))
|
||||
return -EBUSY;
|
||||
|
||||
parport_enable_irq(w->parport);
|
||||
return 0;
|
||||
}
|
||||
@@ -197,40 +196,51 @@ static void walkera0701_close(struct input_dev *dev)
|
||||
|
||||
parport_disable_irq(w->parport);
|
||||
hrtimer_cancel(&w->timer);
|
||||
|
||||
parport_release(w->pardevice);
|
||||
}
|
||||
|
||||
static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
{
|
||||
int err = -ENODEV;
|
||||
int error;
|
||||
|
||||
w->parport = parport_find_number(parport);
|
||||
if (w->parport == NULL)
|
||||
if (!w->parport) {
|
||||
pr_err("parport %d does not exist\n", parport);
|
||||
return -ENODEV;
|
||||
|
||||
if (w->parport->irq == -1) {
|
||||
printk(KERN_ERR "walkera0701: parport without interrupt\n");
|
||||
goto init_err;
|
||||
}
|
||||
|
||||
err = -EBUSY;
|
||||
if (w->parport->irq == -1) {
|
||||
pr_err("parport %d does not have interrupt assigned\n",
|
||||
parport);
|
||||
error = -EINVAL;
|
||||
goto err_put_parport;
|
||||
}
|
||||
|
||||
w->pardevice = parport_register_device(w->parport, "walkera0701",
|
||||
NULL, NULL, walkera0701_irq_handler,
|
||||
PARPORT_DEV_EXCL, w);
|
||||
if (!w->pardevice)
|
||||
goto init_err;
|
||||
if (!w->pardevice) {
|
||||
pr_err("failed to register parport device\n");
|
||||
error = -EIO;
|
||||
goto err_put_parport;
|
||||
}
|
||||
|
||||
if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT))
|
||||
goto init_err1;
|
||||
|
||||
if (parport_claim(w->pardevice))
|
||||
goto init_err1;
|
||||
if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) {
|
||||
pr_err("failed to negotiate parport mode\n");
|
||||
error = -EIO;
|
||||
goto err_unregister_device;
|
||||
}
|
||||
|
||||
hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
w->timer.function = timer_handler;
|
||||
|
||||
w->input_dev = input_allocate_device();
|
||||
if (!w->input_dev)
|
||||
goto init_err2;
|
||||
if (!w->input_dev) {
|
||||
pr_err("failed to allocate input device\n");
|
||||
error = -ENOMEM;
|
||||
goto err_unregister_device;
|
||||
}
|
||||
|
||||
input_set_drvdata(w->input_dev, w);
|
||||
w->input_dev->name = "Walkera WK-0701 TX";
|
||||
@@ -241,6 +251,7 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
w->input_dev->id.vendor = 0x0001;
|
||||
w->input_dev->id.product = 0x0001;
|
||||
w->input_dev->id.version = 0x0100;
|
||||
w->input_dev->dev.parent = w->parport->dev;
|
||||
w->input_dev->open = walkera0701_open;
|
||||
w->input_dev->close = walkera0701_close;
|
||||
|
||||
@@ -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_MISC, -512, 512, 0, 0);
|
||||
|
||||
err = input_register_device(w->input_dev);
|
||||
if (err)
|
||||
goto init_err3;
|
||||
error = input_register_device(w->input_dev);
|
||||
if (error) {
|
||||
pr_err("failed to register input device\n");
|
||||
goto err_free_input_dev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
init_err3:
|
||||
err_free_input_dev:
|
||||
input_free_device(w->input_dev);
|
||||
init_err2:
|
||||
parport_release(w->pardevice);
|
||||
init_err1:
|
||||
err_unregister_device:
|
||||
parport_unregister_device(w->pardevice);
|
||||
init_err:
|
||||
err_put_parport:
|
||||
parport_put_port(w->parport);
|
||||
return err;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void walkera0701_disconnect(struct walkera_dev *w)
|
||||
{
|
||||
input_unregister_device(w->input_dev);
|
||||
parport_release(w->pardevice);
|
||||
parport_unregister_device(w->pardevice);
|
||||
parport_put_port(w->parport);
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ config KEYBOARD_TCA6416
|
||||
|
||||
config KEYBOARD_TCA8418
|
||||
tristate "TCA8418 Keypad Support"
|
||||
depends on I2C
|
||||
depends on I2C && GENERIC_HARDIRQS
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
This driver implements basic keypad functionality
|
||||
@@ -303,7 +303,7 @@ config KEYBOARD_HP7XX
|
||||
|
||||
config KEYBOARD_LM8323
|
||||
tristate "LM8323 keypad chip"
|
||||
depends on I2C
|
||||
depends on I2C && GENERIC_HARDIRQS
|
||||
depends on LEDS_CLASS
|
||||
help
|
||||
If you say yes here you get support for the National Semiconductor
|
||||
@@ -420,7 +420,7 @@ config KEYBOARD_NOMADIK
|
||||
|
||||
config KEYBOARD_TEGRA
|
||||
tristate "NVIDIA Tegra internal matrix keyboard controller support"
|
||||
depends on ARCH_TEGRA
|
||||
depends on ARCH_TEGRA && OF
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Say Y here if you want to use a matrix keyboard connected directly
|
||||
@@ -479,6 +479,16 @@ config KEYBOARD_SAMSUNG
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
tristate "Stowaway keyboard"
|
||||
select SERIO
|
||||
|
||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
|
||||
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.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_POLLED) += gpio_keys_polled.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
|
||||
|
||||
@@ -676,6 +676,39 @@ static inline void atkbd_disable(struct atkbd *atkbd)
|
||||
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.
|
||||
*/
|
||||
@@ -726,11 +759,17 @@ static int atkbd_probe(struct atkbd *atkbd)
|
||||
|
||||
if (atkbd->id == 0xaca1 && atkbd->translated) {
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure nothing is coming from the keyboard and disturbs our
|
||||
* internal state.
|
||||
*/
|
||||
atkbd_deactivate(atkbd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -825,24 +864,6 @@ static int atkbd_reset_state(struct atkbd *atkbd)
|
||||
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
|
||||
* reboot.
|
||||
@@ -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_reset_state(atkbd);
|
||||
atkbd_activate(atkbd);
|
||||
|
||||
} else {
|
||||
atkbd->set = 2;
|
||||
@@ -1165,6 +1185,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
||||
goto fail3;
|
||||
|
||||
atkbd_enable(atkbd);
|
||||
if (serio->write)
|
||||
atkbd_activate(atkbd);
|
||||
|
||||
err = input_register_device(atkbd->dev);
|
||||
if (err)
|
||||
@@ -1208,8 +1230,6 @@ static int atkbd_reconnect(struct serio *serio)
|
||||
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
|
||||
goto out;
|
||||
|
||||
atkbd_activate(atkbd);
|
||||
|
||||
/*
|
||||
* Restore LED state and repeat rate. While input core
|
||||
* will do this for us at resume time reconnect may happen
|
||||
@@ -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);
|
||||
if (atkbd->write)
|
||||
atkbd_activate(atkbd);
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timer.h>
|
||||
@@ -414,15 +415,23 @@ open_err:
|
||||
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)
|
||||
{
|
||||
const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
|
||||
struct imx_keypad *keypad;
|
||||
struct input_dev *input_dev;
|
||||
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");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -480,22 +489,6 @@ static int imx_keypad_probe(struct platform_device *pdev)
|
||||
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 */
|
||||
input_dev->name = pdev->name;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
@@ -512,6 +505,19 @@ static int imx_keypad_probe(struct platform_device *pdev)
|
||||
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);
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
input_set_drvdata(input_dev, keypad);
|
||||
@@ -631,6 +637,7 @@ static struct platform_driver imx_keypad_driver = {
|
||||
.name = "imx-keypad",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &imx_kbd_pm_ops,
|
||||
.of_match_table = of_match_ptr(imx_keypad_of_match),
|
||||
},
|
||||
.probe = imx_keypad_probe,
|
||||
.remove = imx_keypad_remove,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
@@ -39,6 +40,11 @@
|
||||
#define QT2160_CMD_GPIOS 6
|
||||
#define QT2160_CMD_SUBVER 7
|
||||
#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)
|
||||
|
||||
@@ -49,6 +55,17 @@ static unsigned char qt2160_key2code[] = {
|
||||
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 i2c_client *client;
|
||||
struct input_dev *input;
|
||||
@@ -56,8 +73,61 @@ struct qt2160_data {
|
||||
spinlock_t lock; /* Protects canceling/rescheduling of dwork */
|
||||
unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
|
||||
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,
|
||||
u8 inireg, u8 *buffer, unsigned int count)
|
||||
{
|
||||
@@ -216,6 +286,63 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
|
||||
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)
|
||||
{
|
||||
@@ -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);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to register input device\n");
|
||||
goto err_free_irq;
|
||||
goto err_unregister_leds;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, qt2160);
|
||||
@@ -326,6 +459,8 @@ static int qt2160_probe(struct i2c_client *client,
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_leds:
|
||||
qt2160_unregister_leds(qt2160);
|
||||
err_free_irq:
|
||||
if (client->irq)
|
||||
free_irq(client->irq, qt2160);
|
||||
@@ -339,6 +474,8 @@ static int qt2160_remove(struct i2c_client *client)
|
||||
{
|
||||
struct qt2160_data *qt2160 = i2c_get_clientdata(client);
|
||||
|
||||
qt2160_unregister_leds(qt2160);
|
||||
|
||||
/* Release IRQ so no queue will be scheduled */
|
||||
if (client->irq)
|
||||
free_irq(client->irq, qt2160);
|
||||
|
||||
+155
-335
File diff suppressed because it is too large
Load Diff
@@ -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} */
|
||||
.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
|
||||
.fifo_mode = FIFO_STREAM,
|
||||
.fifo_mode = ADXL_FIFO_STREAM,
|
||||
.watermark = 0,
|
||||
};
|
||||
|
||||
@@ -732,7 +732,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
|
||||
mutex_init(&ac->mutex);
|
||||
|
||||
input_dev->name = "ADXL34x accelerometer";
|
||||
revid = ac->bops->read(dev, DEVID);
|
||||
revid = AC_READ(ac, DEVID);
|
||||
|
||||
switch (revid) {
|
||||
case ID_ADXL345:
|
||||
@@ -809,7 +809,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
|
||||
if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS)
|
||||
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,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
@@ -827,7 +827,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
|
||||
if (err)
|
||||
goto err_remove_attr;
|
||||
|
||||
AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold);
|
||||
AC_WRITE(ac, OFSX, pdata->x_axis_offset);
|
||||
ac->hwcal.x = pdata->x_axis_offset;
|
||||
AC_WRITE(ac, OFSY, pdata->y_axis_offset);
|
||||
|
||||
@@ -46,18 +46,6 @@
|
||||
#define BMA150_POLL_MAX 200
|
||||
#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_SLEEP 2
|
||||
#define BMA150_MODE_WAKE_UP 3
|
||||
@@ -372,7 +360,7 @@ static int bma150_open(struct bma150_data *bma150)
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get_sync(&bma150->client->dev);
|
||||
if (error && error != -ENOSYS)
|
||||
if (error < 0 && error != -ENOSYS)
|
||||
return error;
|
||||
|
||||
/*
|
||||
|
||||
@@ -43,7 +43,6 @@ struct vibra_info {
|
||||
struct device *dev;
|
||||
struct input_dev *input_dev;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct play_work;
|
||||
|
||||
bool enabled;
|
||||
@@ -143,19 +142,7 @@ static int vibra_play(struct input_dev *input, void *data,
|
||||
if (!info->speed)
|
||||
info->speed = effect->u.rumble.weak_magnitude >> 9;
|
||||
info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1;
|
||||
queue_work(info->workqueue, &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;
|
||||
}
|
||||
schedule_work(&info->play_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -164,9 +151,6 @@ static void twl4030_vibra_close(struct input_dev *input)
|
||||
struct vibra_info *info = input_get_drvdata(input);
|
||||
|
||||
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)
|
||||
vibra_disable(info);
|
||||
@@ -219,7 +203,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -227,11 +211,10 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
|
||||
info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
|
||||
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) {
|
||||
dev_err(&pdev->dev, "couldn't allocate input device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_set_drvdata(info->input_dev, info);
|
||||
@@ -239,14 +222,13 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
|
||||
info->input_dev->name = "twl4030:vibrator";
|
||||
info->input_dev->id.version = 1;
|
||||
info->input_dev->dev.parent = pdev->dev.parent;
|
||||
info->input_dev->open = twl4030_vibra_open;
|
||||
info->input_dev->close = twl4030_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_dbg(&pdev->dev, "couldn't register vibrator to FF\n");
|
||||
goto err_ialloc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = input_register_device(info->input_dev);
|
||||
@@ -262,28 +244,11 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
|
||||
|
||||
err_iff:
|
||||
input_ff_destroy(info->input_dev);
|
||||
err_ialloc:
|
||||
input_free_device(info->input_dev);
|
||||
err_kzalloc:
|
||||
kfree(info);
|
||||
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 = {
|
||||
.probe = twl4030_vibra_probe,
|
||||
.remove = twl4030_vibra_remove,
|
||||
.driver = {
|
||||
.name = "twl4030-vibra",
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
@@ -275,7 +275,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "couldn't allocate memory\n");
|
||||
return -ENOMEM;
|
||||
@@ -309,24 +309,65 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
if ((!info->vibldrv_res && !info->viblmotor_res) ||
|
||||
(!info->vibrdrv_res && !info->vibrmotor_res)) {
|
||||
dev_err(info->dev, "invalid vibra driver/motor resistance\n");
|
||||
ret = -EINVAL;
|
||||
goto err_kzalloc;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->irq = platform_get_irq(pdev, 0);
|
||||
if (info->irq < 0) {
|
||||
dev_err(info->dev, "invalid irq\n");
|
||||
ret = -EINVAL;
|
||||
goto err_kzalloc;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_init(&info->mutex);
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
|
||||
twl6040_vib_irq_handler, 0,
|
||||
"twl6040_irq_vib", info);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->supplies[0].supply = "vddvibl";
|
||||
info->supplies[1].supply = "vddvibr";
|
||||
/*
|
||||
* When booted with Device tree the regulators are attached to the
|
||||
* parent device (twl6040 MFD core)
|
||||
*/
|
||||
ret = regulator_bulk_get(pdata ? info->dev : twl6040_core_dev,
|
||||
ARRAY_SIZE(info->supplies), info->supplies);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "couldn't get regulators %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vddvibl_uV) {
|
||||
ret = regulator_set_voltage(info->supplies[0].consumer,
|
||||
vddvibl_uV, vddvibl_uV);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
|
||||
ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
if (vddvibr_uV) {
|
||||
ret = regulator_set_voltage(info->supplies[1].consumer,
|
||||
vddvibr_uV, vddvibr_uV);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
|
||||
ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
INIT_WORK(&info->play_work, vibra_play_work);
|
||||
|
||||
info->input_dev = input_allocate_device();
|
||||
if (info->input_dev == NULL) {
|
||||
dev_err(info->dev, "couldn't allocate input device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
goto err_regulator;
|
||||
}
|
||||
|
||||
input_set_drvdata(info->input_dev, info);
|
||||
@@ -351,70 +392,14 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
|
||||
"twl6040_irq_vib", info);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
info->supplies[0].supply = "vddvibl";
|
||||
info->supplies[1].supply = "vddvibr";
|
||||
/*
|
||||
* When booted with Device tree the regulators are attached to the
|
||||
* parent device (twl6040 MFD core)
|
||||
*/
|
||||
ret = regulator_bulk_get(pdata ? info->dev : twl6040_core_dev,
|
||||
ARRAY_SIZE(info->supplies), info->supplies);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "couldn't get regulators %d\n", ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
|
||||
if (vddvibl_uV) {
|
||||
ret = regulator_set_voltage(info->supplies[0].consumer,
|
||||
vddvibl_uV, vddvibl_uV);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
|
||||
ret);
|
||||
goto err_voltage;
|
||||
}
|
||||
}
|
||||
|
||||
if (vddvibr_uV) {
|
||||
ret = regulator_set_voltage(info->supplies[1].consumer,
|
||||
vddvibr_uV, vddvibr_uV);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
|
||||
ret);
|
||||
goto err_voltage;
|
||||
}
|
||||
}
|
||||
|
||||
info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0);
|
||||
if (info->workqueue == NULL) {
|
||||
dev_err(info->dev, "couldn't create workqueue\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_voltage;
|
||||
}
|
||||
INIT_WORK(&info->play_work, vibra_play_work);
|
||||
|
||||
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:
|
||||
if (info->input_dev)
|
||||
input_ff_destroy(info->input_dev);
|
||||
err_ialloc:
|
||||
input_free_device(info->input_dev);
|
||||
err_kzalloc:
|
||||
kfree(info);
|
||||
err_regulator:
|
||||
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -423,10 +408,7 @@ static int twl6040_vibra_remove(struct platform_device *pdev)
|
||||
struct vibra_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
input_unregister_device(info->input_dev);
|
||||
free_irq(info->irq, info);
|
||||
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
|
||||
destroy_workqueue(info->workqueue);
|
||||
kfree(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ static int wm831x_on_probe(struct platform_device *pdev)
|
||||
wm831x_on->wm831x = wm831x;
|
||||
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) {
|
||||
dev_err(&pdev->dev, "Can't allocate input dev\n");
|
||||
ret = -ENOMEM;
|
||||
@@ -119,7 +119,6 @@ static int wm831x_on_probe(struct platform_device *pdev)
|
||||
err_irq:
|
||||
free_irq(irq, wm831x_on);
|
||||
err_input_dev:
|
||||
input_free_device(wm831x_on->dev);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -131,7 +130,6 @@ static int wm831x_on_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(irq, wm831x_on);
|
||||
cancel_delayed_work_sync(&wm831x_on->work);
|
||||
input_unregister_device(wm831x_on->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS
|
||||
|
||||
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
|
||||
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
|
||||
default y
|
||||
@@ -193,6 +203,18 @@ config MOUSE_BCM5974
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
tristate "InPort/MS/ATIXL busmouse"
|
||||
depends on ISA
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
|
||||
obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
|
||||
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
|
||||
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
|
||||
obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
|
||||
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
|
||||
obj-$(CONFIG_MOUSE_INPORT) += inport.o
|
||||
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
|
||||
@@ -32,3 +33,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o
|
||||
|
||||
+401
-322
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user