[PATCH 1/3] input: tsc2007: Add pre-calibration, flipping and rotation
Belisko Marek
marek.belisko at gmail.com
Sat Jan 10 06:15:39 PST 2015
Ping for input maintainer. DT changes was acked. Thanks.
On Tue, Sep 30, 2014 at 10:17 PM, Marek Belisko <marek at goldelico.com> wrote:
> This patch adds new parameters that allow to address typical hardware
> design differences: touch screens may be wired or oriented differently
> (portrait or landscape). And usually the active area of the touch is a
> little larger than the active area of the LCD. This results in the touch
> coordinates that have some significant deviation from LCD coordinates.
> Usually this is addressed in user space by a calibration tool (e.g. tslib
> or xinput-calibrator) but some systems don't have these tools or require
> that the screen is already roughly calibrated (e.g. Replicant) to operate
> the device until a better calibration can be done. And, some systems
> react very strangely if the touch event stream reports coordinates
> outside of the active area.
>
> This makes it necessry to be able to configure:
> 1. swapping x and y wires (coordinate values)
> 2. flipping of x (left - right) or y (top - bottom) or even both
> 3. define an active area so that an uncalibrated screen already
> roughly matches the LCD to be useful.
> 4. clip reported coordinates to the active area.
>
> If none of the new parameters is defined (in DT) or set in a board file,
> the driver behaves the same as without this patch.
>
> Author (1&2): H. Nikolaus Schaller <hns at goldelico.com>
> Author (3&4): Paul Kocialkowski <contact at paulk.fr>
>
> Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
> ---
> drivers/input/touchscreen/tsc2007.c | 89 +++++++++++++++++++++++++++++++++++--
> include/linux/i2c/tsc2007.h | 6 +++
> 2 files changed, 91 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
> index 1bf9906..cc0cc3c 100644
> --- a/drivers/input/touchscreen/tsc2007.c
> +++ b/drivers/input/touchscreen/tsc2007.c
> @@ -74,6 +74,12 @@ struct tsc2007 {
>
> u16 model;
> u16 x_plate_ohms;
> + bool swap_xy; /* swap x and y axis */
> + u16 min_x;
> + u16 min_y;
> + u16 min_rt;
> + u16 max_x;
> + u16 max_y;
> u16 max_rt;
> unsigned long poll_period;
> int fuzzx;
> @@ -193,11 +199,50 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
> break;
> }
>
> - if (rt <= ts->max_rt) {
> + if (rt <= max(ts->min_rt, ts->max_rt)) {
> dev_dbg(&ts->client->dev,
> "DOWN point(%4d,%4d), pressure (%4u)\n",
> tc.x, tc.y, rt);
>
> + if (ts->swap_xy) {
> + /* swap before applying the range limits */
> + u16 h = tc.x;
> +
> + tc.x = tc.y;
> + tc.y = h;
> + }
> +
> + /* flip and/or clip X */
> + if (ts->max_x < ts->min_x)
> + tc.x = (ts->min_x - tc.x) + ts->max_x;
> +
> + if (tc.x > max(ts->min_x, ts->max_x))
> + tc.x = max(ts->min_x, ts->max_x);
> + else if (tc.x < min(ts->min_x, ts->max_x))
> + tc.x = min(ts->min_x, ts->max_x);
> +
> + /* flip and/or clip Y */
> + if (ts->max_y < ts->min_y)
> + tc.y = (ts->min_y - tc.y) + ts->max_y;
> +
> + if (tc.y > max(ts->min_y, ts->max_y))
> + tc.y = max(ts->min_y, ts->max_y);
> + else if (tc.y < min(ts->min_y, ts->max_y))
> + tc.y = min(ts->min_y, ts->max_y);
> +
> + /* clip Z */
> + if (ts->max_rt < ts->min_rt)
> + rt = (ts->min_rt - rt) + ts->max_rt;
> +
> + if (rt > max(ts->min_rt, ts->max_rt))
> + rt = max(ts->min_rt, ts->max_rt);
> + else if (rt < min(ts->min_rt, ts->max_rt))
> + rt = min(ts->min_rt, ts->max_rt);
> +
> + 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);
> @@ -299,6 +344,24 @@ static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
> return -EINVAL;
> }
>
> + ts->swap_xy = of_property_read_bool(np, "ti,swap-xy");
> +
> + 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,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_u32(np, "ti,min-rt", &val32))
> + ts->min_rt = val32;
> if (!of_property_read_u32(np, "ti,max-rt", &val32))
> ts->max_rt = val32;
> else
> @@ -325,6 +388,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,
> + "min/max_rt (%4d,%4d)\n",
> + ts->min_rt, 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;
> @@ -349,6 +422,12 @@ 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->swap_xy = pdata->swap_xy;
> + ts->min_x = pdata->min_x ? : 0;
> + ts->min_y = pdata->min_y ? : 0;
> + ts->min_rt = pdata->min_rt ? : 0;
> + ts->max_x = pdata->max_x ? : MAX_12BIT;
> + ts->max_y = pdata->max_y ? : MAX_12BIT;
> ts->max_rt = pdata->max_rt ? : MAX_12BIT;
> ts->poll_period = pdata->poll_period ? : 1;
> ts->get_pendown_state = pdata->get_pendown_state;
> @@ -422,9 +501,11 @@ 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,
> + input_set_abs_params(input_dev, ABS_X, min(ts->min_x, ts->max_x),
> + max(ts->min_x, ts->max_x), ts->fuzzx, 0);
> + input_set_abs_params(input_dev, ABS_Y, min(ts->min_y, ts->max_y),
> + max(ts->min_y, ts->max_y), ts->fuzzy, 0);
> + input_set_abs_params(input_dev, ABS_PRESSURE, ts->min_rt, ts->max_rt,
> ts->fuzzz, 0);
>
> if (pdata) {
> diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h
> index 4f35b6a..5ce7b79 100644
> --- a/include/linux/i2c/tsc2007.h
> +++ b/include/linux/i2c/tsc2007.h
> @@ -6,6 +6,12 @@
> struct tsc2007_platform_data {
> u16 model; /* 2007. */
> u16 x_plate_ohms; /* must be non-zero value */
> + bool swap_xy; /* swap x and y axis */
> + u16 min_x; /* min and max values to reported to user space */
> + u16 min_y;
> + u16 min_rt;
> + 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 */
> --
> 1.9.3
>
BR,
marek
--
as simple and primitive as possible
-------------------------------------------------
Marek Belisko - OPEN-NANDRA
Freelance Developer
Ruska Nova Ves 219 | Presov, 08005 Slovak Republic
Tel: +421 915 052 184
skype: marekwhite
twitter: #opennandra
web: http://open-nandra.com
More information about the linux-arm-kernel
mailing list