commit b98abe52fa8e ("Input: add common DT binding for touchscreens")
introduced common DT bindings for touchscreens [1] and a helper function to
parse the DT.

This has been integrated and interpretation of the inversion (flipping)
properties for the x and y axis has been added to accommodate any
orientation of the touch in relation to the LCD.

By scaling the min/max ADC values to the screen size it is now possible to
pre-calibrate the touch so that is (almost) exactly matches the LCD it is
glued onto. This allows to well enough operate the touch before a user
space calibration can improve the precision.

calculate_pressure has been renamed to calculate_resistance because
that is what it is doing.

[1]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt

Signed-off-by: H. Nikolaus Schaller <h...@goldelico.com>
---
 .../bindings/input/touchscreen/tsc2007.txt         |  20 +--
 drivers/input/touchscreen/tsc2007.c                | 135 +++++++++++++++++----
 include/linux/i2c/tsc2007.h                        |   8 ++
 3 files changed, 135 insertions(+), 28 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt 
b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
index ec365e1..6e9fd55 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
@@ -6,6 +6,7 @@ Required properties:
 - ti,x-plate-ohms: X-plate resistance in ohms.
 
 Optional properties:
+- generic touch screen properties: see touchscreen binding [2].
 - gpios: the interrupt gpio the chip is connected to (trough the penirq pin).
   The penirq pin goes to low when the panel is touched.
   (see GPIO binding[1] for more details).
@@ -13,17 +14,20 @@ Optional properties:
   (see interrupt binding[0]).
 - interrupts: (gpio) interrupt to which the chip is connected
   (see interrupt binding[0]).
-- ti,max-rt: maximum pressure.
-- ti,fuzzx: specifies the absolute input fuzz x value.
-  If set, it will permit noise in the data up to +- the value given to the fuzz
-  parameter, that is used to filter noise from the event stream.
-- ti,fuzzy: specifies the absolute input fuzz y value.
-- ti,fuzzz: specifies the absolute input fuzz z value.
+- ti,max-rt: maximum pressure resistance above which samples are ignored
+  (default: 4095).
+- ti,report-resistance: report resistance (no pressure = max_rt) instead
+  of pressure (no pressure = 0).
+- ti,min-x: minimum value reported by X axis ADC (default 0).
+- ti,max-x: maximum value reported by X axis ADC (default 4095).
+- ti,min-y: minimum value reported by Y axis ADC (default 0).
+- ti,max-y: maximum value reported by Y axis ADC (default 4095).
 - ti,poll-period: how much time to wait (in milliseconds) before reading again 
the
-  values from the tsc2007.
+  values from the tsc2007 (default 1).
 
 [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 [1]: Documentation/devicetree/bindings/gpio/gpio.txt
+[2]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
 
 Example:
        &i2c1 {
@@ -35,6 +39,8 @@ Example:
                        interrupts = <0x0 0x8>;
                        gpios = <&gpio4 0 0>;
                        ti,x-plate-ohms = <180>;
+                       touchscreen-size-x = <640>;
+                       touchscreen-size-y = <480>;
                };
 
                /* ... */
diff --git a/drivers/input/touchscreen/tsc2007.c 
b/drivers/input/touchscreen/tsc2007.c
index 5d0cd51..e0c7173 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -29,6 +29,7 @@
 #include <linux/of_device.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/input/touchscreen.h>
 
 #define TSC2007_MEASURE_TEMP0          (0x0 << 4)
 #define TSC2007_MEASURE_AUX            (0x2 << 4)
@@ -74,6 +75,14 @@ struct tsc2007 {
 
        u16                     model;
        u16                     x_plate_ohms;
+       bool                    swap_xy;
+       bool                    invert_x;
+       bool                    invert_y;
+       bool                    report_resistance;
+       u16                     min_x;
+       u16                     min_y;
+       u16                     max_x;
+       u16                     max_y;
        u16                     max_rt;
        unsigned long           poll_period; /* in jiffies */
        int                     fuzzx;
@@ -128,7 +137,8 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct 
ts_event *tc)
        tsc2007_xfer(tsc, PWRDOWN);
 }
 
