summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-10-14 03:40:31 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-14 03:40:31 -0700
commita1c6e317af6f42236e4ee698a810833f54328d0d (patch)
tree84049a40a42ac11de1e557d5c74353c63b318bf1
parentb2799f1e25b3fbec3741930d73595c65bec752b5 (diff)
parent3ef7b5c53ec92b76f6a63c8bfa080f108cf456a4 (diff)
Merge "input: pat9125: add support of sending rotating switch events"
-rw-r--r--Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt21
-rw-r--r--drivers/input/misc/ots_pat9125/pat9125_linux_driver.c94
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.h3
3 files changed, 112 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
index 02f21835f870..1b68c695d2c5 100644
--- a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
+++ b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
@@ -6,5 +6,24 @@ to the Host processor. The host processor reads the direction and number of
steps over I2C and passes the data to the rest of the system.
Required properties:
+ - compatible : should be "pixart,pat9125".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : interrupt to indicate motion of the rotating switch.
- - compatible : should be "pixart,pat9125".
+Optional properties:
+ - pixart,inverse-x : boolean, use this to invert the x data before sending it to input framework
+ - pixart,inverse-y : boolean, use this to invert the y data before sending it to input framework
+ - pixart,press-enabled : boolean, use this to enable detection of pressing the button
+
+Required properties if 'pixart,press-enabled' DT property is defined:
+ - pixart,press-keycode : keycode to be sent when press is detected by the driver.
+
+Example:
+ pixart_pat9125@75 {
+ compatible = "pixart,pat9125";
+ reg = <0x75>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <98 0x2008>;
+ pixart,irq-gpio = <&msm_gpio 98 0x2008>;
+ };
diff --git a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
index e5edaf5f908d..fa44b7d866f8 100644
--- a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
+++ b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of_gpio.h>
+#include <linux/delay.h>
#include "pixart_ots.h"
struct pixart_pat9125_data {
@@ -18,6 +19,10 @@ struct pixart_pat9125_data {
struct input_dev *input;
int irq_gpio;
u32 irq_flags;
+ u32 press_keycode;
+ bool press_en;
+ bool inverse_x;
+ bool inverse_y;
};
static int pat9125_i2c_write(struct i2c_client *client, u8 reg, u8 *data,
@@ -70,7 +75,7 @@ static int pat9125_i2c_read(struct i2c_client *client, u8 reg, u8 *data)
return ret;
}
-unsigned char read_data(struct i2c_client *client, u8 addr)
+u8 read_data(struct i2c_client *client, u8 addr)
{
u8 data = 0xff;
@@ -83,8 +88,55 @@ void write_data(struct i2c_client *client, u8 addr, u8 data)
pat9125_i2c_write(client, addr, &data, 1);
}
-static irqreturn_t pixart_pat9125_irq(int irq, void *data)
+static irqreturn_t pat9125_irq(int irq, void *dev_data)
{
+ u8 delta_x = 0, delta_y = 0, motion;
+ struct pixart_pat9125_data *data = dev_data;
+ struct input_dev *ipdev = data->input;
+ struct device *dev = &data->client->dev;
+
+ motion = read_data(data->client, PIXART_PAT9125_MOTION_STATUS_REG);
+ do {
+ /* check if MOTION bit is set or not */
+ if (motion & PIXART_PAT9125_VALID_MOTION_DATA) {
+ delta_x = read_data(data->client,
+ PIXART_PAT9125_DELTA_X_LO_REG);
+ delta_y = read_data(data->client,
+ PIXART_PAT9125_DELTA_Y_LO_REG);
+
+ /* Inverse x depending upon the device orientation */
+ delta_x = (data->inverse_x) ? -delta_x : delta_x;
+ /* Inverse y depending upon the device orientation */
+ delta_y = (data->inverse_y) ? -delta_y : delta_y;
+ }
+
+ dev_dbg(dev, "motion = %x, delta_x = %x, delta_y = %x\n",
+ motion, delta_x, delta_y);
+
+ if (delta_x != 0) {
+ /* Send delta_x as REL_WHEEL for rotation */
+ input_report_rel(ipdev, REL_WHEEL, (s8) delta_x);
+ input_sync(ipdev);
+ }
+
+ if (data->press_en && delta_y != 0) {
+ if ((s8) delta_y > 0) {
+ /* Send DOWN event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 1);
+ input_sync(ipdev);
+ } else {
+ /* Send UP event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 0);
+ input_sync(ipdev);
+ }
+ }
+ usleep_range(PIXART_SAMPLING_PERIOD_US_MIN,
+ PIXART_SAMPLING_PERIOD_US_MAX);
+
+ motion = read_data(data->client,
+ PIXART_PAT9125_MOTION_STATUS_REG);
+ } while (motion & PIXART_PAT9125_VALID_MOTION_DATA);
+
return IRQ_HANDLED;
}
@@ -145,13 +197,36 @@ static struct attribute_group pat9125_attr_grp = {
.attrs = pat9125_attr_list,
};
+static int pat9125_parse_dt(struct device *dev,
+ struct pixart_pat9125_data *data)
+{
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+ int ret;
+
+ data->inverse_x = of_property_read_bool(np, "pixart,inverse-x");
+ data->inverse_y = of_property_read_bool(np, "pixart,inverse-y");
+ data->press_en = of_property_read_bool(np, "pixart,press-enabled");
+ if (data->press_en) {
+ ret = of_property_read_u32(np, "pixart,press-keycode",
+ &temp_val);
+ if (!ret) {
+ data->press_keycode = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse press-keycode\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int pat9125_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
struct pixart_pat9125_data *data;
struct input_dev *input;
- struct device_node *np;
struct device *dev = &client->dev;
err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
@@ -165,6 +240,11 @@ static int pat9125_i2c_probe(struct i2c_client *client,
GFP_KERNEL);
if (!data)
return -ENOMEM;
+ err = pat9125_parse_dt(dev, data);
+ if (err) {
+ dev_err(dev, "DT parsing failed, errno:%d\n", err);
+ return err;
+ }
} else {
data = client->dev.platform_data;
if (!data) {
@@ -180,6 +260,10 @@ static int pat9125_i2c_probe(struct i2c_client *client,
return -ENOMEM;
}
+ input_set_capability(input, EV_REL, REL_WHEEL);
+ if (data->press_en)
+ input_set_capability(input, EV_KEY, data->press_keycode);
+
i2c_set_clientdata(client, data);
input_set_drvdata(input, data);
input->name = PAT9125_DEV_NAME;
@@ -213,8 +297,8 @@ static int pat9125_i2c_probe(struct i2c_client *client,
goto err_sensor_init;
}
- err = devm_request_threaded_irq(dev, client->irq, NULL,
- pixart_pat9125_irq, (unsigned long)data->irq_flags,
+ err = devm_request_threaded_irq(dev, client->irq, NULL, pat9125_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW,
"pixart_pat9125_irq", data);
if (err) {
dev_err(dev, "Req irq %d failed, errno:%d\n", client->irq, err);
diff --git a/drivers/input/misc/ots_pat9125/pixart_ots.h b/drivers/input/misc/ots_pat9125/pixart_ots.h
index a66ded5c9d08..91813929d811 100644
--- a/drivers/input/misc/ots_pat9125/pixart_ots.h
+++ b/drivers/input/misc/ots_pat9125/pixart_ots.h
@@ -39,6 +39,9 @@
#define PIXART_PAT9125_LOW_VOLTAGE_SEGMENT 0x04
#define PIXART_PAT9125_VALID_MOTION_DATA 0x80
+#define PIXART_SAMPLING_PERIOD_US_MIN 4000
+#define PIXART_SAMPLING_PERIOD_US_MAX 8000
+
/* Export functions */
bool ots_sensor_init(struct i2c_client *);