Commit 39fada55 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull more input updates from Dmitry Torokhov:
 "Two new drivers for touchscreen controllers:

   - Silead touchscreen controllers
   - SiS 9200 family touchscreen controllers

  and a few driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: silead - remove some dead code
  Input: sis-i2c - select CONFIG_CRC_ITU_T
  Input: add driver for SiS 9200 family I2C touchscreen controllers
  Input: ili210x - fix permissions on "calibrate" attribute
  Input: elan_i2c - properly wake up touchpad on ASUS laptops
  Input: add driver for Silead touchscreens
  Input: elantech - fix debug dump of the current packet
  Input: rotary_encoder - support binary encoding of states
  Input: xpad - power off wireless 360 controllers on suspend
  Input: i8042 - break load dependency between atkbd/psmouse and i8042
  Input: synaptics-rmi4 - do not check for NULL when calling of_node_put()
  Input: cros_ec_keyb - cleanup use of dev
parents f72035fa 22fe874f
......@@ -20,6 +20,8 @@ Optional properties:
2: Half-period mode
4: Quarter-period mode
- wakeup-source: Boolean, rotary encoder can wake up the system.
- rotary-encoder,encoding: String, the method used to encode steps.
Supported are "gray" (the default and more common) and "binary".
Deprecated properties:
- rotary-encoder,half-period: Makes the driver work on half-period mode.
......@@ -34,6 +36,7 @@ Example:
compatible = "rotary-encoder";
gpios = <&gpio 19 1>, <&gpio 20 0>; /* GPIO19 is inverted */
linux,axis = <0>; /* REL_X */
rotary-encoder,encoding = "gray";
rotary-encoder,relative-axis;
};
......@@ -42,5 +45,6 @@ Example:
gpios = <&gpio 21 0>, <&gpio 22 0>;
linux,axis = <1>; /* ABS_Y */
rotary-encoder,steps = <24>;
rotary-encoder,encoding = "binary";
rotary-encoder,rollover;
};
* GSL 1680 touchscreen controller
Required properties:
- compatible : "silead,gsl1680"
- reg : I2C slave address of the chip (0x40)
- interrupt-parent : a phandle pointing to the interrupt controller
serving the interrupt for this chip
- interrupts : interrupt specification for the gsl1680 interrupt
- power-gpios : Specification for the pin connected to the gsl1680's
shutdown input. This needs to be driven high to take the
gsl1680 out of its low power state
- touchscreen-size-x : See touchscreen.txt
- touchscreen-size-y : See touchscreen.txt
Optional properties:
- touchscreen-inverted-x : See touchscreen.txt
- touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt
- silead,max-fingers : maximum number of fingers the touchscreen can detect
Example:
i2c@00000000 {
gsl1680: touchscreen@40 {
compatible = "silead,gsl1680";
reg = <0x40>;
interrupt-parent = <&pio>;
interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>;
power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>;
touchscreen-size-x = <480>;
touchscreen-size-y = <800>;
touchscreen-inverted-x;
touchscreen-swapped-x-y;
silead,max-fingers = <5>;
};
};
* SiS I2C Multiple Touch Controller
Required properties:
- compatible: must be "sis,9200-ts"
- reg: i2c slave address
- interrupt-parent: the phandle for the interrupt controller
(see interrupt binding [0])
- interrupts: touch controller interrupt (see interrupt
binding [0])
Optional properties:
- pinctrl-names: should be "default" (see pinctrl binding [1]).
- pinctrl-0: a phandle pointing to the pin settings for the
device (see pinctrl binding [1]).
- attn-gpios: the gpio pin used as attention line
- reset-gpios: the gpio pin used to reset the controller
- wakeup-source: touchscreen can be used as a wakeup source
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example:
sis9255@5c {
compatible = "sis,9200-ts";
reg = <0x5c>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sis>;
interrupt-parent = <&gpio3>;
interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
irq-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>;
};
......@@ -238,6 +238,7 @@ simtek
sii Seiko Instruments, Inc.
silergy Silergy Corp.
sirf SiRF Technology, Inc.
sis Silicon Integrated Systems Corp.
sitronix Sitronix Technology Corporation
skyworks Skyworks Solutions, Inc.
smsc Standard Microsystems Corporation
......
......@@ -115,6 +115,10 @@ static bool sticks_to_null;
module_param(sticks_to_null, bool, S_IRUGO);
MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
static bool auto_poweroff = true;
module_param(auto_poweroff, bool, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(auto_poweroff, "Power off wireless controllers on suspend");
static const struct xpad_device {
u16 idVendor;
u16 idProduct;
......@@ -1248,6 +1252,36 @@ static void xpad_stop_input(struct usb_xpad *xpad)
usb_kill_urb(xpad->irq_in);
}
static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
{
unsigned long flags;
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
spin_lock_irqsave(&xpad->odata_lock, flags);
packet->data[0] = 0x00;
packet->data[1] = 0x00;
packet->data[2] = 0x08;
packet->data[3] = 0xC0;
packet->data[4] = 0x00;
packet->data[5] = 0x00;
packet->data[6] = 0x00;
packet->data[7] = 0x00;
packet->data[8] = 0x00;
packet->data[9] = 0x00;
packet->data[10] = 0x00;
packet->data[11] = 0x00;
packet->len = 12;
packet->pending = true;
/* Reset the sequence so we send out poweroff now */
xpad->last_out_packet = -1;
xpad_try_sending_next_out_packet(xpad);
spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
static int xpad360w_start_input(struct usb_xpad *xpad)
{
int error;
......@@ -1590,6 +1624,15 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
* or goes away.
*/
xpad360w_stop_input(xpad);
/*
* The wireless adapter is going off now, so the
* gamepads are going to become disconnected.
* Unless explicitly disabled, power them down
* so they don't just sit there flashing.
*/
if (auto_poweroff && xpad->pad_present)
xpad360w_poweroff_controller(xpad);
} else {
mutex_lock(&input->mutex);
if (input->users)
......
......@@ -186,7 +186,7 @@ static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
if (ret >= 0)
cros_ec_keyb_process(ckdev, kb_state, ret);
else
dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
dev_err(ckdev->dev, "failed to get keyboard state: %d\n", ret);
return IRQ_HANDLED;
}
......@@ -236,7 +236,7 @@ static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev)
static int cros_ec_keyb_probe(struct platform_device *pdev)
{
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
struct device *dev = ec->dev;
struct device *dev = &pdev->dev;
struct cros_ec_keyb *ckdev;
struct input_dev *idev;
struct device_node *np;
......@@ -246,23 +246,22 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
if (!np)
return -ENODEV;
ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL);
ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);
if (!ckdev)
return -ENOMEM;
err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows,
&ckdev->cols);
err = matrix_keypad_parse_of_params(dev, &ckdev->rows, &ckdev->cols);
if (err)
return err;
ckdev->valid_keys = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
if (!ckdev->valid_keys)
return -ENOMEM;
ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
ckdev->old_kb_state = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
if (!ckdev->old_kb_state)
return -ENOMEM;
idev = devm_input_allocate_device(&pdev->dev);
idev = devm_input_allocate_device(dev);
if (!idev)
return -ENOMEM;
......@@ -273,7 +272,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
ckdev->ec = ec;
ckdev->dev = dev;
dev_set_drvdata(&pdev->dev, ckdev);
dev_set_drvdata(dev, ckdev);
idev->name = CROS_EC_DEV_NAME;
idev->phys = ec->phys_name;
......@@ -282,7 +281,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
idev->id.bustype = BUS_VIRTUAL;
idev->id.version = 1;
idev->id.product = 0;
idev->dev.parent = &pdev->dev;
idev->dev.parent = dev;
idev->open = cros_ec_keyb_open;
idev->close = cros_ec_keyb_close;
......
......@@ -28,6 +28,11 @@
#define DRV_NAME "rotary-encoder"
enum rotary_encoder_encoding {
ROTENC_GRAY,
ROTENC_BINARY,
};
struct rotary_encoder {
struct input_dev *input;
......@@ -37,6 +42,7 @@ struct rotary_encoder {
u32 axis;
bool relative_axis;
bool rollover;
enum rotary_encoder_encoding encoding;
unsigned int pos;
......@@ -57,8 +63,9 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
for (i = 0; i < encoder->gpios->ndescs; ++i) {
int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
/* convert from gray encoding to normal */
if (ret & 1)
if (encoder->encoding == ROTENC_GRAY && ret & 1)
val = !val;
ret = ret << 1 | val;
......@@ -213,6 +220,20 @@ static int rotary_encoder_probe(struct platform_device *pdev)
encoder->rollover =
device_property_read_bool(dev, "rotary-encoder,rollover");
if (!device_property_present(dev, "rotary-encoder,encoding") ||
!device_property_match_string(dev, "rotary-encoder,encoding",
"gray")) {
dev_info(dev, "gray");
encoder->encoding = ROTENC_GRAY;
} else if (!device_property_match_string(dev, "rotary-encoder,encoding",
"binary")) {
dev_info(dev, "binary");
encoder->encoding = ROTENC_BINARY;
} else {
dev_err(dev, "unknown encoding setting\n");
return -EINVAL;
}
device_property_read_u32(dev, "linux,axis", &encoder->axis);
encoder->relative_axis =
device_property_read_bool(dev, "rotary-encoder,relative-axis");
......
......@@ -4,7 +4,8 @@
* Copyright (c) 2013 ELAN Microelectronics Corp.
*
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
* Version: 1.6.0
* Author: KT Liao <kt.liao@emc.com.tw>
* Version: 1.6.2
*
* Based on cyapa driver:
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
......@@ -40,7 +41,7 @@
#include "elan_i2c.h"
#define DRIVER_NAME "elan_i2c"
#define ELAN_DRIVER_VERSION "1.6.1"
#define ELAN_DRIVER_VERSION "1.6.2"
#define ELAN_VENDOR_ID 0x04f3
#define ETP_MAX_PRESSURE 255
#define ETP_FWIDTH_REDUCE 90
......@@ -199,9 +200,41 @@ static int elan_sleep(struct elan_tp_data *data)
return error;
}
static int elan_query_product(struct elan_tp_data *data)
{
int error;
error = data->ops->get_product_id(data->client, &data->product_id);
if (error)
return error;
error = data->ops->get_sm_version(data->client, &data->ic_type,
&data->sm_version);
if (error)
return error;
return 0;
}
static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
{
if (data->ic_type != 0x0E)
return false;
switch (data->product_id) {
case 0x05 ... 0x07:
case 0x09:
case 0x13:
return true;
default:
return false;
}
}
static int __elan_initialize(struct elan_tp_data *data)
{
struct i2c_client *client = data->client;
bool woken_up = false;
int error;
error = data->ops->initialize(client);
......@@ -210,6 +243,27 @@ static int __elan_initialize(struct elan_tp_data *data)
return error;
}
error = elan_query_product(data);
if (error)
return error;
/*
* Some ASUS devices were shipped with firmware that requires
* touchpads to be woken up first, before attempting to switch
* them into absolute reporting mode.
*/
if (elan_check_ASUS_special_fw(data)) {
error = data->ops->sleep_control(client, false);
if (error) {
dev_err(&client->dev,
"failed to wake device up: %d\n", error);
return error;
}
msleep(200);
woken_up = true;
}
data->mode |= ETP_ENABLE_ABS;
error = data->ops->set_mode(client, data->mode);
if (error) {
......@@ -218,11 +272,13 @@ static int __elan_initialize(struct elan_tp_data *data)
return error;
}
error = data->ops->sleep_control(client, false);
if (error) {
dev_err(&client->dev,
"failed to wake device up: %d\n", error);
return error;
if (!woken_up) {
error = data->ops->sleep_control(client, false);
if (error) {
dev_err(&client->dev,
"failed to wake device up: %d\n", error);
return error;
}
}
return 0;
......@@ -248,10 +304,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
{
int error;
error = data->ops->get_product_id(data->client, &data->product_id);
if (error)
return error;
error = data->ops->get_version(data->client, false, &data->fw_version);
if (error)
return error;
......@@ -261,11 +313,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
if (error)
return error;
error = data->ops->get_sm_version(data->client, &data->ic_type,
&data->sm_version);
if (error)
return error;
error = data->ops->get_version(data->client, true, &data->iap_version);
if (error)
return error;
......
......@@ -222,12 +222,8 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
*/
static void elantech_packet_dump(struct psmouse *psmouse)
{
int i;
psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
for (i = 0; i < psmouse->pktsize; i++)
printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
printk("]\n");
psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [%*ph]\n",
psmouse->pktsize, psmouse->packet);
}
/*
......
......@@ -232,10 +232,7 @@ err_put_device:
void rmi_unregister_function(struct rmi_function *fn)
{
device_del(&fn->dev);
if (fn->dev.of_node)
of_node_put(fn->dev.of_node);
of_node_put(fn->dev.of_node);
put_device(&fn->dev);
}
......
......@@ -1277,6 +1277,7 @@ static int __init i8042_create_kbd_port(void)
serio->start = i8042_start;
serio->stop = i8042_stop;
serio->close = i8042_port_close;
serio->ps2_cmd_mutex = &i8042_mutex;
serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
......@@ -1373,21 +1374,6 @@ static void i8042_unregister_ports(void)
}
}
/*
* Checks whether port belongs to i8042 controller.
*/
bool i8042_check_port_owner(const struct serio *port)
{
int i;
for (i = 0; i < I8042_NUM_PORTS; i++)
if (i8042_ports[i].serio == port)
return true;
return false;
}
EXPORT_SYMBOL(i8042_check_port_owner);
static void i8042_free_irqs(void)
{
if (i8042_aux_irq_registered)
......
......@@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte);
void ps2_begin_command(struct ps2dev *ps2dev)
{
mutex_lock(&ps2dev->cmd_mutex);
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
if (i8042_check_port_owner(ps2dev->serio))
i8042_lock_chip();
mutex_lock(m);
}
EXPORT_SYMBOL(ps2_begin_command);
void ps2_end_command(struct ps2dev *ps2dev)
{
if (i8042_check_port_owner(ps2dev->serio))
i8042_unlock_chip();
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
mutex_unlock(&ps2dev->cmd_mutex);
mutex_unlock(m);
}
EXPORT_SYMBOL(ps2_end_command);
......
......@@ -1059,6 +1059,31 @@ config TOUCHSCREEN_RM_TS
To compile this driver as a module, choose M here: the
module will be called raydium_i2c_ts.
config TOUCHSCREEN_SILEAD
tristate "Silead I2C touchscreen"
depends on I2C
help
Say Y here if you have the Silead touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called silead.
config TOUCHSCREEN_SIS_I2C
tristate "SiS 9200 family I2C touchscreen"
depends on I2C
select CRC_ITU_T
depends on GPIOLIB || COMPILE_TEST
help
This enables support for SiS 9200 family over I2C based touchscreens.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called sis_i2c.
config TOUCHSCREEN_ST1232
tristate "Sitronix ST1232 touchscreen controllers"
depends on I2C
......
......@@ -64,6 +64,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o
obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
......
......@@ -169,7 +169,7 @@ static ssize_t ili210x_calibrate(struct device *dev,
return count;
}
static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate);
static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate);
static struct attribute *ili210x_attributes[] = {
&dev_attr_calibrate.attr,
......
This diff is collapsed.
This diff is collapsed.
......@@ -62,7 +62,6 @@ struct serio;
void i8042_lock_chip(void);
void i8042_unlock_chip(void);
int i8042_command(unsigned char *param, int command);
bool i8042_check_port_owner(const struct serio *);
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio));
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
......@@ -83,11 +82,6 @@ static inline int i8042_command(unsigned char *param, int command)
return -ENODEV;
}
static inline bool i8042_check_port_owner(const struct serio *serio)
{
return false;
}
static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
......
......@@ -31,7 +31,8 @@ struct serio {
struct serio_device_id id;
spinlock_t lock; /* protects critical sections from port's interrupt handler */
/* Protects critical sections from port's interrupt handler */
spinlock_t lock;
int (*write)(struct serio *, unsigned char);
int (*open)(struct serio *);
......@@ -40,16 +41,29 @@ struct serio {
void (*stop)(struct serio *);
struct serio *parent;
struct list_head child_node; /* Entry in parent->children list */
/* Entry in parent->children list */
struct list_head child_node;
struct list_head children;
unsigned int depth; /* level of nesting in serio hierarchy */
/* Level of nesting in serio hierarchy */
unsigned int depth;
struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */
struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
/*
* serio->drv is accessed from interrupt handlers; when modifying
* caller should acquire serio->drv_mutex and serio->lock.
*/
struct serio_driver *drv;
/* Protects serio->drv so attributes can pin current driver */
struct mutex drv_mutex;
struct device dev;
struct list_head node;
/*
* For use by PS/2 layer when several ports share hardware and
* may get indigestion when exposed to concurrent access (i8042).
*/
struct mutex *ps2_cmd_mutex;
};
#define to_serio_port(d) container_of(d, struct serio, dev)
......
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