-static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
+static u32 tsc2007_calculate_resistance(struct tsc2007 *tsc,
+                                       struct ts_event *tc)
 {
        u32 rt = 0;
 
@@ -177,12 +187,13 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
        struct ts_event tc;
        u32 rt;
 
+       dev_dbg(&ts->client->dev, "soft irq %d\n", irq);
        while (!ts->stopped && tsc2007_is_pen_down(ts)) {
 
                /* pen is down, continue with the measurement */
                tsc2007_read_values(ts, &tc);
 
-               rt = tsc2007_calculate_pressure(ts, &tc);
+               rt = tsc2007_calculate_resistance(ts, &tc);
 
                if (!rt && !ts->get_pendown_state) {
                        /*
@@ -198,6 +209,48 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
                                "DOWN point(%4d,%4d), pressure (%4u)\n",
                                tc.x, tc.y, rt);
 
+                       /* clamp to expected ADC range */
+                       if (tc.x < ts->min_x)
+                               tc.x = ts->min_x;
+                       if (tc.x > ts->max_x)
+                               tc.x = ts->max_x;
+                       if (tc.y < ts->min_y)
+                               tc.y = ts->min_y;
+                       if (tc.y > ts->max_y)
+                               tc.y = ts->max_y;
+
+                       dev_dbg(&ts->client->dev,
+                                       "Clamped point(%4d,%4d), pressure 
(%4u)\n",
+                                       tc.x, tc.y, rt);
+
+                       /* flip */
+                       if (ts->invert_x)
+                               tc.x = (ts->max_x - tc.x) + ts->min_x;
+                       if (ts->invert_y)
+                               tc.y = (ts->max_y - tc.y) + ts->min_y;
+                       if (!ts->report_resistance)
+                               rt = ts->max_rt - rt;
+
+                       dev_dbg(&ts->client->dev,
+                                       "Flipped point(%4d,%4d), pressure 
(%4u)\n",
+                                       tc.x, tc.y, rt);
+
+                       /* scale to desired output range */
+                       tc.x = (input->absinfo[ABS_X].maximum *
+                               (tc.x - ts->min_x)) / (ts->max_x - ts->min_x);
+                       tc.y = (input->absinfo[ABS_Y].maximum *
+                               (tc.y - ts->min_y)) / (ts->max_y - ts->min_y);
+                       rt = (input->absinfo[ABS_PRESSURE].maximum * rt)
+                               / ts->max_rt;
+
+                       /* swap x and y */
+                       if (ts->swap_xy)
+                               swap(tc.x, tc.y);
+
+                       /* report event */
+                       dev_dbg(&ts->client->dev,
+                                       "shaped point(%4d,%4d), pressure 
(%4u)\n",
+                                       tc.x, tc.y, rt);
                        input_report_key(input, BTN_TOUCH, 1);
                        input_report_abs(input, ABS_X, tc.x);
                        input_report_abs(input, ABS_Y, tc.y);
@@ -207,8 +260,8 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 
                } else {
                        /*
-                        * Sample found inconsistent by debouncing or pressure 
is
-                        * beyond the maximum. Don't report it to user space,
+                        * Sample found inconsistent by debouncing or resistance
+                        * is beyond the maximum. Don't report it to user space,
                         * repeat at least once more the measurement.
                         */
                        dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
@@ -233,6 +286,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
 {
        struct tsc2007 *ts = handle;
 
+       dev_dbg(&ts->client->dev, "hard irq %d\n", irq);
        if (tsc2007_is_pen_down(ts))
                return IRQ_WAKE_THREAD;
 
@@ -303,14 +357,25 @@ static int tsc2007_probe_dt(struct i2c_client *client, 
struct tsc2007 *ts)
        else
                ts->max_rt = MAX_12BIT;
 
-       if (!of_property_read_u32(np, "ti,fuzzx", &val32))
-               ts->fuzzx = val32;
+       ts->swap_xy = of_property_read_bool(np, "touchscreen-swapped-x-y");
+       ts->invert_x = of_property_read_bool(np, "touchscreen-inverted-x");
+       ts->invert_y = of_property_read_bool(np, "touchscreen-inverted-y");
+       ts->report_resistance =
+                      of_property_read_bool(np, "ti,report-resistance");
 
-       if (!of_property_read_u32(np, "ti,fuzzy", &val32))
-               ts->fuzzy = val32;
+       if (!of_property_read_u32(np, "ti,min-x", &val32))
+               ts->min_x = val32;
+       if (!of_property_read_u32(np, "ti,max-x", &val32))
+               ts->max_x = val32;
+       else
+               ts->max_x = MAX_12BIT;
 
-       if (!of_property_read_u32(np, "ti,fuzzz", &val32))
-               ts->fuzzz = val32;
+       if (!of_property_read_u32(np, "ti,min-y", &val32))
+               ts->min_y = val32;
+       if (!of_property_read_u32(np, "ti,max-y", &val32))
+               ts->max_y = val32;
+       else
+               ts->max_y = MAX_12BIT;
 
        if (!of_property_read_u64(np, "ti,poll-period", &val64))
                ts->poll_period = msecs_to_jiffies(val64);
@@ -324,6 +389,16 @@ static int tsc2007_probe_dt(struct i2c_client *client, 
struct tsc2007 *ts)
                return -EINVAL;
        }
 
+       dev_dbg(&client->dev,
+                       "min/max_x (%4d,%4d)\n",
+                       ts->min_x, ts->max_x);
+       dev_dbg(&client->dev,
+                       "min/max_y (%4d,%4d)\n",
+                       ts->min_y, ts->max_y);
+       dev_dbg(&client->dev,
+                       "max_rt (%4d)\n",
+                       ts->max_rt);
+
        ts->gpio = of_get_gpio(np, 0);
        if (gpio_is_valid(ts->gpio))
                ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
@@ -332,6 +407,10 @@ static int tsc2007_probe_dt(struct i2c_client *client, 
struct tsc2007 *ts)
                         "GPIO not specified in DT (of_get_gpio returned %d)\n",
                         ts->gpio);
 
+       dev_dbg(&client->dev,
+                       "ts-gpio: %d\n",
+                       ts->gpio);
+
        return 0;
 }
 #else
@@ -349,6 +428,14 @@ static int tsc2007_probe_pdev(struct i2c_client *client, 
struct tsc2007 *ts,
        ts->model             = pdata->model;
        ts->x_plate_ohms      = pdata->x_plate_ohms;
        ts->max_rt            = pdata->max_rt ? : MAX_12BIT;
+       ts->swap_xy           = pdata->swap_xy;
+       ts->invert_x          = pdata->invert_x;
+       ts->invert_y          = pdata->invert_y;
+       ts->report_resistance = pdata->report_resistance;
+       ts->min_x             = pdata->min_x ? : 0;
+       ts->min_y             = pdata->min_y ? : 0;
+       ts->max_x             = pdata->max_x ? : MAX_12BIT;
+       ts->max_y             = pdata->max_y ? : MAX_12BIT;
        ts->poll_period       = msecs_to_jiffies(pdata->poll_period ? : 1);
        ts->get_pendown_state = pdata->get_pendown_state;
        ts->clear_penirq      = pdata->clear_penirq;
@@ -388,13 +475,6 @@ static int tsc2007_probe(struct i2c_client *client,
        if (!ts)
                return -ENOMEM;
 
-       if (pdata)
-               err = tsc2007_probe_pdev(client, ts, pdata, id);
-       else
-               err = tsc2007_probe_dt(client, ts);
-       if (err)
-               return err;
-
        input_dev = devm_input_allocate_device(&client->dev);
        if (!input_dev)
                return -ENOMEM;
@@ -421,10 +501,21 @@ static int tsc2007_probe(struct i2c_client *client,
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
-       input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
-                            ts->fuzzz, 0);
+       if (pdata)
+               err = tsc2007_probe_pdev(client, ts, pdata, id);
+       else
+               err = tsc2007_probe_dt(client, ts);
+       if (err)
+               return err;
+
+       input_set_abs_params(input_dev, ABS_X, 0, ts->max_x-ts->min_x,
+                                                 ts->fuzzx, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, ts->max_y-ts->min_y,
+                                                 ts->fuzzy, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, ts->max_rt,
+                                                 ts->fuzzz, 0);
+
+       touchscreen_parse_properties(input_dev, false);
 
        if (pdata) {
                if (pdata->exit_platform_hw) {
@@ -443,6 +534,8 @@ static int tsc2007_probe(struct i2c_client *client,
                        pdata->init_platform_hw();
        }
 
+       dev_dbg(&client->dev, "request irq %d\n",
+                       ts->irq);
        err = devm_request_threaded_irq(&client->dev, ts->irq,
                                        tsc2007_hard_irq, tsc2007_soft_irq,
                                        IRQF_ONESHOT,
diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h
index 4f35b6a..632db20 100644
--- a/include/linux/i2c/tsc2007.h
+++ b/include/linux/i2c/tsc2007.h
@@ -6,6 +6,14 @@
 struct tsc2007_platform_data {
        u16     model;                          /* 2007. */
        u16     x_plate_ohms;   /* must be non-zero value */
+       bool    swap_xy;        /* swap x and y axis */
+       bool    invert_x;
+       bool    invert_y;
+       bool    report_resistance;
+       u16     min_x;  /* min and max values reported by ADC */
+       u16     min_y;
+       u16     max_x;
+       u16     max_y;
        u16     max_rt; /* max. resistance above which samples are ignored */
        unsigned long poll_period; /* time (in ms) between samples */
        int     fuzzx; /* fuzz factor for X, Y and pressure axes */
-- 
2.5.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to