diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2019-11-25 13:26:56 -0800 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2019-11-25 13:26:56 -0800 |
commit | 976e3645923bdd2fe7893aae33fd7a21098bfb28 (patch) | |
tree | d1cb24e4c9743beef15a4796070aca7e2c08228a /drivers/input/touchscreen | |
parent | 8791663435e7fea896d8ca0f56fd64976d2089ff (diff) | |
parent | 71c296f6d5b33faf9867d04c6c5d75c7e56b886b (diff) |
Merge branch 'next' into for-linus
Prepare input updates for 5.5 merge window.
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/ar1021_i2c.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/colibri-vf50-ts.c | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 30 | ||||
-rw-r--r-- | drivers/input/touchscreen/ili210x.c | 418 | ||||
-rw-r--r-- | drivers/input/touchscreen/mms114.c | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/pixcir_i2c_ts.c | 177 | ||||
-rw-r--r-- | drivers/input/touchscreen/raspberrypi-ts.c | 38 | ||||
-rw-r--r-- | drivers/input/touchscreen/s3c2410_ts.c | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/st1232.c | 184 | ||||
-rw-r--r-- | drivers/input/touchscreen/sur40.c | 96 | ||||
-rw-r--r-- | drivers/input/touchscreen/tps6507x-ts.c | 36 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts4800-ts.c | 68 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom_i2c.c | 1 |
15 files changed, 586 insertions, 481 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 46ad9090493b..c071f7c407b6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -633,7 +633,7 @@ config TOUCHSCREEN_HP600 depends on SH_HP6XX && SH_ADC help Say Y here if you have a HP Jornada 620/660/680/690 and want to - support the built-in touchscreen. + support the built-in touchscreen. To compile this driver as a module, choose M here: the module will be called hp680_ts_input. @@ -700,7 +700,6 @@ config TOUCHSCREEN_EDT_FT5X06 config TOUCHSCREEN_RASPBERRYPI_FW tristate "Raspberry Pi's firmware base touch screen support" depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) - select INPUT_POLLDEV help Say Y here if you have the official Raspberry Pi 7 inch screen on your system. @@ -1038,7 +1037,6 @@ config TOUCHSCREEN_TS4800 depends on HAS_IOMEM && OF depends on SOC_IMX51 || COMPILE_TEST select MFD_SYSCON - select INPUT_POLLDEV help Say Y here if you have a touchscreen on a TS-4800 board. @@ -1210,7 +1208,6 @@ config TOUCHSCREEN_SUR40 tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen" depends on USB && MEDIA_USB_SUPPORT && HAS_DMA depends on VIDEO_V4L2 - select INPUT_POLLDEV select VIDEOBUF2_DMA_SG help Say Y here if you want support for the Samsung SUR40 touchscreen @@ -1246,7 +1243,6 @@ config TOUCHSCREEN_SX8654 config TOUCHSCREEN_TPS6507X tristate "TPS6507x based touchscreens" depends on I2C - select INPUT_POLLDEV help Say Y here if you have a TPS6507x based touchscreen controller. diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index 28644f372bd8..c0d5c2413356 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -13,7 +13,7 @@ #include <linux/irq.h> #include <linux/interrupt.h> -#define AR1021_TOCUH_PKG_SIZE 5 +#define AR1021_TOUCH_PKG_SIZE 5 #define AR1021_MAX_X 4095 #define AR1021_MAX_Y 4095 @@ -25,7 +25,7 @@ struct ar1021_i2c { struct i2c_client *client; struct input_dev *input; - u8 data[AR1021_TOCUH_PKG_SIZE]; + u8 data[AR1021_TOUCH_PKG_SIZE]; }; static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 24c4b691b1c9..ae60442efda0 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3156,6 +3156,8 @@ static int __maybe_unused mxt_suspend(struct device *dev) mutex_unlock(&input_dev->mutex); + disable_irq(data->irq); + return 0; } @@ -3168,6 +3170,8 @@ static int __maybe_unused mxt_resume(struct device *dev) if (!input_dev) return 0; + enable_irq(data->irq); + mutex_lock(&input_dev->mutex); if (input_dev->users) diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c index 0e40897949bb..aa829725ded7 100644 --- a/drivers/input/touchscreen/colibri-vf50-ts.c +++ b/drivers/input/touchscreen/colibri-vf50-ts.c @@ -9,7 +9,6 @@ #include <linux/delay.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/iio/consumer.h> #include <linux/iio/types.h> diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5525f1fb1526..d61731c0037d 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -28,6 +28,7 @@ #include <linux/input/mt.h> #include <linux/input/touchscreen.h> #include <asm/unaligned.h> +#include <linux/regulator/consumer.h> #define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_REPORT_RATE 0x08 @@ -88,6 +89,7 @@ struct edt_ft5x06_ts_data { struct touchscreen_properties prop; u16 num_x; u16 num_y; + struct regulator *vcc; struct gpio_desc *reset_gpio; struct gpio_desc *wake_gpio; @@ -1036,6 +1038,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } +static void edt_ft5x06_disable_regulator(void *arg) +{ + struct edt_ft5x06_ts_data *data = arg; + + regulator_disable(data->vcc); +} + static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1064,6 +1073,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, tsdata->max_support_points = chip_data->max_support_points; + tsdata->vcc = devm_regulator_get(&client->dev, "vcc"); + if (IS_ERR(tsdata->vcc)) { + error = PTR_ERR(tsdata->vcc); + if (error != -EPROBE_DEFER) + dev_err(&client->dev, + "failed to request regulator: %d\n", error); + return error; + } + + error = regulator_enable(tsdata->vcc); + if (error < 0) { + dev_err(&client->dev, "failed to enable vcc: %d\n", error); + return error; + } + + error = devm_add_action_or_reset(&client->dev, + edt_ft5x06_disable_regulator, + tsdata); + if (error) + return error; + tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tsdata->reset_gpio)) { diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index e9006407c9bc..4a17096e83e1 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -1,54 +1,54 @@ // SPDX-License-Identifier: GPL-2.0-only -#include <linux/module.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> #include <linux/of_device.h> +#include <linux/sizes.h> +#include <linux/slab.h> #include <asm/unaligned.h> -#define ILI210X_TOUCHES 2 -#define ILI251X_TOUCHES 10 -#define DEFAULT_POLL_PERIOD 20 +#define ILI2XXX_POLL_PERIOD 20 + +#define ILI210X_DATA_SIZE 64 +#define ILI211X_DATA_SIZE 43 +#define ILI251X_DATA_SIZE1 31 +#define ILI251X_DATA_SIZE2 20 /* Touchscreen commands */ #define REG_TOUCHDATA 0x10 #define REG_PANEL_INFO 0x20 -#define REG_FIRMWARE_VERSION 0x40 #define REG_CALIBRATE 0xcc -struct firmware_version { - u8 id; - u8 major; - u8 minor; -} __packed; - -enum ili2xxx_model { - MODEL_ILI210X, - MODEL_ILI251X, +struct ili2xxx_chip { + int (*read_reg)(struct i2c_client *client, u8 reg, + void *buf, size_t len); + int (*get_touch_data)(struct i2c_client *client, u8 *data); + bool (*parse_touch_data)(const u8 *data, unsigned int finger, + unsigned int *x, unsigned int *y); + bool (*continue_polling)(const u8 *data, bool touch); + unsigned int max_touches; + unsigned int resolution; + bool has_calibrate_reg; }; struct ili210x { struct i2c_client *client; struct input_dev *input; - unsigned int poll_period; - struct delayed_work dwork; struct gpio_desc *reset_gpio; struct touchscreen_properties prop; - enum ili2xxx_model model; - unsigned int max_touches; + const struct ili2xxx_chip *chip; + bool stop; }; -static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, - size_t len) +static int ili210x_read_reg(struct i2c_client *client, + u8 reg, void *buf, size_t len) { - struct ili210x *priv = i2c_get_clientdata(client); - struct i2c_msg msg[2] = { + struct i2c_msg msg[] = { { .addr = client->addr, .flags = 0, @@ -62,151 +62,223 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, .buf = buf, } }; + int error, ret; - if (priv->model == MODEL_ILI251X) { - if (i2c_transfer(client->adapter, msg, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } - - usleep_range(5000, 5500); - - if (i2c_transfer(client->adapter, msg + 1, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } - } else { - if (i2c_transfer(client->adapter, msg, 2) != 2) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret != ARRAY_SIZE(msg)) { + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return error; } return 0; } -static int ili210x_read(struct i2c_client *client, void *buf, size_t len) +static int ili210x_read_touch_data(struct i2c_client *client, u8 *data) { - struct i2c_msg msg = { - .addr = client->addr, - .flags = I2C_M_RD, - .len = len, - .buf = buf, - }; + return ili210x_read_reg(client, REG_TOUCHDATA, + data, ILI210X_DATA_SIZE); +} + +static bool ili210x_touchdata_to_coords(const u8 *touchdata, + unsigned int finger, + unsigned int *x, unsigned int *y) +{ + if (touchdata[0] & BIT(finger)) + return false; + + *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0); + *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2); - if (i2c_transfer(client->adapter, &msg, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); + return true; +} + +static bool ili210x_check_continue_polling(const u8 *data, bool touch) +{ + return data[0] & 0xf3; +} + +static const struct ili2xxx_chip ili210x_chip = { + .read_reg = ili210x_read_reg, + .get_touch_data = ili210x_read_touch_data, + .parse_touch_data = ili210x_touchdata_to_coords, + .continue_polling = ili210x_check_continue_polling, + .max_touches = 2, + .has_calibrate_reg = true, +}; + +static int ili211x_read_touch_data(struct i2c_client *client, u8 *data) +{ + s16 sum = 0; + int error; + int ret; + int i; + + ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE); + if (ret != ILI211X_DATA_SIZE) { + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return error; + } + + /* This chip uses custom checksum at the end of data */ + for (i = 0; i < ILI211X_DATA_SIZE - 1; i++) + sum = (sum + data[i]) & 0xff; + + if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) { + dev_err(&client->dev, + "CRC error (crc=0x%02x expected=0x%02x)\n", + sum, data[ILI211X_DATA_SIZE - 1]); return -EIO; } return 0; } -static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, +static bool ili211x_touchdata_to_coords(const u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) { - if (finger >= ILI210X_TOUCHES) - return false; + u32 data; - if (touchdata[0] & BIT(finger)) + data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0); + if (data == 0xffffffff) /* Finger up */ return false; - *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0); - *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2); + *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) | + touchdata[1 + (finger * 4) + 1]; + *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) | + touchdata[1 + (finger * 4) + 2]; return true; } -static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, +static bool ili211x_decline_polling(const u8 *data, bool touch) +{ + return false; +} + +static const struct ili2xxx_chip ili211x_chip = { + .read_reg = ili210x_read_reg, + .get_touch_data = ili211x_read_touch_data, + .parse_touch_data = ili211x_touchdata_to_coords, + .continue_polling = ili211x_decline_polling, + .max_touches = 10, + .resolution = 2048, +}; + +static int ili251x_read_reg(struct i2c_client *client, + u8 reg, void *buf, size_t len) +{ + int error; + int ret; + + ret = i2c_master_send(client, ®, 1); + if (ret == 1) { + usleep_range(5000, 5500); + + ret = i2c_master_recv(client, buf, len); + if (ret == len) + return 0; + } + + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return ret; +} + +static int ili251x_read_touch_data(struct i2c_client *client, u8 *data) +{ + int error; + + error = ili251x_read_reg(client, REG_TOUCHDATA, + data, ILI251X_DATA_SIZE1); + if (!error && data[0] == 2) { + error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1, + ILI251X_DATA_SIZE2); + if (error >= 0 && error != ILI251X_DATA_SIZE2) + error = -EIO; + } + + return error; +} + +static bool ili251x_touchdata_to_coords(const u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) { - if (finger >= ILI251X_TOUCHES) - return false; + u16 val; - *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); - if (!(*x & BIT(15))) /* Touch indication */ + val = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); + if (!(val & BIT(15))) /* Touch indication */ return false; - *x &= 0x3fff; + *x = val & 0x3fff; *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2); return true; } +static bool ili251x_check_continue_polling(const u8 *data, bool touch) +{ + return touch; +} + +static const struct ili2xxx_chip ili251x_chip = { + .read_reg = ili251x_read_reg, + .get_touch_data = ili251x_read_touch_data, + .parse_touch_data = ili251x_touchdata_to_coords, + .continue_polling = ili251x_check_continue_polling, + .max_touches = 10, + .has_calibrate_reg = true, +}; + static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) { struct input_dev *input = priv->input; int i; - bool contact = false, touch = false; + bool contact = false, touch; unsigned int x = 0, y = 0; - for (i = 0; i < priv->max_touches; i++) { - if (priv->model == MODEL_ILI210X) { - touch = ili210x_touchdata_to_coords(priv, touchdata, - i, &x, &y); - } else if (priv->model == MODEL_ILI251X) { - touch = ili251x_touchdata_to_coords(priv, touchdata, - i, &x, &y); - if (touch) - contact = true; - } + for (i = 0; i < priv->chip->max_touches; i++) { + touch = priv->chip->parse_touch_data(touchdata, i, &x, &y); input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); - if (!touch) - continue; - touchscreen_report_pos(input, &priv->prop, x, y, - true); + if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) { + touchscreen_report_pos(input, &priv->prop, x, y, true); + contact = true; + } } input_mt_report_pointer_emulation(input, false); input_sync(input); - if (priv->model == MODEL_ILI210X) - contact = touchdata[0] & 0xf3; - return contact; } -static void ili210x_work(struct work_struct *work) +static irqreturn_t ili210x_irq(int irq, void *irq_data) { - struct ili210x *priv = container_of(work, struct ili210x, - dwork.work); + struct ili210x *priv = irq_data; struct i2c_client *client = priv->client; - u8 touchdata[64] = { 0 }; + const struct ili2xxx_chip *chip = priv->chip; + u8 touchdata[ILI210X_DATA_SIZE] = { 0 }; + bool keep_polling; bool touch; - int error = -EINVAL; - - if (priv->model == MODEL_ILI210X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, sizeof(touchdata)); - } else if (priv->model == MODEL_ILI251X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, 31); - if (!error && touchdata[0] == 2) - error = ili210x_read(client, &touchdata[31], 20); - } - - if (error) { - dev_err(&client->dev, - "Unable to get touchdata, err = %d\n", error); - return; - } - - touch = ili210x_report_events(priv, touchdata); - - if (touch) - schedule_delayed_work(&priv->dwork, - msecs_to_jiffies(priv->poll_period)); -} + int error; -static irqreturn_t ili210x_irq(int irq, void *irq_data) -{ - struct ili210x *priv = irq_data; + do { + error = chip->get_touch_data(client, touchdata); + if (error) { + dev_err(&client->dev, + "Unable to get touch data: %d\n", error); + break; + } - schedule_delayed_work(&priv->dwork, 0); + touch = ili210x_report_events(priv, touchdata); + keep_polling = chip->continue_polling(touchdata, touch); + if (keep_polling) + msleep(ILI2XXX_POLL_PERIOD); + } while (!priv->stop && keep_polling); return IRQ_HANDLED; } @@ -242,8 +314,19 @@ static struct attribute *ili210x_attributes[] = { NULL, }; +static umode_t ili210x_calibrate_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct i2c_client *client = to_i2c_client(dev); + struct ili210x *priv = i2c_get_clientdata(client); + + return priv->chip->has_calibrate_reg; +} + static const struct attribute_group ili210x_attr_group = { .attrs = ili210x_attributes, + .is_visible = ili210x_calibrate_visible, }; static void ili210x_power_down(void *data) @@ -253,28 +336,35 @@ static void ili210x_power_down(void *data) gpiod_set_value_cansleep(reset_gpio, 1); } -static void ili210x_cancel_work(void *data) +static void ili210x_stop(void *data) { struct ili210x *priv = data; - cancel_delayed_work_sync(&priv->dwork); + /* Tell ISR to quit even if there is a contact. */ + priv->stop = true; } static int ili210x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct device *dev = &client->dev; + const struct ili2xxx_chip *chip; struct ili210x *priv; struct gpio_desc *reset_gpio; struct input_dev *input; - struct firmware_version firmware; - enum ili2xxx_model model; int error; - - model = (enum ili2xxx_model)id->driver_data; + unsigned int max_xy; dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); + chip = device_get_match_data(dev); + if (!chip && id) + chip = (const struct ili2xxx_chip *)id->driver_data; + if (!chip) { + dev_err(&client->dev, "unknown device model\n"); + return -ENODEV; + } + if (client->irq <= 0) { dev_err(dev, "No IRQ!\n"); return -EINVAL; @@ -305,49 +395,39 @@ static int ili210x_i2c_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->poll_period = DEFAULT_POLL_PERIOD; - INIT_DELAYED_WORK(&priv->dwork, ili210x_work); priv->reset_gpio = reset_gpio; - priv->model = model; - if (model == MODEL_ILI210X) - priv->max_touches = ILI210X_TOUCHES; - if (model == MODEL_ILI251X) - priv->max_touches = ILI251X_TOUCHES; - + priv->chip = chip; i2c_set_clientdata(client, priv); - /* Get firmware version */ - error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, - &firmware, sizeof(firmware)); - if (error) { - dev_err(dev, "Failed to get firmware version, err: %d\n", - error); - return error; - } - /* Setup input device */ input->name = "ILI210x Touchscreen"; input->id.bustype = BUS_I2C; - input->dev.parent = dev; /* Multi touch */ - input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); + max_xy = (chip->resolution ?: SZ_64K) - 1; + input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0); touchscreen_parse_properties(input, true, &priv->prop); - input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT); - error = devm_add_action(dev, ili210x_cancel_work, priv); - if (error) + error = input_mt_init_slots(input, priv->chip->max_touches, + INPUT_MT_DIRECT); + if (error) { + dev_err(dev, "Unable to set up slots, err: %d\n", error); return error; + } - error = devm_request_irq(dev, client->irq, ili210x_irq, 0, - client->name, priv); + error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, + IRQF_ONESHOT, client->name, priv); if (error) { dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", error); return error; } + error = devm_add_action_or_reset(dev, ili210x_stop, priv); + if (error) + return error; + error = devm_device_add_group(dev, &ili210x_attr_group); if (error) { dev_err(dev, "Unable to create sysfs attributes, err: %d\n", @@ -361,56 +441,28 @@ static int ili210x_i2c_probe(struct i2c_client *client, return error; } - device_init_wakeup(dev, 1); - - dev_dbg(dev, - "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", - client->irq, firmware.id, firmware.major, firmware.minor); - return 0; } -static int __maybe_unused ili210x_i2c_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - - return 0; -} - -static int __maybe_unused ili210x_i2c_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, - ili210x_i2c_suspend, ili210x_i2c_resume); - static const struct i2c_device_id ili210x_i2c_id[] = { - { "ili210x", MODEL_ILI210X }, - { "ili251x", MODEL_ILI251X }, + { "ili210x", (long)&ili210x_chip }, + { "ili2117", (long)&ili211x_chip }, + { "ili251x", (long)&ili251x_chip }, { } }; MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); static const struct of_device_id ili210x_dt_ids[] = { - { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, - { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, - { }, + { .compatible = "ilitek,ili210x", .data = &ili210x_chip }, + { .compatible = "ilitek,ili2117", .data = &ili211x_chip }, + { .compatible = "ilitek,ili251x", .data = &ili251x_chip }, + { } }; MODULE_DEVICE_TABLE(of, ili210x_dt_ids); static struct i2c_driver ili210x_ts_driver = { .driver = { .name = "ili210x_i2c", - .pm = &ili210x_i2c_pm, .of_match_table = ili210x_dt_ids, }, .id_table = ili210x_i2c_id, diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index a5ab774da4cc..69c6d559eeb0 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -446,8 +446,7 @@ static int mms114_probe(struct i2c_client *client, data->client = client; data->input_dev = input_dev; - /* FIXME: switch to device_get_match_data() when available */ - match_data = of_device_get_match_data(&client->dev); + match_data = device_get_match_data(&client->dev); if (!match_data) return -EINVAL; diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index e146dfa257b1..9aa098577350 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -5,22 +5,73 @@ * Copyright (C) 2010-2011 Pixcir, Inc. */ +#include <asm/unaligned.h> #include <linux/delay.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/slab.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> #include <linux/of_device.h> -#include <linux/platform_data/pixcir_i2c_ts.h> -#include <asm/unaligned.h> +#include <linux/module.h> +#include <linux/slab.h> #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ +/* + * 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 during 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_i2c_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_i2c_ts_data { struct i2c_client *client; struct input_dev *input; @@ -30,7 +81,6 @@ struct pixcir_i2c_ts_data { struct gpio_desc *gpio_wake; const struct pixcir_i2c_chip_data *chip; struct touchscreen_properties prop; - int max_fingers; /* Max fingers supported in this instance */ bool running; }; @@ -54,7 +104,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, memset(report, 0, sizeof(struct pixcir_report_data)); i = chip->has_hw_ids ? 1 : 0; - readsize = 2 + tsdata->max_fingers * (4 + i); + readsize = 2 + tsdata->chip->max_fingers * (4 + i); if (readsize > sizeof(rdbuf)) readsize = sizeof(rdbuf); @@ -75,8 +125,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, } touch = rdbuf[0] & 0x7; - if (touch > tsdata->max_fingers) - touch = tsdata->max_fingers; + if (touch > tsdata->chip->max_fingers) + touch = tsdata->chip->max_fingers; report->num_touches = touch; bufptr = &rdbuf[2]; @@ -192,7 +242,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, 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", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_POWER_MODE, ret); return ret; } @@ -205,7 +255,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, 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", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_POWER_MODE, ret); return ret; } @@ -231,7 +281,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, 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", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -246,7 +296,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, 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", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -264,7 +314,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) 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", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -276,7 +326,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool 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", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -412,31 +462,9 @@ 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 int pixcir_parse_dt(struct device *dev, - struct pixcir_i2c_ts_data *tsdata) -{ - tsdata->chip = of_device_get_match_data(dev); - if (!tsdata->chip) - return -EINVAL; - - return 0; -} -#else -static int pixcir_parse_dt(struct device *dev, - struct pixcir_i2c_ts_data *tsdata) -{ - return -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 pixcir_i2c_ts_data *tsdata; struct input_dev *input; @@ -446,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, if (!tsdata) return -ENOMEM; - if (pdata) { - tsdata->chip = &pdata->chip; - } else if (dev->of_node) { - error = pixcir_parse_dt(dev, tsdata); - if (error) - return error; - } else { - dev_err(dev, "platform data not defined\n"); - retu |