* [PATCH 3/3] Input: wacom - Avoid incorrect sign extension from pressure-value lower byte
From: Carl Worth @ 2014-02-26 22:38 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, linux-kernel, Carl Worth
In-Reply-To: <1393454296-32735-3-git-send-email-cworth@cworth.org>
Previously, whenever the lower byte was greater than 127, the sign
extension of the "char" during integer promotion would result in a
negative value for pressure. There was code in place to adjust a
negative value back to positive by subtracting from pressure_max, but
this code was only correct with a tablet with a maximum of 256
pressure values.
By switching from "char" to "unsigned char" we can avoid the sign
extension altogether, eliminate the code to adjust values, and obtain
correct pressure results.
With this code in place, I am now obtaining correct pressure results
from the Wacom tablet built into a ThinkPad Yoga laptop. (Prior to
this fix, gradual increases of pressure would result in pressure
values that would reset from 255 to 0 rathern than simply increasing.)
Signed-off-by: Carl Worth <cworth@cworth.org>
---
drivers/input/tablet/wacom_wac.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 563f197..93f7440 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1018,8 +1018,7 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
static int wacom_tpc_pen(struct wacom_wac *wacom)
{
- struct wacom_features *features = &wacom->features;
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
int pressure;
bool prox = data[1] & 0x20;
@@ -1038,8 +1037,6 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
pressure = (data[7] << 8) | data[6];
- if (pressure < 0)
- pressure = features->pressure_max + pressure + 1;
input_report_abs(input, ABS_PRESSURE, pressure);
input_report_key(input, BTN_TOUCH, data[1] & 0x05);
input_report_key(input, wacom->tool[0], prox);
--
1.9.0
^ permalink raw reply related
* [PATCH 1/3] Input: wacom - EC tablet supports 1023 levels of pressure, not just 255
From: Carl Worth @ 2014-02-26 22:38 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, linux-kernel, Carl Worth
In-Reply-To: <1393454296-32735-1-git-send-email-cworth@cworth.org>
This was verified on a ThinkPad Yoga laptop with an integrated Wacom
tablet which reports itself with an ID of 0xEC.
Signed-off-by: Carl Worth <cworth@cworth.org>
---
drivers/input/tablet/wacom_wac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 782c253..4958081 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -2109,7 +2109,7 @@ static const struct wacom_features wacom_features_0xE6 =
0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
.touch_max = 2 };
static const struct wacom_features wacom_features_0xEC =
- { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255,
+ { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 1023,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xED =
{ "Wacom ISDv4 ED", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
--
1.9.0
^ permalink raw reply related
* [PATCH 2/3] Input: wacom - Don't discard bits from upper byte of pressure value
From: Carl Worth @ 2014-02-26 22:38 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, linux-kernel, Carl Worth
In-Reply-To: <1393454296-32735-2-git-send-email-cworth@cworth.org>
The mask here previously discarded all but one bit of data from the
upper byte of the pressure value. That would be correct for a tablet
with at most 512 pressure values, but is incorrect for a tablet with
1024 or more pressure values.
We can support as many tablets as possible by simply not discarding
any of the bits from this byte.
Signed-off-by: Carl Worth <cworth@cworth.org>
---
drivers/input/tablet/wacom_wac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 4958081..563f197 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1037,7 +1037,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
- pressure = ((data[7] & 0x01) << 8) | data[6];
+ pressure = (data[7] << 8) | data[6];
if (pressure < 0)
pressure = features->pressure_max + pressure + 1;
input_report_abs(input, ABS_PRESSURE, pressure);
--
1.9.0
^ permalink raw reply related
* wacom: Fixes for stylus pressure values for Thinkpad Yoga
From: Carl Worth @ 2014-02-26 22:38 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, linux-kernel
This series of patches fixes the pressure values reported for the
wacom tablet built-in to a Lenovo ThinkPad Yoga laptop. Prior to this
patch series, if I slowly increased stylus pressure, (expecting a
gradual increase of values from 0 to 1023), I instead received values
that increased slowly to 255, then reset to 0 and increased slowly
again, etc.
The buggy arithmetic that is updated here appears to exist in
identical forms for other drivers. I did not update any code that I
was not able to test directly. But it looks like wacom_pl_irq and
wacom_dtu_irq potentially have similar bugs, (depending on the actual
pressure_max values encountered in practice).
^ permalink raw reply
* Re: [PATCH 0/5] ARM: davinci: tnetv107x removal
From: Sergei Shtylyov @ 2014-02-26 20:04 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel, Alexandre Courbot
Cc: davinci-linux-open-source, Samuel Ortiz, Kevin Hilman,
Linus Walleij, Dmitry Torokhov, linux-kernel, linux-spi,
linux-gpio, Mark Brown, linux-input, Lee Jones
In-Reply-To: <201402261446.29257.arnd@arndb.de>
Hello.
On 02/26/2014 04:46 PM, Arnd Bergmann wrote:
>> The five patches are completely independent of one another,
>> and applying them out of order is fine since we just want
>> to remove the code. However, I'm looking for an Ack from
>> Cyril Chemparathy and Sekhar Nori first, to be sure we
>> won't need this code in the future. Kevin Hilman has
>> already mentioned that he sees no reason to keep this
>> code.
> Hmm, apparently Cyril is no longer at TI. If anyone has his
> current email address and thinks he might have an opinion,
> could you forward the original email?
Done. Fished his Gmail address from LinkedIn.
> Arnd
WBR, Sergei
^ permalink raw reply
* [PATCH v3 0/9] Use regmap+devm+DT in pm8xxx input drivers
From: Stephen Boyd @ 2014-02-26 19:05 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-input,
devicetree
These patches move the pm8xxx input drivers over to use devm_* APIs
and regmap. This breaks the dependency of these drivers on the pm8xxx
specific read/write calls and also simplifies the probe code a bit.
Finally we add devicetree support to these drivers so they can be probed
on the platforms that are supported upstream.
Changes since v2:
* Rebased to v3.14-rc3
Changes since v1:
* Picked up Dmitry's version of devm for pwrkey
* Added DT bindings and parsing patches
* Dropped patches picked up by Dmitry
Stephen Boyd (9):
Input: pmic8xxx-pwrkey - Migrate to regmap APIs
Input: pmic8xxx-keypad - Migrate to devm_* APIs
Input: pmic8xxx-keypad - Migrate to regmap APIs
Input: pmic8xxx-pwrkey - Migrate to DT
Input: pm8xxx-vibrator - Add DT match table
Input: pmic8xxx-keypad - Migrate to DT
devicetree: bindings: Document PM8921/8058 keypads
devicetree: bindings: Document PM8921/8058 power keys
devicetree: bindings: Document PM8921/8058 vibrators
.../bindings/input/qcom,pm8xxx-keypad.txt | 72 +++++
.../bindings/input/qcom,pm8xxx-pwrkey.txt | 39 +++
.../devicetree/bindings/input/qcom,pm8xxx-vib.txt | 16 ++
drivers/input/keyboard/pmic8xxx-keypad.c | 291 ++++++++++-----------
drivers/input/misc/pm8xxx-vibrator.c | 8 +
drivers/input/misc/pmic8xxx-pwrkey.c | 37 ++-
include/linux/input/pmic8xxx-keypad.h | 52 ----
include/linux/input/pmic8xxx-pwrkey.h | 31 ---
8 files changed, 290 insertions(+), 256 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
create mode 100644 Documentation/devicetree/bindings/input/qcom,pm8xxx-pwrkey.txt
create mode 100644 Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.txt
delete mode 100644 include/linux/input/pmic8xxx-keypad.h
delete mode 100644 include/linux/input/pmic8xxx-pwrkey.h
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH v2 3/8] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
From: Felipe Balbi @ 2014-02-26 15:41 UTC (permalink / raw)
To: Roger Quadros
Cc: dmitry.torokhov, rydberg, jcbian, balbi, dmurphy, mugunthanvnm,
linux-input, linux-kernel, devicetree
In-Reply-To: <1393428486-15001-4-git-send-email-rogerq@ti.com>
[-- Attachment #1: Type: text/plain, Size: 271 bytes --]
On Wed, Feb 26, 2014 at 05:28:01PM +0200, Roger Quadros wrote:
> Get rid of the attb_read_val() platform hook. Instead,
> read the ATTB gpio directly from the driver.
>
> Fail if valid ATTB gpio is not provided by patform data.
s/patform/platform/
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* [PATCH v2 7/8] Input: pixcir_i2c_ts: Add device tree support
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Provide device tree support and binding information.
Also provide support for a new chip "pixcir_tangoc".
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
.../bindings/input/touchscreen/pixcir_i2c_ts.txt | 26 ++++++++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
drivers/input/touchscreen/pixcir_i2c_ts.c | 78 ++++++++++++++++++++++
3 files changed, 105 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
diff --git a/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
new file mode 100644
index 0000000..0ab9505
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
@@ -0,0 +1,26 @@
+* Pixcir I2C touchscreen controllers
+
+Required properties:
+- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- attb-gpio: GPIO connected to the ATTB line of the chip
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+ i2c@00000000 {
+ /* ... */
+
+ pixcir_ts@5c {
+ compatible = "pixcir,pixcir_ts";
+ reg = <0x5c>;
+ interrupts = <2 0>;
+ attb-gpio = <&gpf 2 0 2>;
+ x-size = <800>;
+ y-size = <600>;
+ };
+
+ /* ... */
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 40ce2df..d2324b7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -65,6 +65,7 @@ onnn ON Semiconductor Corp.
panasonic Panasonic Corporation
phytec PHYTEC Messtechnik GmbH
picochip Picochip Ltd
+pixcir PIXCIR MICROELECTRONICS Co., Ltd
powervr PowerVR (deprecated, use img)
qca Qualcomm Atheros, Inc.
qcom Qualcomm Technologies, Inc
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 8ca258b..bb6b42a 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -26,6 +26,9 @@
#include <linux/input/mt.h>
#include <linux/input/pixcir_ts.h>
#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
@@ -404,16 +407,70 @@ unlock:
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
+#ifdef CONFIG_OF
+static const struct of_device_id pixcir_of_match[];
+
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+ struct pixcir_ts_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+
+ const struct of_device_id *match;
+
+ match = of_match_device(of_match_ptr(pixcir_of_match), dev);
+ if (!match)
+ return ERR_PTR(-EINVAL);
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data;
+
+ pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0);
+ /* gpio_attb validity is checked in probe */
+
+ if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+ dev_err(dev, "Failed to get x-size property\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pdata->x_max -= 1;
+
+ if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+ dev_err(dev, "Failed to get y-size property\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pdata->y_max -= 1;
+
+ dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__,
+ pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb);
+
+ return pdata;
+}
+#else
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
static int pixcir_i2c_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev);
struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input;
int error;
+ if (np && !pdata) {
+ pdata = pixcir_parse_dt(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ }
+
if (!pdata) {
dev_err(&client->dev, "platform data not defined\n");
return -EINVAL;
@@ -524,15 +581,36 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
{ "pixcir_ts", 0 },
+ { "pixcir_tangoc", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
+#ifdef CONFIG_OF
+static const struct pixcir_i2c_chip_data pixcir_ts_data = {
+ .max_fingers = 2,
+ /* no hw id support */
+};
+
+static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
+ .max_fingers = 5,
+ .has_hw_ids = true,
+};
+
+static const struct of_device_id pixcir_of_match[] = {
+ { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
+ { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pixcir_of_match);
+#endif
+
static struct i2c_driver pixcir_i2c_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "pixcir_ts",
.pm = &pixcir_dev_pm_ops,
+ .of_match_table = of_match_ptr(pixcir_of_match),
},
.probe = pixcir_i2c_ts_probe,
.remove = pixcir_i2c_ts_remove,
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 5/8] Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided tracking IDs
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Some variants of the Pixcir touch controller support upto 5
simultaneous fingers and hardware tracking IDs. Prepare the driver
for that.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 74 ++++++++++++++++++++++++-------
include/linux/input/pixcir_ts.h | 12 +++++
2 files changed, 69 insertions(+), 17 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 8736f71..b1e92f6 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -27,18 +27,20 @@
#include <linux/input/pixcir_ts.h>
#include <linux/gpio.h>
-#define PIXCIR_MAX_SLOTS 2
+#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
struct pixcir_i2c_ts_data {
struct i2c_client *client;
struct input_dev *input;
- const struct pixcir_ts_platform_data *chip;
+ const struct pixcir_ts_platform_data *pdata;
bool exiting;
+ int max_fingers; /* Max fingers supported in this instance */
};
struct pixcir_touch {
int x;
int y;
+ int id;
};
struct pixcir_report_data {
@@ -49,13 +51,21 @@ struct pixcir_report_data {
static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
struct pixcir_report_data *report)
{
- u8 rdbuf[10], wrbuf[1] = { 0 };
+ u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
+ u8 wrbuf[1] = { 0 };
u8 *bufptr;
u8 touch;
int ret, i;
+ int readsize;
+ const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
memset(report, 0, sizeof(struct pixcir_report_data));
+ i = chip->has_hw_ids ? 1 : 0;
+ readsize = 2 + tsdata->max_fingers * (4 + i);
+ if (readsize > sizeof(rdbuf))
+ readsize = sizeof(rdbuf);
+
ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
if (ret != sizeof(wrbuf)) {
dev_err(&tsdata->client->dev,
@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
return;
}
- ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+ ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
if (ret != sizeof(rdbuf)) {
dev_err(&tsdata->client->dev,
"%s: i2c_master_recv failed(), ret=%d\n",
@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
}
touch = rdbuf[0] & 0x7;
- if (touch > PIXCIR_MAX_SLOTS)
- touch = PIXCIR_MAX_SLOTS;
+ if (touch > tsdata->max_fingers)
+ touch = tsdata->max_fingers;
report->num_touches = touch;
bufptr = &rdbuf[2];
@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
- bufptr = &bufptr[4];
+ if (chip->has_hw_ids) {
+ report->touches[i].id = bufptr[4];
+ bufptr = &bufptr[5];
+ } else {
+ bufptr = &bufptr[4];
+ }
}
}
@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
struct pixcir_touch *touch;
int n, i, slot;
struct device *dev = &ts->client->dev;
+ const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
n = report->num_touches;
if (n > PIXCIR_MAX_SLOTS)
n = PIXCIR_MAX_SLOTS;
- for (i = 0; i < n; i++) {
- touch = &report->touches[i];
- pos[i].x = touch->x;
- pos[i].y = touch->y;
- }
+ if (!chip->has_hw_ids) {
+ for (i = 0; i < n; i++) {
+ touch = &report->touches[i];
+ pos[i].x = touch->x;
+ pos[i].y = touch->y;
+ }
- input_mt_assign_slots(ts->input, slots, pos, n);
+ input_mt_assign_slots(ts->input, slots, pos, n);
+ }
for (i = 0; i < n; i++) {
touch = &report->touches[i];
- slot = slots[i];
+
+ if (chip->has_hw_ids) {
+ slot = input_mt_get_slot_by_key(ts->input, touch->id);
+ if (slot < 0) {
+ dev_dbg(dev, "no free slot for id 0x%x\n",
+ touch->id);
+ continue;
+ }
+ } else {
+ slot = slots[i];
+ }
input_mt_slot(ts->input, slot);
input_mt_report_slot_state(ts->input,
@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{
struct pixcir_i2c_ts_data *tsdata = dev_id;
- const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+ const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
struct pixcir_report_data report;
while (!tsdata->exiting) {
@@ -356,6 +384,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
dev_err(dev, "Invalid gpio_attb in pdata\n");
return -EINVAL;
}
+
+ if (pdata->chip.max_fingers <= 0) {
+ dev_err(dev, "Invalid max_fingers in pdata\n");
+ return -EINVAL;
+ }
}
tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -370,7 +403,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
tsdata->client = client;
tsdata->input = input;
- tsdata->chip = pdata;
+ tsdata->pdata = pdata;
input->name = client->name;
input->id.bustype = BUS_I2C;
@@ -386,7 +419,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
- error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+ tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
+ if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
+ tsdata->max_fingers = PIXCIR_MAX_SLOTS;
+ dev_info(dev, "Limiting maximum fingers to %d\n",
+ tsdata->max_fingers);
+ }
+
+ error = input_mt_init_slots(input, tsdata->max_fingers,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) {
dev_err(dev, "Error initializing Multi-Touch slots\n");
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 160cf35..7bae83b 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -43,10 +43,22 @@ enum pixcir_int_mode {
#define PIXCIR_INT_ENABLE (1UL << 3)
#define PIXCIR_INT_POL_HIGH (1UL << 2)
+/**
+ * struct pixcir_irc_chip_data - chip related data
+ * @max_fingers: Max number of fingers reported simultaneously by h/w
+ * @has_hw_ids: Hardware supports finger tracking IDs
+ *
+ */
+struct pixcir_i2c_chip_data {
+ u8 max_fingers;
+ bool has_hw_ids;
+};
+
struct pixcir_ts_platform_data {
int x_max;
int y_max;
int gpio_attb; /* GPIO connected to ATTB line */
+ struct pixcir_i2c_chip_data chip;
};
#endif
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 1/8] Input: pixcir_i2c_ts: Use devres managed resource allocations
From: Roger Quadros @ 2014-02-26 15:27 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Use devm_() and friends for allocating memory, input device
and IRQ.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 34 ++++++++++++-------------------
1 file changed, 13 insertions(+), 21 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 02392d2..38e83a2 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -130,6 +130,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
{
const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev);
+ struct device *dev = &client->dev;
struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input;
int error;
@@ -139,12 +140,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return -EINVAL;
}
- tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
- input = input_allocate_device();
- if (!tsdata || !input) {
- dev_err(&client->dev, "Failed to allocate driver data!\n");
- error = -ENOMEM;
- goto err_free_mem;
+ tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
+ if (!tsdata)
+ return -ENOMEM;
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(&client->dev, "Failed to allocate input device\n");
+ return -ENOMEM;
}
tsdata->client = client;
@@ -165,29 +168,22 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_drvdata(input, tsdata);
- error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
+ error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, tsdata);
if (error) {
- dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
- goto err_free_mem;
+ dev_err(dev, "failed to request irq %d\n", client->irq);
+ return error;
}
error = input_register_device(input);
if (error)
- goto err_free_irq;
+ return error;
i2c_set_clientdata(client, tsdata);
device_init_wakeup(&client->dev, 1);
return 0;
-
-err_free_irq:
- free_irq(client->irq, tsdata);
-err_free_mem:
- input_free_device(input);
- kfree(tsdata);
- return error;
}
static int pixcir_i2c_ts_remove(struct i2c_client *client)
@@ -198,10 +194,6 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
tsdata->exiting = true;
mb();
- free_irq(client->irq, tsdata);
-
- input_unregister_device(tsdata->input);
- kfree(tsdata);
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 8/8] ARM: dts: am43x-epos-evm: Correct Touch controller info
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros, Benoit Cousson,
Tony Lindgren
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Fixup Y resolution and add default pin state. Also update
the compatible id.
CC: Benoit Cousson <bcousson@baylibre.com>
CC: Tony Lindgren <tony@atomide.com>
CC: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
arch/arm/boot/dts/am43x-epos-evm.dts | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index fbf9c4c..6c8efcf 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -79,6 +79,13 @@
0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
+
+ pixcir_ts_pins: pixcir_ts_pins {
+ pinctrl-single,pins = <
+ 0x44 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a1.gpio1_17 */
+ >;
+ };
+
};
matrix_keypad: matrix_keypad@0 {
@@ -157,7 +164,9 @@
};
pixcir_ts@5c {
- compatible = "pixcir,pixcir_ts";
+ compatible = "pixcir,pixcir_tangoc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pixcir_ts_pins>;
reg = <0x5c>;
interrupt-parent = <&gpio1>;
interrupts = <17 0>;
@@ -165,7 +174,7 @@
attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
x-size = <1024>;
- y-size = <768>;
+ y-size = <600>;
};
};
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 6/8] Input: pixcir_i2c_ts: Implement wakeup from suspend
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Improve the suspend and resume handlers to allow the device
to wakeup the system from suspend.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 46 ++++++++++++++++++++++++++++---
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index b1e92f6..8ca258b 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -345,21 +345,59 @@ static void pixcir_input_close(struct input_dev *dev)
static int pixcir_i2c_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+ struct input_dev *input = ts->input;
+ int ret = 0;
+
+ mutex_lock(&input->mutex);
+
+ if (device_may_wakeup(&client->dev)) {
+ /* need to start device if not open, to be wakeup source */
+ if (!input->users) {
+ ret = pixcir_start(ts);
+ if (ret)
+ goto unlock;
+ }
- if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
- return 0;
+ } else if (input->users) {
+ ret = pixcir_stop(ts);
+ }
+
+unlock:
+ mutex_unlock(&input->mutex);
+
+ return ret;
}
static int pixcir_i2c_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+ struct input_dev *input = ts->input;
+ int ret = 0;
+
+ mutex_lock(&input->mutex);
- if (device_may_wakeup(&client->dev))
+ if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq);
- return 0;
+ /* need to stop device if it was not open on suspend */
+ if (!input->users) {
+ ret = pixcir_stop(ts);
+ if (ret)
+ goto unlock;
+ }
+
+ } else if (input->users) {
+ ret = pixcir_start(ts);
+ }
+
+unlock:
+ mutex_unlock(&input->mutex);
+
+ return ret;
}
#endif
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 4/8] Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w
Cc: rydberg-Hk7bIW8heu4wFerOooGFRg, jcbian-mY6CKx1T+M6Pt1CcHtbs0g,
balbi-l0cyMroinI0, dmurphy-l0cyMroinI0, mugunthanvnm-l0cyMroinI0,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq-l0cyMroinI0@public.gmane.org>
Switch to using the Type-B Multi-Touch protocol.
Signed-off-by: Roger Quadros <rogerq-l0cyMroinI0@public.gmane.org>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 125 ++++++++++++++++++++++--------
1 file changed, 94 insertions(+), 31 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index fe17b41..8736f71 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -23,9 +23,12 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/input/pixcir_ts.h>
#include <linux/gpio.h>
+#define PIXCIR_MAX_SLOTS 2
+
struct pixcir_i2c_ts_data {
struct i2c_client *client;
struct input_dev *input;
@@ -33,12 +36,25 @@ struct pixcir_i2c_ts_data {
bool exiting;
};
-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+struct pixcir_touch {
+ int x;
+ int y;
+};
+
+struct pixcir_report_data {
+ int num_touches;
+ struct pixcir_touch touches[PIXCIR_MAX_SLOTS];
+};
+
+static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
+ struct pixcir_report_data *report)
{
- struct pixcir_i2c_ts_data *tsdata = data;
u8 rdbuf[10], wrbuf[1] = { 0 };
+ u8 *bufptr;
u8 touch;
- int ret;
+ int ret, i;
+
+ memset(report, 0, sizeof(struct pixcir_report_data));
ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
if (ret != sizeof(wrbuf)) {
@@ -56,45 +72,85 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
return;
}
- touch = rdbuf[0];
- if (touch) {
- u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
- u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
- u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
- u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
-
- input_report_key(tsdata->input, BTN_TOUCH, 1);
- input_report_abs(tsdata->input, ABS_X, posx1);
- input_report_abs(tsdata->input, ABS_Y, posy1);
-
- input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
- input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
- input_mt_sync(tsdata->input);
-
- if (touch == 2) {
- input_report_abs(tsdata->input,
- ABS_MT_POSITION_X, posx2);
- input_report_abs(tsdata->input,
- ABS_MT_POSITION_Y, posy2);
- input_mt_sync(tsdata->input);
- }
- } else {
- input_report_key(tsdata->input, BTN_TOUCH, 0);
+ touch = rdbuf[0] & 0x7;
+ if (touch > PIXCIR_MAX_SLOTS)
+ touch = PIXCIR_MAX_SLOTS;
+
+ report->num_touches = touch;
+ bufptr = &rdbuf[2];
+
+ for (i = 0; i < touch; i++) {
+ report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
+ report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
+
+ bufptr = &bufptr[4];
}
+}
+
+static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
+ struct pixcir_report_data *report)
+{
+ struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
+ int slots[PIXCIR_MAX_SLOTS];
+ struct pixcir_touch *touch;
+ int n, i, slot;
+ struct device *dev = &ts->client->dev;
- input_sync(tsdata->input);
+ n = report->num_touches;
+ if (n > PIXCIR_MAX_SLOTS)
+ n = PIXCIR_MAX_SLOTS;
+
+ for (i = 0; i < n; i++) {
+ touch = &report->touches[i];
+ pos[i].x = touch->x;
+ pos[i].y = touch->y;
+ }
+
+ input_mt_assign_slots(ts->input, slots, pos, n);
+
+ for (i = 0; i < n; i++) {
+ touch = &report->touches[i];
+ slot = slots[i];
+
+ input_mt_slot(ts->input, slot);
+ input_mt_report_slot_state(ts->input,
+ MT_TOOL_FINGER, true);
+
+ input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x);
+ input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y);
+
+ dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
+ i, slot, touch->x, touch->y);
+ }
+
+ input_mt_sync_frame(ts->input);
+ input_sync(ts->input);
}
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{
struct pixcir_i2c_ts_data *tsdata = dev_id;
const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+ struct pixcir_report_data report;
while (!tsdata->exiting) {
- pixcir_ts_poscheck(tsdata);
-
- if (gpio_get_value(pdata->gpio_attb))
+ /* parse packet */
+ pixcir_ts_parse(tsdata, &report);
+
+ /* report it */
+ pixcir_ts_report(tsdata, &report);
+
+ if (gpio_get_value(pdata->gpio_attb)) {
+ if (report.num_touches) {
+ /*
+ * Last report with no finger up?
+ * Do it now then.
+ */
+ input_mt_sync_frame(tsdata->input);
+ input_sync(tsdata->input);
+ }
break;
+ }
msleep(20);
}
@@ -330,6 +386,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
+ error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error) {
+ dev_err(dev, "Error initializing Multi-Touch slots\n");
+ return error;
+ }
+
input_set_drvdata(input, tsdata);
error = devm_gpio_request_one(dev, pdata->gpio_attb,
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 3/8] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Get rid of the attb_read_val() platform hook. Instead,
read the ATTB gpio directly from the driver.
Fail if valid ATTB gpio is not provided by patform data.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 16 +++++++++++++++-
include/linux/input/pixcir_ts.h | 2 +-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index cce3740..fe17b41 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -24,6 +24,7 @@
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/pixcir_ts.h>
+#include <linux/gpio.h>
struct pixcir_i2c_ts_data {
struct i2c_client *client;
@@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{
struct pixcir_i2c_ts_data *tsdata = dev_id;
+ const struct pixcir_ts_platform_data *pdata = tsdata->chip;
while (!tsdata->exiting) {
pixcir_ts_poscheck(tsdata);
- if (tsdata->chip->attb_read_val())
+ if (gpio_get_value(pdata->gpio_attb))
break;
msleep(20);
@@ -293,6 +295,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
if (!pdata) {
dev_err(&client->dev, "platform data not defined\n");
return -EINVAL;
+ } else {
+ if (!gpio_is_valid(pdata->gpio_attb)) {
+ dev_err(dev, "Invalid gpio_attb in pdata\n");
+ return -EINVAL;
+ }
}
tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -325,6 +332,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_drvdata(input, tsdata);
+ error = devm_gpio_request_one(dev, pdata->gpio_attb,
+ GPIOF_DIR_IN, "pixcir_i2c_attb");
+ if (error) {
+ dev_err(dev, "Failed to request ATTB gpio\n");
+ return error;
+ }
+
error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, tsdata);
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7942804..160cf35 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -44,9 +44,9 @@ enum pixcir_int_mode {
#define PIXCIR_INT_POL_HIGH (1UL << 2)
struct pixcir_ts_platform_data {
- int (*attb_read_val)(void);
int x_max;
int y_max;
+ int gpio_attb; /* GPIO connected to ATTB line */
};
#endif
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 2/8] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
From: Roger Quadros @ 2014-02-26 15:28 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
In-Reply-To: <1393428486-15001-1-git-send-email-rogerq@ti.com>
Introduce helper functions to configure power and interrupt
registers. Default to IDLE mode on probe as device supports
auto wakeup to ACVIE mode on detecting finger touch.
Configure interrupt mode and polarity on start up.
Power down on device closure or module removal.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/input/touchscreen/pixcir_i2c_ts.c | 173 +++++++++++++++++++++++++++++-
include/linux/input/pixcir_ts.h | 42 ++++++++
2 files changed, 213 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 38e83a2..cce3740 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -100,6 +100,161 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
+ enum pixcir_power_mode mode)
+{
+ struct device *dev = &ts->client->dev;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_POWER_MODE, ret);
+ return ret;
+ }
+
+ ret &= ~PIXCIR_POWER_MODE_MASK;
+ ret |= mode;
+
+ /* Always AUTO_IDLE */
+ ret |= PIXCIR_POWER_ALLOW_IDLE;
+
+ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_POWER_MODE, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Set the interrupt mode for the device i.e. ATTB line behaviour
+ *
+ * @polarity : 1 for active high, 0 for active low.
+ */
+static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
+ enum pixcir_int_mode mode,
+ bool polarity)
+{
+ struct device *dev = &ts->client->dev;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_INT_MODE, ret);
+ return ret;
+ }
+
+ ret &= ~PIXCIR_INT_MODE_MASK;
+ ret |= mode;
+
+ if (polarity)
+ ret |= PIXCIR_INT_POL_HIGH;
+ else
+ ret &= ~PIXCIR_INT_POL_HIGH;
+
+ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_INT_MODE, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Enable/disable interrupt generation
+ */
+static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
+{
+ struct device *dev = &ts->client->dev;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_INT_MODE, ret);
+ return ret;
+ }
+
+ if (enable)
+ ret |= PIXCIR_INT_ENABLE;
+ else
+ ret &= ~PIXCIR_INT_ENABLE;
+
+ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+ if (ret < 0) {
+ dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+ __func__, PIXCIR_REG_INT_MODE, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pixcir_start(struct pixcir_i2c_ts_data *ts)
+{
+ struct device *dev = &ts->client->dev;
+ int ret;
+
+ /* LEVEL_TOUCH interrupt with active low polarity */
+ ret = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
+ if (ret) {
+ dev_err(dev, "Failed to set interrupt mode\n");
+ return ret;
+ }
+
+ ts->exiting = false;
+ mb(); /* Update status before IRQ can fire */
+
+ /* enable interrupt generation */
+ ret = pixcir_int_enable(ts, 1);
+ if (ret) {
+ dev_err(dev, "Failed to enable interrupt generation\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
+{
+ struct device *dev = &ts->client->dev;
+ int ret;
+
+ /* disable interrupt generation */
+ ret = pixcir_int_enable(ts, 0);
+ if (ret) {
+ dev_err(dev, "Failed to disable interrupt generation\n");
+ return ret;
+ }
+
+ synchronize_irq(ts->client->irq);
+ mb(); /* Update status after pending IRQ is complete */
+ ts->exiting = true;
+
+ return 0;
+}
+
+static int pixcir_input_open(struct input_dev *dev)
+{
+ struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+ return pixcir_start(ts);
+}
+
+static void pixcir_input_close(struct input_dev *dev)
+{
+ struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+ pixcir_stop(ts);
+}
+
+
#ifdef CONFIG_PM_SLEEP
static int pixcir_i2c_ts_suspend(struct device *dev)
{
@@ -157,6 +312,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input->name = client->name;
input->id.bustype = BUS_I2C;
input->dev.parent = &client->dev;
+ input->open = pixcir_input_open;
+ input->close = pixcir_input_close;
__set_bit(EV_KEY, input->evbit);
__set_bit(EV_ABS, input->evbit);
@@ -176,6 +333,18 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return error;
}
+ /* Always be in IDLE mode to save power, device supports auto wake */
+ error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
+ if (error) {
+ dev_err(dev, "Failed to set IDLE mode\n");
+ return error;
+ }
+
+ /* Stop device till opened */
+ error = pixcir_stop(tsdata);
+ if (error)
+ return error;
+
error = input_register_device(input);
if (error)
return error;
@@ -192,8 +361,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
device_init_wakeup(&client->dev, 0);
- tsdata->exiting = true;
- mb();
+ if (!tsdata->exiting)
+ pixcir_stop(tsdata);
return 0;
}
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7163d91..7942804 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -1,6 +1,48 @@
#ifndef _PIXCIR_I2C_TS_H
#define _PIXCIR_I2C_TS_H
+/*
+ * Register map
+ */
+#define PIXCIR_REG_POWER_MODE 51
+#define PIXCIR_REG_INT_MODE 52
+
+/*
+ * Power modes:
+ * active: max scan speed
+ * idle: lower scan speed with automatic transition to active on touch
+ * halt: datasheet says sleep but this is more like halt as the chip
+ * clocks are cut and it can only be brought out of this mode
+ * using the RESET pin.
+ */
+enum pixcir_power_mode {
+ PIXCIR_POWER_ACTIVE,
+ PIXCIR_POWER_IDLE,
+ PIXCIR_POWER_HALT,
+};
+
+#define PIXCIR_POWER_MODE_MASK 0x03
+#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
+
+/*
+ * Interrupt modes:
+ * periodical: interrupt is asserted periodicaly
+ * diff coordinates: interrupt is asserted when coordinates change
+ * level on touch: interrupt level asserted during touch
+ * pulse on touch: interrupt pulse asserted druing touch
+ *
+ */
+enum pixcir_int_mode {
+ PIXCIR_INT_PERIODICAL,
+ PIXCIR_INT_DIFF_COORD,
+ PIXCIR_INT_LEVEL_TOUCH,
+ PIXCIR_INT_PULSE_TOUCH,
+};
+
+#define PIXCIR_INT_MODE_MASK 0x03
+#define PIXCIR_INT_ENABLE (1UL << 3)
+#define PIXCIR_INT_POL_HIGH (1UL << 2)
+
struct pixcir_ts_platform_data {
int (*attb_read_val)(void);
int x_max;
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 0/8] Input: pixcir_i2c_ts: Add Type-B Multi-touch and DT support
From: Roger Quadros @ 2014-02-26 15:27 UTC (permalink / raw)
To: dmitry.torokhov
Cc: rydberg, jcbian, balbi, dmurphy, mugunthanvnm, linux-input,
linux-kernel, devicetree, Roger Quadros
Hi,
This series does the following
- use devres managed resource allocations
- convert to Type-B multi touch protocol
- support upto 5 fingers with hardware supplied tracking IDs
- device tree support
Changelog:
v2:
- Addressed review comments and re-arranged patch order
v1:
- http://article.gmane.org/gmane.linux.kernel/1616417
cheers,
-roger
---
Roger Quadros (8):
Input: pixcir_i2c_ts: Use devres managed resource allocations
Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided
tracking IDs
Input: pixcir_i2c_ts: Implement wakeup from suspend
Input: pixcir_i2c_ts: Add device tree support
ARM: dts: am43x-epos-evm: Correct Touch controller info
.../bindings/input/touchscreen/pixcir_i2c_ts.txt | 26 ++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/arm/boot/dts/am43x-epos-evm.dts | 13 +-
drivers/input/touchscreen/pixcir_i2c_ts.c | 510 ++++++++++++++++++---
include/linux/input/pixcir_ts.h | 56 ++-
5 files changed, 545 insertions(+), 61 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
--
1.8.3.2
^ permalink raw reply
* Re: [PATCH 0/5] ARM: davinci: tnetv107x removal
From: Arnd Bergmann @ 2014-02-26 13:46 UTC (permalink / raw)
To: linux-arm-kernel, Alexandre Courbot
Cc: linux-kernel, Sekhar Nori, Kevin Hilman,
davinci-linux-open-source, Dmitry Torokhov, Lee Jones,
Linus Walleij, Mark Brown, Samuel Ortiz, linux-gpio, linux-input,
linux-spi
In-Reply-To: <1393418614-3968549-1-git-send-email-arnd@arndb.de>
On Wednesday 26 February 2014, Arnd Bergmann wrote:
> The five patches are completely independent of one another,
> and applying them out of order is fine since we just want
> to remove the code. However, I'm looking for an Ack from
> Cyril Chemparathy and Sekhar Nori first, to be sure we
> won't need this code in the future. Kevin Hilman has
> already mentioned that he sees no reason to keep this
> code.
Hmm, apparently Cyril is no longer at TI. If anyone has his
current email address and thinks he might have an opinion,
could you forward the original email?
Arnd
^ permalink raw reply
* [PATCH 5/5] input: remove obsolete tnetv107x drivers
From: Arnd Bergmann @ 2014-02-26 12:43 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, Sekhar Nori, Kevin Hilman,
davinci-linux-open-source, Cyril Chemparathy, Arnd Bergmann,
Dmitry Torokhov, linux-input
In-Reply-To: <1393418614-3968549-1-git-send-email-arnd@arndb.de>
The tnetv107x platform is getting removed, so the touchscreen
and keypad drivers for this platform will no longer be needed
either.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/keyboard/Kconfig | 10 -
drivers/input/keyboard/Makefile | 1 -
drivers/input/keyboard/tnetv107x-keypad.c | 329 -------------------------
drivers/input/touchscreen/Kconfig | 9 -
drivers/input/touchscreen/Makefile | 1 -
drivers/input/touchscreen/tnetv107x-ts.c | 384 ------------------------------
6 files changed, 734 deletions(-)
delete mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
delete mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a673c9f..935dcaf 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -595,16 +595,6 @@ config KEYBOARD_TC3589X
To compile this driver as a module, choose M here: the
module will be called tc3589x-keypad.
-config KEYBOARD_TNETV107X
- tristate "TI TNETV107X keypad support"
- depends on ARCH_DAVINCI_TNETV107X
- select INPUT_MATRIXKMAP
- help
- Say Y here if you want to use the TNETV107X keypad.
-
- To compile this driver as a module, choose M here: the
- module will be called tnetv107x-keypad.
-
config KEYBOARD_TWL4030
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
depends on TWL4030_CORE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a699b61..81014d9 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -53,7 +53,6 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
-obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
deleted file mode 100644
index 086511c..0000000
--- a/drivers/input/keyboard/tnetv107x-keypad.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Texas Instruments TNETV107X Keypad Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/module.h>
-
-#define BITS(x) (BIT(x) - 1)
-
-#define KEYPAD_ROWS 9
-#define KEYPAD_COLS 9
-
-#define DEBOUNCE_MIN 0x400ul
-#define DEBOUNCE_MAX 0x3ffffffful
-
-struct keypad_regs {
- u32 rev;
- u32 mode;
- u32 mask;
- u32 pol;
- u32 dclock;
- u32 rclock;
- u32 stable_cnt;
- u32 in_en;
- u32 out;
- u32 out_en;
- u32 in;
- u32 lock;
- u32 pres[3];
-};
-
-#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg)
-#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg)
-
-struct keypad_data {
- struct input_dev *input_dev;
- struct resource *res;
- struct keypad_regs __iomem *regs;
- struct clk *clk;
- struct device *dev;
- spinlock_t lock;
- int irq_press;
- int irq_release;
- int rows, cols, row_shift;
- int debounce_ms, active_low;
- u32 prev_keys[3];
- unsigned short keycodes[];
-};
-
-static irqreturn_t keypad_irq(int irq, void *data)
-{
- struct keypad_data *kp = data;
- int i, bit, val, row, col, code;
- unsigned long flags;
- u32 curr_keys[3];
- u32 change;
-
- spin_lock_irqsave(&kp->lock, flags);
-
- memset(curr_keys, 0, sizeof(curr_keys));
- if (irq == kp->irq_press)
- for (i = 0; i < 3; i++)
- curr_keys[i] = keypad_read(kp, pres[i]);
-
- for (i = 0; i < 3; i++) {
- change = curr_keys[i] ^ kp->prev_keys[i];
-
- while (change) {
- bit = fls(change) - 1;
- change ^= BIT(bit);
- val = curr_keys[i] & BIT(bit);
- bit += i * 32;
- row = bit / KEYPAD_COLS;
- col = bit % KEYPAD_COLS;
-
- code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
- input_event(kp->input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(kp->input_dev, kp->keycodes[code],
- val);
- }
- }
- input_sync(kp->input_dev);
- memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys));
-
- if (irq == kp->irq_press)
- keypad_write(kp, lock, 0); /* Allow hardware updates */
-
- spin_unlock_irqrestore(&kp->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-static int keypad_start(struct input_dev *dev)
-{
- struct keypad_data *kp = input_get_drvdata(dev);
- unsigned long mask, debounce, clk_rate_khz;
- unsigned long flags;
-
- clk_enable(kp->clk);
- clk_rate_khz = clk_get_rate(kp->clk) / 1000;
-
- spin_lock_irqsave(&kp->lock, flags);
-
- /* Initialize device registers */
- keypad_write(kp, mode, 0);
-
- mask = BITS(kp->rows) << KEYPAD_COLS;
- mask |= BITS(kp->cols);
- keypad_write(kp, mask, ~mask);
-
- keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff);
- keypad_write(kp, stable_cnt, 3);
-
- debounce = kp->debounce_ms * clk_rate_khz;
- debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX);
- keypad_write(kp, dclock, debounce);
- keypad_write(kp, rclock, 4 * debounce);
-
- keypad_write(kp, in_en, 1);
-
- spin_unlock_irqrestore(&kp->lock, flags);
-
- return 0;
-}
-
-static void keypad_stop(struct input_dev *dev)
-{
- struct keypad_data *kp = input_get_drvdata(dev);
-
- synchronize_irq(kp->irq_press);
- synchronize_irq(kp->irq_release);
- clk_disable(kp->clk);
-}
-
-static int keypad_probe(struct platform_device *pdev)
-{
- const struct matrix_keypad_platform_data *pdata;
- const struct matrix_keymap_data *keymap_data;
- struct device *dev = &pdev->dev;
- struct keypad_data *kp;
- int error = 0, sz, row_shift;
- u32 rev = 0;
-
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- dev_err(dev, "cannot find device data\n");
- return -EINVAL;
- }
-
- keymap_data = pdata->keymap_data;
- if (!keymap_data) {
- dev_err(dev, "cannot find keymap data\n");
- return -EINVAL;
- }
-
- row_shift = get_count_order(pdata->num_col_gpios);
- sz = offsetof(struct keypad_data, keycodes);
- sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]);
- kp = kzalloc(sz, GFP_KERNEL);
- if (!kp) {
- dev_err(dev, "cannot allocate device info\n");
- return -ENOMEM;
- }
-
- kp->dev = dev;
- kp->rows = pdata->num_row_gpios;
- kp->cols = pdata->num_col_gpios;
- kp->row_shift = row_shift;
- platform_set_drvdata(pdev, kp);
- spin_lock_init(&kp->lock);
-
- kp->irq_press = platform_get_irq_byname(pdev, "press");
- kp->irq_release = platform_get_irq_byname(pdev, "release");
- if (kp->irq_press < 0 || kp->irq_release < 0) {
- dev_err(dev, "cannot determine device interrupts\n");
- error = -ENODEV;
- goto error_res;
- }
-
- kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!kp->res) {
- dev_err(dev, "cannot determine register area\n");
- error = -ENODEV;
- goto error_res;
- }
-
- if (!request_mem_region(kp->res->start, resource_size(kp->res),
- pdev->name)) {
- dev_err(dev, "cannot claim register memory\n");
- kp->res = NULL;
- error = -EINVAL;
- goto error_res;
- }
-
- kp->regs = ioremap(kp->res->start, resource_size(kp->res));
- if (!kp->regs) {
- dev_err(dev, "cannot map register memory\n");
- error = -ENOMEM;
- goto error_map;
- }
-
- kp->clk = clk_get(dev, NULL);
- if (IS_ERR(kp->clk)) {
- dev_err(dev, "cannot claim device clock\n");
- error = PTR_ERR(kp->clk);
- goto error_clk;
- }
-
- error = request_threaded_irq(kp->irq_press, NULL, keypad_irq,
- IRQF_ONESHOT, dev_name(dev), kp);
- if (error < 0) {
- dev_err(kp->dev, "Could not allocate keypad press key irq\n");
- goto error_irq_press;
- }
-
- error = request_threaded_irq(kp->irq_release, NULL, keypad_irq,
- IRQF_ONESHOT, dev_name(dev), kp);
- if (error < 0) {
- dev_err(kp->dev, "Could not allocate keypad release key irq\n");
- goto error_irq_release;
- }
-
- kp->input_dev = input_allocate_device();
- if (!kp->input_dev) {
- dev_err(dev, "cannot allocate input device\n");
- error = -ENOMEM;
- goto error_input;
- }
-
- kp->input_dev->name = pdev->name;
- kp->input_dev->dev.parent = &pdev->dev;
- kp->input_dev->open = keypad_start;
- kp->input_dev->close = keypad_stop;
-
- clk_enable(kp->clk);
- rev = keypad_read(kp, rev);
- kp->input_dev->id.bustype = BUS_HOST;
- kp->input_dev->id.product = ((rev >> 8) & 0x07);
- kp->input_dev->id.version = ((rev >> 16) & 0xfff);
- clk_disable(kp->clk);
-
- error = matrix_keypad_build_keymap(keymap_data, NULL,
- kp->rows, kp->cols,
- kp->keycodes, kp->input_dev);
- if (error) {
- dev_err(dev, "Failed to build keymap\n");
- goto error_reg;
- }
-
- if (!pdata->no_autorepeat)
- kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
- input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
-
- input_set_drvdata(kp->input_dev, kp);
-
- error = input_register_device(kp->input_dev);
- if (error < 0) {
- dev_err(dev, "Could not register input device\n");
- goto error_reg;
- }
-
- return 0;
-
-
-error_reg:
- input_free_device(kp->input_dev);
-error_input:
- free_irq(kp->irq_release, kp);
-error_irq_release:
- free_irq(kp->irq_press, kp);
-error_irq_press:
- clk_put(kp->clk);
-error_clk:
- iounmap(kp->regs);
-error_map:
- release_mem_region(kp->res->start, resource_size(kp->res));
-error_res:
- kfree(kp);
- return error;
-}
-
-static int keypad_remove(struct platform_device *pdev)
-{
- struct keypad_data *kp = platform_get_drvdata(pdev);
-
- free_irq(kp->irq_press, kp);
- free_irq(kp->irq_release, kp);
- input_unregister_device(kp->input_dev);
- clk_put(kp->clk);
- iounmap(kp->regs);
- release_mem_region(kp->res->start, resource_size(kp->res));
- kfree(kp);
-
- return 0;
-}
-
-static struct platform_driver keypad_driver = {
- .probe = keypad_probe,
- .remove = keypad_remove,
- .driver.name = "tnetv107x-keypad",
- .driver.owner = THIS_MODULE,
-};
-module_platform_driver(keypad_driver);
-
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_DESCRIPTION("TNETV107X Keypad Driver");
-MODULE_ALIAS("platform:tnetv107x-keypad");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 07e9e82..68edc9d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -514,15 +514,6 @@ config TOUCHSCREEN_MIGOR
To compile this driver as a module, choose M here: the
module will be called migor_ts.
-config TOUCHSCREEN_TNETV107X
- tristate "TI TNETV107X touchscreen support"
- depends on ARCH_DAVINCI_TNETV107X
- help
- Say Y here if you want to use the TNETV107X touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called tnetv107x-ts.
-
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62801f2..4bc954b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
-obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
deleted file mode 100644
index c47827a..0000000
--- a/drivers/input/touchscreen/tnetv107x-ts.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Texas Instruments TNETV107X Touchscreen Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; 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/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-
-#include <mach/tnetv107x.h>
-
-#define TSC_PENUP_POLL (HZ / 5)
-#define IDLE_TIMEOUT 100 /* msec */
-
-/*
- * The first and last samples of a touch interval are usually garbage and need
- * to be filtered out with these devices. The following definitions control
- * the number of samples skipped.
- */
-#define TSC_HEAD_SKIP 1
-#define TSC_TAIL_SKIP 1
-#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
-#define TSC_SAMPLES (TSC_SKIP + 1)
-
-/* Register Offsets */
-struct tsc_regs {
- u32 rev;
- u32 tscm;
- u32 bwcm;
- u32 swc;
- u32 adcchnl;
- u32 adcdata;
- u32 chval[4];
-};
-
-/* TSC Mode Configuration Register (tscm) bits */
-#define WMODE BIT(0)
-#define TSKIND BIT(1)
-#define ZMEASURE_EN BIT(2)
-#define IDLE BIT(3)
-#define TSC_EN BIT(4)
-#define STOP BIT(5)
-#define ONE_SHOT BIT(6)
-#define SINGLE BIT(7)
-#define AVG BIT(8)
-#define AVGNUM(x) (((x) & 0x03) << 9)
-#define PVSTC(x) (((x) & 0x07) << 11)
-#define PON BIT(14)
-#define PONBG BIT(15)
-#define AFERST BIT(16)
-
-/* ADC DATA Capture Register bits */
-#define DATA_VALID BIT(16)
-
-/* Register Access Macros */
-#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg)
-#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg);
-#define tsc_set_bits(ts, reg, val) \
- tsc_write(ts, reg, tsc_read(ts, reg) | (val))
-#define tsc_clr_bits(ts, reg, val) \
- tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
-
-struct sample {
- int x, y, p;
-};
-
-struct tsc_data {
- struct input_dev *input_dev;
- struct resource *res;
- struct tsc_regs __iomem *regs;
- struct timer_list timer;
- spinlock_t lock;
- struct clk *clk;
- struct device *dev;
- int sample_count;
- struct sample samples[TSC_SAMPLES];
- int tsc_irq;
-};
-
-static int tsc_read_sample(struct tsc_data *ts, struct sample* sample)
-{
- int x, y, z1, z2, t, p = 0;
- u32 val;
-
- val = tsc_read(ts, chval[0]);
- if (val & DATA_VALID)
- x = val & 0xffff;
- else
- return -EINVAL;
-
- y = tsc_read(ts, chval[1]) & 0xffff;
- z1 = tsc_read(ts, chval[2]) & 0xffff;
- z2 = tsc_read(ts, chval[3]) & 0xffff;
-
- if (z1) {
- t = ((600 * x) * (z2 - z1));
- p = t / (u32) (z1 << 12);
- if (p < 0)
- p = 0;
- }
-
- sample->x = x;
- sample->y = y;
- sample->p = p;
-
- return 0;
-}
-
-static void tsc_poll(unsigned long data)
-{
- struct tsc_data *ts = (struct tsc_data *)data;
- unsigned long flags;
- int i, val, x, y, p;
-
- spin_lock_irqsave(&ts->lock, flags);
-
- if (ts->sample_count >= TSC_SKIP) {
- input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
- input_report_key(ts->input_dev, BTN_TOUCH, 0);
- input_sync(ts->input_dev);
- } else if (ts->sample_count > 0) {
- /*
- * A touch event lasted less than our skip count. Salvage and
- * report anyway.
- */
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].x;
- x = val / ts->sample_count;
-
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].y;
- y = val / ts->sample_count;
-
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].p;
- p = val / ts->sample_count;
-
- input_report_abs(ts->input_dev, ABS_X, x);
- input_report_abs(ts->input_dev, ABS_Y, y);
- input_report_abs(ts->input_dev, ABS_PRESSURE, p);
- input_report_key(ts->input_dev, BTN_TOUCH, 1);
- input_sync(ts->input_dev);
- }
-
- ts->sample_count = 0;
-
- spin_unlock_irqrestore(&ts->lock, flags);
-}
-
-static irqreturn_t tsc_irq(int irq, void *dev_id)
-{
- struct tsc_data *ts = (struct tsc_data *)dev_id;
- struct sample *sample;
- int index;
-
- spin_lock(&ts->lock);
-
- index = ts->sample_count % TSC_SAMPLES;
- sample = &ts->samples[index];
- if (tsc_read_sample(ts, sample) < 0)
- goto out;
-
- if (++ts->sample_count >= TSC_SKIP) {
- index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
- sample = &ts->samples[index];
-
- input_report_abs(ts->input_dev, ABS_X, sample->x);
- input_report_abs(ts->input_dev, ABS_Y, sample->y);
- input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p);
- if (ts->sample_count == TSC_SKIP)
- input_report_key(ts->input_dev, BTN_TOUCH, 1);
- input_sync(ts->input_dev);
- }
- mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
-out:
- spin_unlock(&ts->lock);
- return IRQ_HANDLED;
-}
-
-static int tsc_start(struct input_dev *dev)
-{
- struct tsc_data *ts = input_get_drvdata(dev);
- unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT);
- u32 val;
-
- clk_enable(ts->clk);
-
- /* Go to idle mode, before any initialization */
- while (time_after(timeout, jiffies)) {
- if (tsc_read(ts, tscm) & IDLE)
- break;
- }
-
- if (time_before(timeout, jiffies)) {
- dev_warn(ts->dev, "timeout waiting for idle\n");
- clk_disable(ts->clk);
- return -EIO;
- }
-
- /* Configure TSC Control register*/
- val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
- tsc_write(ts, tscm, val);
-
- /* Bring TSC out of reset: Clear AFE reset bit */
- val &= ~(AFERST);
- tsc_write(ts, tscm, val);
-
- /* Configure all pins for hardware control*/
- tsc_write(ts, bwcm, 0);
-
- /* Finally enable the TSC */
- tsc_set_bits(ts, tscm, TSC_EN);
-
- return 0;
-}
-
-static void tsc_stop(struct input_dev *dev)
-{
- struct tsc_data *ts = input_get_drvdata(dev);
-
- tsc_clr_bits(ts, tscm, TSC_EN);
- synchronize_irq(ts->tsc_irq);
- del_timer_sync(&ts->timer);
- clk_disable(ts->clk);
-}
-
-static int tsc_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct tsc_data *ts;
- int error = 0;
- u32 rev = 0;
-
- ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
- if (!ts) {
- dev_err(dev, "cannot allocate device info\n");
- return -ENOMEM;
- }
-
- ts->dev = dev;
- spin_lock_init(&ts->lock);
- setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
- platform_set_drvdata(pdev, ts);
-
- ts->tsc_irq = platform_get_irq(pdev, 0);
- if (ts->tsc_irq < 0) {
- dev_err(dev, "cannot determine device interrupt\n");
- error = -ENODEV;
- goto error_res;
- }
-
- ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!ts->res) {
- dev_err(dev, "cannot determine register area\n");
- error = -ENODEV;
- goto error_res;
- }
-
- if (!request_mem_region(ts->res->start, resource_size(ts->res),
- pdev->name)) {
- dev_err(dev, "cannot claim register memory\n");
- ts->res = NULL;
- error = -EINVAL;
- goto error_res;
- }
-
- ts->regs = ioremap(ts->res->start, resource_size(ts->res));
- if (!ts->regs) {
- dev_err(dev, "cannot map register memory\n");
- error = -ENOMEM;
- goto error_map;
- }
-
- ts->clk = clk_get(dev, NULL);
- if (IS_ERR(ts->clk)) {
- dev_err(dev, "cannot claim device clock\n");
- error = PTR_ERR(ts->clk);
- goto error_clk;
- }
-
- error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, IRQF_ONESHOT,
- dev_name(dev), ts);
- if (error < 0) {
- dev_err(ts->dev, "Could not allocate ts irq\n");
- goto error_irq;
- }
-
- ts->input_dev = input_allocate_device();
- if (!ts->input_dev) {
- dev_err(dev, "cannot allocate input device\n");
- error = -ENOMEM;
- goto error_input;
- }
- input_set_drvdata(ts->input_dev, ts);
-
- ts->input_dev->name = pdev->name;
- ts->input_dev->id.bustype = BUS_HOST;
- ts->input_dev->dev.parent = &pdev->dev;
- ts->input_dev->open = tsc_start;
- ts->input_dev->close = tsc_stop;
-
- clk_enable(ts->clk);
- rev = tsc_read(ts, rev);
- ts->input_dev->id.product = ((rev >> 8) & 0x07);
- ts->input_dev->id.version = ((rev >> 16) & 0xfff);
- clk_disable(ts->clk);
-
- __set_bit(EV_KEY, ts->input_dev->evbit);
- __set_bit(EV_ABS, ts->input_dev->evbit);
- __set_bit(BTN_TOUCH, ts->input_dev->keybit);
-
- input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0);
- input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0);
- input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
-
- error = input_register_device(ts->input_dev);
- if (error < 0) {
- dev_err(dev, "failed input device registration\n");
- goto error_reg;
- }
-
- return 0;
-
-error_reg:
- input_free_device(ts->input_dev);
-error_input:
- free_irq(ts->tsc_irq, ts);
-error_irq:
- clk_put(ts->clk);
-error_clk:
- iounmap(ts->regs);
-error_map:
- release_mem_region(ts->res->start, resource_size(ts->res));
-error_res:
- kfree(ts);
-
- return error;
-}
-
-static int tsc_remove(struct platform_device *pdev)
-{
- struct tsc_data *ts = platform_get_drvdata(pdev);
-
- input_unregister_device(ts->input_dev);
- free_irq(ts->tsc_irq, ts);
- clk_put(ts->clk);
- iounmap(ts->regs);
- release_mem_region(ts->res->start, resource_size(ts->res));
- kfree(ts);
-
- return 0;
-}
-
-static struct platform_driver tsc_driver = {
- .probe = tsc_probe,
- .remove = tsc_remove,
- .driver.name = "tnetv107x-ts",
- .driver.owner = THIS_MODULE,
-};
-module_platform_driver(tsc_driver);
-
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
-MODULE_ALIAS("platform:tnetv107x-ts");
-MODULE_LICENSE("GPL");
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/5] ARM: davinci: tnetv107x removal
From: Arnd Bergmann @ 2014-02-26 12:43 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Alexandre Courbot, davinci-linux-open-source, Samuel Ortiz,
Arnd Bergmann, Kevin Hilman, Linus Walleij, Dmitry Torokhov,
Sekhar Nori, linux-kernel, linux-spi, linux-gpio, Mark Brown,
Cyril Chemparathy, Lee Jones, linux-input
This series removes the TI davinci/tnetv107x platform that
has evidently bitrotted to the point where it's completely
useless. While we could probably fix it and add a defconfig,
it appears that there are actually no users of this platform,
and it complicates the davinci code base because it's
incompatible with all the other SoCs in there that are
based on ARM926T.
The five patches are completely independent of one another,
and applying them out of order is fine since we just want
to remove the code. However, I'm looking for an Ack from
Cyril Chemparathy and Sekhar Nori first, to be sure we
won't need this code in the future. Kevin Hilman has
already mentioned that he sees no reason to keep this
code.
I can apply the first patch directly into arm-soc once
I have an Ack, and I'd like the other patches to get picked
up by the respective subsystem maintainers.
Arnd
Arnd Bergmann (5):
ARM: davinci: remove tnetv107x support
gpio: remove obsolete tnetv107x driver
spi: remove obsolete spi-ti-ssp driver
mfd: remove obsolete ti-ssp driver
input: remove obsolete tnetv107x drivers
arch/arm/Kconfig.debug | 13 +-
arch/arm/mach-davinci/Kconfig | 12 -
arch/arm/mach-davinci/Makefile | 2 -
arch/arm/mach-davinci/board-tnetv107x-evm.c | 287 ---------
arch/arm/mach-davinci/devices-tnetv107x.c | 434 --------------
arch/arm/mach-davinci/include/mach/cputype.h | 8 -
arch/arm/mach-davinci/include/mach/irqs.h | 97 ---
arch/arm/mach-davinci/include/mach/mux.h | 269 ---------
arch/arm/mach-davinci/include/mach/psc.h | 47 --
arch/arm/mach-davinci/include/mach/serial.h | 8 -
arch/arm/mach-davinci/include/mach/tnetv107x.h | 61 --
arch/arm/mach-davinci/include/mach/uncompress.h | 6 -
arch/arm/mach-davinci/tnetv107x.c | 766 ------------------------
drivers/gpio/Makefile | 1 -
drivers/gpio/gpio-tnetv107x.c | 206 -------
drivers/input/keyboard/Kconfig | 10 -
drivers/input/keyboard/Makefile | 1 -
drivers/input/keyboard/tnetv107x-keypad.c | 329 ----------
drivers/input/touchscreen/Kconfig | 9 -
drivers/input/touchscreen/Makefile | 1 -
drivers/input/touchscreen/tnetv107x-ts.c | 384 ------------
drivers/mfd/Kconfig | 11 -
drivers/mfd/Makefile | 1 -
drivers/mfd/ti-ssp.c | 465 --------------
drivers/spi/Kconfig | 7 -
drivers/spi/Makefile | 1 -
drivers/spi/spi-ti-ssp.c | 378 ------------
include/linux/platform_data/gpio-davinci.h | 4 -
28 files changed, 1 insertion(+), 3817 deletions(-)
delete mode 100644 arch/arm/mach-davinci/board-tnetv107x-evm.c
delete mode 100644 arch/arm/mach-davinci/devices-tnetv107x.c
delete mode 100644 arch/arm/mach-davinci/include/mach/tnetv107x.h
delete mode 100644 arch/arm/mach-davinci/tnetv107x.c
delete mode 100644 drivers/gpio/gpio-tnetv107x.c
delete mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
delete mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
delete mode 100644 drivers/mfd/ti-ssp.c
delete mode 100644 drivers/spi/spi-ti-ssp.c
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: linux-gpio@vger.kernel.org
Cc: linux-input@vger.kernel.org
Cc: linux-spi@vger.kernel.org
--
1.8.3.2
^ permalink raw reply
* Re: [PATCH] hid: fix bug destroying hidraw device files after parent
From: Jiri Kosina @ 2014-02-26 10:02 UTC (permalink / raw)
To: Fernando Luis Vázquez Cao
Cc: linux-input, linux-usb, Nestor Lopez Casado, Greg Kroah-Hartman,
Tejun Heo
In-Reply-To: <1393401084.4876.2.camel@nexus>
On Wed, 26 Feb 2014, Fernando Luis Vázquez Cao wrote:
> I noticed that after hot unplugging a Logitech unifying receiver
> (drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
> stack trace similar to this:
>
> usb 1-1.1.2: USB disconnect, device number 7
> WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
> sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
> [...]
> CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
> Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
> 0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
> ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
> ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
> Call Trace:
> [<ffffffff814cd684>] ? dump_stack+0x41/0x51
> [<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
> [<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
> [<ffffffff81374fd0>] ? device_del+0x40/0x1b0
> [<ffffffff8137516f>] ? device_unregister+0x2f/0x50
> [<ffffffff813751fa>] ? device_destroy+0x3a/0x40
> [<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
> [<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
> [<ffffffff811929da>] ? __fput+0xca/0x210
> [<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
> [<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
> [<ffffffff814dbd22>] ? int_signal+0x12/0x17
Applied, thanks.
I have slightly modified the patch title to make sure that it's obvious
that what it fixes is actually a WARN_ON() splat.
--
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] hid: fix bug destroying hidraw device files after parent
From: David Herrmann @ 2014-02-26 8:59 UTC (permalink / raw)
To: Fernando Luis Vázquez Cao
Cc: Jiri Kosina, open list:HID CORE LAYER, linux-usb@vger.kernel.org,
Nestor Lopez Casado, Greg Kroah-Hartman, Tejun Heo
In-Reply-To: <1393401084.4876.2.camel@nexus>
Hi
On Wed, Feb 26, 2014 at 8:51 AM, Fernando Luis Vázquez Cao
<fernando_b1@lab.ntt.co.jp> wrote:
> I noticed that after hot unplugging a Logitech unifying receiver
> (drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
> stack trace similar to this:
>
> usb 1-1.1.2: USB disconnect, device number 7
> WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
> sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
> [...]
> CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
> Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
> 0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
> ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
> ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
> Call Trace:
> [<ffffffff814cd684>] ? dump_stack+0x41/0x51
> [<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
> [<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
> [<ffffffff81374fd0>] ? device_del+0x40/0x1b0
> [<ffffffff8137516f>] ? device_unregister+0x2f/0x50
> [<ffffffff813751fa>] ? device_destroy+0x3a/0x40
> [<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
> [<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
> [<ffffffff811929da>] ? __fput+0xca/0x210
> [<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
> [<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
> [<ffffffff814dbd22>] ? int_signal+0x12/0x17
> ---[ end trace 63f4a46f6566d737 ]---
>
> During device removal hid_disconnect() is called via hid_hw_stop() to
> stop the device and free all its resources, including the sysfs
> files. The problem is that if a user space process, such as upowerd,
> holds a reference to a hidraw file the corresponding sysfs files will
> be kept around (drop_ref() does not call device_destroy() if the open
> counter is not 0) and it will be usb_disconnect() who, by calling
> device_del() for the USB device, will indirectly remove the sysfs
> files of the hidraw device (sysfs_remove_dir() is recursive these
> days). Because of this, by the time user space releases the last
> reference to the hidraw file and drop_ref() tries to destroy the
> device the sysfs files are already gone and the kernel will print
> the warning above.
>
> Fix this by calling device_destroy() at USB disconnect time.
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
This actually also fixes the issue that the device-node is kept even
though the device is dead. By destroying the "struct device", we make
sure to send out a remove-uevent so udev can drop the node. We
correctly check ->exists during open(), but it is still nice to see
the node go away once that bit is set.
Thanks
David
> Cc: Nestor Lopez Casado <nlopezcasad@logitech.com>
> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
> ---
>
> diff -urNp linux-3.14-rc4-orig/drivers/hid/hidraw.c linux-3.14-rc4/drivers/hid/hidraw.c
> --- linux-3.14-rc4-orig/drivers/hid/hidraw.c 2014-02-26 14:21:48.622980475 +0900
> +++ linux-3.14-rc4/drivers/hid/hidraw.c 2014-02-26 14:22:17.990979556 +0900
> @@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidr
> hid_hw_close(hidraw->hid);
> wake_up_interruptible(&hidraw->wait);
> }
> + device_destroy(hidraw_class,
> + MKDEV(hidraw_major, hidraw->minor));
> } else {
> --hidraw->open;
> }
> if (!hidraw->open) {
> if (!hidraw->exist) {
> - device_destroy(hidraw_class,
> - MKDEV(hidraw_major, hidraw->minor));
> hidraw_table[hidraw->minor] = NULL;
> kfree(hidraw);
> } else {
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] hid: fix bug destroying hidraw device files after parent
From: Nestor Lopez Casado @ 2014-02-26 8:16 UTC (permalink / raw)
To: Fernando Luis Vázquez Cao
Cc: Jiri Kosina, open list:HID CORE LAYER, linux-usb,
Greg Kroah-Hartman, Tejun Heo
In-Reply-To: <530D9E36.7040405@lab.ntt.co.jp>
Hi Fernando,
Why are older kernels not affected ?
-nestor
On Wed, Feb 26, 2014 at 8:56 AM, Fernando Luis Vázquez Cao
<fernando_b1@lab.ntt.co.jp> wrote:
> I forgot to mention that if the fix below is acceptable it
> should be queued for 3.13-stable (older kernels are not
> affected).
>
>
> On 02/26/2014 04:51 PM, Fernando Luis Vázquez Cao wrote:
>>
>> I noticed that after hot unplugging a Logitech unifying receiver
>> (drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
>> stack trace similar to this:
>>
>> usb 1-1.1.2: USB disconnect, device number 7
>> WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
>> sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
>> [...]
>> CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
>> Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
>> 0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
>> ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
>> ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
>> Call Trace:
>> [<ffffffff814cd684>] ? dump_stack+0x41/0x51
>> [<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
>> [<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
>> [<ffffffff81374fd0>] ? device_del+0x40/0x1b0
>> [<ffffffff8137516f>] ? device_unregister+0x2f/0x50
>> [<ffffffff813751fa>] ? device_destroy+0x3a/0x40
>> [<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
>> [<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
>> [<ffffffff811929da>] ? __fput+0xca/0x210
>> [<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
>> [<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
>> [<ffffffff814dbd22>] ? int_signal+0x12/0x17
>> ---[ end trace 63f4a46f6566d737 ]---
>>
>> During device removal hid_disconnect() is called via hid_hw_stop() to
>> stop the device and free all its resources, including the sysfs
>> files. The problem is that if a user space process, such as upowerd,
>> holds a reference to a hidraw file the corresponding sysfs files will
>> be kept around (drop_ref() does not call device_destroy() if the open
>> counter is not 0) and it will be usb_disconnect() who, by calling
>> device_del() for the USB device, will indirectly remove the sysfs
>> files of the hidraw device (sysfs_remove_dir() is recursive these
>> days). Because of this, by the time user space releases the last
>> reference to the hidraw file and drop_ref() tries to destroy the
>> device the sysfs files are already gone and the kernel will print
>> the warning above.
>>
>> Fix this by calling device_destroy() at USB disconnect time.
>>
>> Cc: Nestor Lopez Casado <nlopezcasad@logitech.com>
>> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
>> ---
>>
>> diff -urNp linux-3.14-rc4-orig/drivers/hid/hidraw.c
>> linux-3.14-rc4/drivers/hid/hidraw.c
>> --- linux-3.14-rc4-orig/drivers/hid/hidraw.c 2014-02-26
>> 14:21:48.622980475 +0900
>> +++ linux-3.14-rc4/drivers/hid/hidraw.c 2014-02-26 14:22:17.990979556
>> +0900
>> @@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidr
>> hid_hw_close(hidraw->hid);
>> wake_up_interruptible(&hidraw->wait);
>> }
>> + device_destroy(hidraw_class,
>> + MKDEV(hidraw_major, hidraw->minor));
>> } else {
>> --hidraw->open;
>> }
>> if (!hidraw->open) {
>> if (!hidraw->exist) {
>> - device_destroy(hidraw_class,
>> - MKDEV(hidraw_major,
>> hidraw->minor));
>> hidraw_table[hidraw->minor] = NULL;
>> kfree(hidraw);
>> } else {
>>
>>
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] hid: fix bug destroying hidraw device files after parent
From: Fernando Luis Vázquez Cao @ 2014-02-26 7:51 UTC (permalink / raw)
To: Jiri Kosina
Cc: linux-input, linux-usb, Nestor Lopez Casado, Greg Kroah-Hartman,
Tejun Heo
I noticed that after hot unplugging a Logitech unifying receiver
(drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
stack trace similar to this:
usb 1-1.1.2: USB disconnect, device number 7
WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
[...]
CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
Call Trace:
[<ffffffff814cd684>] ? dump_stack+0x41/0x51
[<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
[<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
[<ffffffff81374fd0>] ? device_del+0x40/0x1b0
[<ffffffff8137516f>] ? device_unregister+0x2f/0x50
[<ffffffff813751fa>] ? device_destroy+0x3a/0x40
[<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
[<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
[<ffffffff811929da>] ? __fput+0xca/0x210
[<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
[<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
[<ffffffff814dbd22>] ? int_signal+0x12/0x17
---[ end trace 63f4a46f6566d737 ]---
During device removal hid_disconnect() is called via hid_hw_stop() to
stop the device and free all its resources, including the sysfs
files. The problem is that if a user space process, such as upowerd,
holds a reference to a hidraw file the corresponding sysfs files will
be kept around (drop_ref() does not call device_destroy() if the open
counter is not 0) and it will be usb_disconnect() who, by calling
device_del() for the USB device, will indirectly remove the sysfs
files of the hidraw device (sysfs_remove_dir() is recursive these
days). Because of this, by the time user space releases the last
reference to the hidraw file and drop_ref() tries to destroy the
device the sysfs files are already gone and the kernel will print
the warning above.
Fix this by calling device_destroy() at USB disconnect time.
Cc: Nestor Lopez Casado <nlopezcasad@logitech.com>
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
---
diff -urNp linux-3.14-rc4-orig/drivers/hid/hidraw.c linux-3.14-rc4/drivers/hid/hidraw.c
--- linux-3.14-rc4-orig/drivers/hid/hidraw.c 2014-02-26 14:21:48.622980475 +0900
+++ linux-3.14-rc4/drivers/hid/hidraw.c 2014-02-26 14:22:17.990979556 +0900
@@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidr
hid_hw_close(hidraw->hid);
wake_up_interruptible(&hidraw->wait);
}
+ device_destroy(hidraw_class,
+ MKDEV(hidraw_major, hidraw->minor));
} else {
--hidraw->open;
}
if (!hidraw->open) {
if (!hidraw->exist) {
- device_destroy(hidraw_class,
- MKDEV(hidraw_major, hidraw->minor));
hidraw_table[hidraw->minor] = NULL;
kfree(hidraw);
} else {
^ permalink raw reply
* Re: [PATCH] hid: fix bug destroying hidraw device files after parent
From: Fernando Luis Vázquez Cao @ 2014-02-26 7:56 UTC (permalink / raw)
To: Jiri Kosina
Cc: linux-input, linux-usb, Nestor Lopez Casado, Greg Kroah-Hartman,
Tejun Heo
In-Reply-To: <1393401084.4876.2.camel@nexus>
I forgot to mention that if the fix below is acceptable it
should be queued for 3.13-stable (older kernels are not
affected).
On 02/26/2014 04:51 PM, Fernando Luis Vázquez Cao wrote:
> I noticed that after hot unplugging a Logitech unifying receiver
> (drivers/hid/hid-logitech-dj.c) the kernel would occasionally spew a
> stack trace similar to this:
>
> usb 1-1.1.2: USB disconnect, device number 7
> WARNING: CPU: 0 PID: 2865 at fs/sysfs/group.c:216 device_del+0x40/0x1b0()
> sysfs group ffffffff8187fa20 not found for kobject 'hidraw0'
> [...]
> CPU: 0 PID: 2865 Comm: upowerd Tainted: G W 3.14.0-rc4 #7
> Hardware name: LENOVO 7783PN4/ , BIOS 9HKT43AUS 07/11/2011
> 0000000000000009 ffffffff814cd684 ffff880427ccfdf8 ffffffff810616e7
> ffff88041ec61800 ffff880427ccfe48 ffff88041e444d80 ffff880426fab8e8
> ffff880429359960 ffffffff8106174c ffffffff81714b98 0000000000000028
> Call Trace:
> [<ffffffff814cd684>] ? dump_stack+0x41/0x51
> [<ffffffff810616e7>] ? warn_slowpath_common+0x77/0x90
> [<ffffffff8106174c>] ? warn_slowpath_fmt+0x4c/0x50
> [<ffffffff81374fd0>] ? device_del+0x40/0x1b0
> [<ffffffff8137516f>] ? device_unregister+0x2f/0x50
> [<ffffffff813751fa>] ? device_destroy+0x3a/0x40
> [<ffffffffa03ca245>] ? drop_ref+0x55/0x120 [hid]
> [<ffffffffa03ca3e6>] ? hidraw_release+0x96/0xb0 [hid]
> [<ffffffff811929da>] ? __fput+0xca/0x210
> [<ffffffff8107fe17>] ? task_work_run+0x97/0xd0
> [<ffffffff810139a9>] ? do_notify_resume+0x69/0xa0
> [<ffffffff814dbd22>] ? int_signal+0x12/0x17
> ---[ end trace 63f4a46f6566d737 ]---
>
> During device removal hid_disconnect() is called via hid_hw_stop() to
> stop the device and free all its resources, including the sysfs
> files. The problem is that if a user space process, such as upowerd,
> holds a reference to a hidraw file the corresponding sysfs files will
> be kept around (drop_ref() does not call device_destroy() if the open
> counter is not 0) and it will be usb_disconnect() who, by calling
> device_del() for the USB device, will indirectly remove the sysfs
> files of the hidraw device (sysfs_remove_dir() is recursive these
> days). Because of this, by the time user space releases the last
> reference to the hidraw file and drop_ref() tries to destroy the
> device the sysfs files are already gone and the kernel will print
> the warning above.
>
> Fix this by calling device_destroy() at USB disconnect time.
>
> Cc: Nestor Lopez Casado <nlopezcasad@logitech.com>
> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
> ---
>
> diff -urNp linux-3.14-rc4-orig/drivers/hid/hidraw.c linux-3.14-rc4/drivers/hid/hidraw.c
> --- linux-3.14-rc4-orig/drivers/hid/hidraw.c 2014-02-26 14:21:48.622980475 +0900
> +++ linux-3.14-rc4/drivers/hid/hidraw.c 2014-02-26 14:22:17.990979556 +0900
> @@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidr
> hid_hw_close(hidraw->hid);
> wake_up_interruptible(&hidraw->wait);
> }
> + device_destroy(hidraw_class,
> + MKDEV(hidraw_major, hidraw->minor));
> } else {
> --hidraw->open;
> }
> if (!hidraw->open) {
> if (!hidraw->exist) {
> - device_destroy(hidraw_class,
> - MKDEV(hidraw_major, hidraw->minor));
> hidraw_table[hidraw->minor] = NULL;
> kfree(hidraw);
> } else {
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] input synaptics-rmi4: Trivial F11 tidy up
From: Christopher Heiny @ 2014-02-25 22:08 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Linux Input, Christopher Heiny, Andrew Duggan, Vincent Huang,
Vivian Ly, Daniel Rosenberg, Linus Walleij
Delete an unused symbol and update copyright date.
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
--
drivers/input/rmi4/rmi_f11.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index 2aa7d17..9cc1406 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2013 Synaptics Incorporated
+ * Copyright (c) 2011-2014 Synaptics Incorporated
* Copyright (c) 2011 Unixphere
*
* This program is free software; you can redistribute it and/or modify it
@@ -7,8 +7,6 @@
* the Free Software Foundation.
*/
-#define FUNCTION_DATA f11_data
-
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/device.h>
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox