diff options
| author | Martin Kepplinger <martin.kepplinger@ginzinger.com> | 2019-01-28 13:38:10 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2019-01-28 14:24:47 -0500 |
| commit | 351e0592bfeae58c76a11bdcec59eb78b2937593 (patch) | |
| tree | 6f7c70f835bbd1eb1c035f698fcf769249d6f1ee /drivers/input | |
| parent | b6eba86030bf2fa3abcf9a0e3fb04527330da52e (diff) | |
Input: st1232 - add support for st1633
Add support for the Sitronix ST1633 touchscreen controller to the st1232
driver. A protocol spec can be found here:
www.ampdisplay.com/documents/pdf/AM-320480B6TZQW-TC0H.pdf
Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/input/touchscreen/st1232.c | 120 |
2 files changed, 89 insertions, 37 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index af6027cc7bbf..6c16aaeb4191 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -1168,11 +1168,11 @@ config TOUCHSCREEN_SIS_I2C | |||
| 1168 | module will be called sis_i2c. | 1168 | module will be called sis_i2c. |
| 1169 | 1169 | ||
| 1170 | config TOUCHSCREEN_ST1232 | 1170 | config TOUCHSCREEN_ST1232 |
| 1171 | tristate "Sitronix ST1232 touchscreen controllers" | 1171 | tristate "Sitronix ST1232 or ST1633 touchscreen controllers" |
| 1172 | depends on I2C | 1172 | depends on I2C |
| 1173 | help | 1173 | help |
| 1174 | Say Y here if you want to support Sitronix ST1232 | 1174 | Say Y here if you want to support the Sitronix ST1232 |
| 1175 | touchscreen controller. | 1175 | or ST1633 touchscreen controller. |
| 1176 | 1176 | ||
| 1177 | If unsure, say N. | 1177 | If unsure, say N. |
| 1178 | 1178 | ||
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 11ff32c68025..777df903605d 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
| @@ -23,13 +23,7 @@ | |||
| 23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
| 24 | 24 | ||
| 25 | #define ST1232_TS_NAME "st1232-ts" | 25 | #define ST1232_TS_NAME "st1232-ts" |
| 26 | 26 | #define ST1633_TS_NAME "st1633-ts" | |
| 27 | #define MIN_X 0x00 | ||
| 28 | #define MIN_Y 0x00 | ||
| 29 | #define MAX_X 0x31f /* (800 - 1) */ | ||
| 30 | #define MAX_Y 0x1df /* (480 - 1) */ | ||
| 31 | #define MAX_AREA 0xff | ||
| 32 | #define MAX_FINGERS 2 | ||
| 33 | 27 | ||
| 34 | struct st1232_ts_finger { | 28 | struct st1232_ts_finger { |
| 35 | u16 x; | 29 | u16 x; |
| @@ -38,12 +32,24 @@ struct st1232_ts_finger { | |||
| 38 | bool is_valid; | 32 | bool is_valid; |
| 39 | }; | 33 | }; |
| 40 | 34 | ||
| 35 | struct st_chip_info { | ||
| 36 | bool have_z; | ||
| 37 | u16 max_x; | ||
| 38 | u16 max_y; | ||
| 39 | u16 max_area; | ||
| 40 | u16 max_fingers; | ||
| 41 | u8 start_reg; | ||
| 42 | }; | ||
| 43 | |||
| 41 | struct st1232_ts_data { | 44 | struct st1232_ts_data { |
| 42 | struct i2c_client *client; | 45 | struct i2c_client *client; |
| 43 | struct input_dev *input_dev; | 46 | struct input_dev *input_dev; |
| 44 | struct st1232_ts_finger finger[MAX_FINGERS]; | ||
| 45 | struct dev_pm_qos_request low_latency_req; | 47 | struct dev_pm_qos_request low_latency_req; |
| 46 | int reset_gpio; | 48 | int reset_gpio; |
| 49 | const struct st_chip_info *chip_info; | ||
| 50 | int read_buf_len; | ||
| 51 | u8 *read_buf; | ||
| 52 | struct st1232_ts_finger *finger; | ||
| 47 | }; | 53 | }; |
| 48 | 54 | ||
| 49 | static int st1232_ts_read_data(struct st1232_ts_data *ts) | 55 | static int st1232_ts_read_data(struct st1232_ts_data *ts) |
| @@ -52,40 +58,35 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) | |||
| 52 | struct i2c_client *client = ts->client; | 58 | struct i2c_client *client = ts->client; |
| 53 | struct i2c_msg msg[2]; | 59 | struct i2c_msg msg[2]; |
| 54 | int error; | 60 | int error; |
| 55 | u8 start_reg; | 61 | int i, y; |
| 56 | u8 buf[10]; | 62 | u8 start_reg = ts->chip_info->start_reg; |
| 63 | u8 *buf = ts->read_buf; | ||
| 57 | 64 | ||
| 58 | /* read touchscreen data from ST1232 */ | 65 | /* read touchscreen data */ |
| 59 | msg[0].addr = client->addr; | 66 | msg[0].addr = client->addr; |
| 60 | msg[0].flags = 0; | 67 | msg[0].flags = 0; |
| 61 | msg[0].len = 1; | 68 | msg[0].len = 1; |
| 62 | msg[0].buf = &start_reg; | 69 | msg[0].buf = &start_reg; |
| 63 | start_reg = 0x10; | ||
| 64 | 70 | ||
| 65 | msg[1].addr = ts->client->addr; | 71 | msg[1].addr = ts->client->addr; |
| 66 | msg[1].flags = I2C_M_RD; | 72 | msg[1].flags = I2C_M_RD; |
| 67 | msg[1].len = sizeof(buf); | 73 | msg[1].len = ts->read_buf_len; |
| 68 | msg[1].buf = buf; | 74 | msg[1].buf = buf; |
| 69 | 75 | ||
| 70 | error = i2c_transfer(client->adapter, msg, 2); | 76 | error = i2c_transfer(client->adapter, msg, 2); |
| 71 | if (error < 0) | 77 | if (error < 0) |
| 72 | return error; | 78 | return error; |
| 73 | 79 | ||
| 74 | /* get "valid" bits */ | 80 | for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) { |
| 75 | finger[0].is_valid = buf[2] >> 7; | 81 | finger[i].is_valid = buf[i + y] >> 7; |
| 76 | finger[1].is_valid = buf[5] >> 7; | 82 | if (finger[i].is_valid) { |
| 77 | 83 | finger[i].x = ((buf[i + y] & 0x0070) << 4) | buf[i + 1]; | |
| 78 | /* get xy coordinate */ | 84 | finger[i].y = ((buf[i + y] & 0x0007) << 8) | buf[i + 2]; |
| 79 | if (finger[0].is_valid) { | ||
| 80 | finger[0].x = ((buf[2] & 0x0070) << 4) | buf[3]; | ||
| 81 | finger[0].y = ((buf[2] & 0x0007) << 8) | buf[4]; | ||
| 82 | finger[0].t = buf[8]; | ||
| 83 | } | ||
| 84 | 85 | ||
| 85 | if (finger[1].is_valid) { | 86 | /* st1232 includes a z-axis / touch strength */ |
| 86 | finger[1].x = ((buf[5] & 0x0070) << 4) | buf[6]; | 87 | if (ts->chip_info->have_z) |
| 87 | finger[1].y = ((buf[5] & 0x0007) << 8) | buf[7]; | 88 | finger[i].t = buf[i + 6]; |
| 88 | finger[1].t = buf[9]; | 89 | } |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | return 0; | 92 | return 0; |
| @@ -104,11 +105,14 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | |||
| 104 | goto end; | 105 | goto end; |
| 105 | 106 | ||
| 106 | /* multi touch protocol */ | 107 | /* multi touch protocol */ |
| 107 | for (i = 0; i < MAX_FINGERS; i++) { | 108 | for (i = 0; i < ts->chip_info->max_fingers; i++) { |
| 108 | if (!finger[i].is_valid) | 109 | if (!finger[i].is_valid) |
| 109 | continue; | 110 | continue; |
| 110 | 111 | ||
| 111 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t); | 112 | if (ts->chip_info->have_z) |
| 113 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 114 | finger[i].t); | ||
| 115 | |||
| 112 | input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x); | 116 | input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x); |
| 113 | input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y); | 117 | input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y); |
| 114 | input_mt_sync(input_dev); | 118 | input_mt_sync(input_dev); |
| @@ -142,13 +146,41 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) | |||
| 142 | gpio_direction_output(ts->reset_gpio, poweron); | 146 | gpio_direction_output(ts->reset_gpio, poweron); |
| 143 | } | 147 | } |
| 144 | 148 | ||
| 149 | static const struct st_chip_info st1232_chip_info = { | ||
| 150 | .have_z = true, | ||
| 151 | .max_x = 0x31f, /* 800 - 1 */ | ||
| 152 | .max_y = 0x1df, /* 480 -1 */ | ||
| 153 | .max_area = 0xff, | ||
| 154 | .max_fingers = 2, | ||
| 155 | .start_reg = 0x12, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static const struct st_chip_info st1633_chip_info = { | ||
| 159 | .have_z = false, | ||
| 160 | .max_x = 0x13f, /* 320 - 1 */ | ||
| 161 | .max_y = 0x1df, /* 480 -1 */ | ||
| 162 | .max_area = 0x00, | ||
| 163 | .max_fingers = 5, | ||
| 164 | .start_reg = 0x12, | ||
| 165 | }; | ||
| 166 | |||
| 145 | static int st1232_ts_probe(struct i2c_client *client, | 167 | static int st1232_ts_probe(struct i2c_client *client, |
| 146 | const struct i2c_device_id *id) | 168 | const struct i2c_device_id *id) |
| 147 | { | 169 | { |
| 170 | const struct st_chip_info *match; | ||
| 148 | struct st1232_ts_data *ts; | 171 | struct st1232_ts_data *ts; |
| 172 | struct st1232_ts_finger *finger; | ||
| 149 | struct input_dev *input_dev; | 173 | struct input_dev *input_dev; |
| 150 | int error; | 174 | int error; |
| 151 | 175 | ||
| 176 | match = device_get_match_data(&client->dev); | ||
| 177 | if (!match && id) | ||
| 178 | match = (const void *)id->driver_data; | ||
| 179 | if (!match) { | ||
| 180 | dev_err(&client->dev, "unknown device model\n"); | ||
| 181 | return -ENODEV; | ||
| 182 | } | ||
| 183 | |||
| 152 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 184 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| 153 | dev_err(&client->dev, "need I2C_FUNC_I2C\n"); | 185 | dev_err(&client->dev, "need I2C_FUNC_I2C\n"); |
| 154 | return -EIO; | 186 | return -EIO; |
| @@ -163,6 +195,19 @@ static int st1232_ts_probe(struct i2c_client *client, | |||
| 163 | if (!ts) | 195 | if (!ts) |
| 164 | return -ENOMEM; | 196 | return -ENOMEM; |
| 165 | 197 | ||
| 198 | ts->chip_info = match; | ||
| 199 | ts->finger = devm_kcalloc(&client->dev, | ||
| 200 | ts->chip_info->max_fingers, sizeof(*finger), | ||
| 201 | GFP_KERNEL); | ||
| 202 | if (!ts->finger) | ||
| 203 | return -ENOMEM; | ||
| 204 | |||
| 205 | /* allocate a buffer according to the number of registers to read */ | ||
| 206 | ts->read_buf_len = ts->chip_info->max_fingers * 4; | ||
| 207 | ts->read_buf = devm_kzalloc(&client->dev, ts->read_buf_len, GFP_KERNEL); | ||
| 208 | if (!ts->read_buf) | ||
| 209 | return -ENOMEM; | ||
| 210 | |||
| 166 | input_dev = devm_input_allocate_device(&client->dev); | 211 | input_dev = devm_input_allocate_device(&client->dev); |
| 167 | if (!input_dev) | 212 | if (!input_dev) |
| 168 | return -ENOMEM; | 213 | return -ENOMEM; |
| @@ -192,9 +237,14 @@ static int st1232_ts_probe(struct i2c_client *client, | |||
| 192 | __set_bit(EV_KEY, input_dev->evbit); | 237 | __set_bit(EV_KEY, input_dev->evbit); |
| 193 | __set_bit(EV_ABS, input_dev->evbit); | 238 | __set_bit(EV_ABS, input_dev->evbit); |
| 194 | 239 | ||
| 195 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); | 240 | if (ts->chip_info->have_z) |
| 196 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0); | 241 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, |
| 197 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0); | 242 | ts->chip_info->max_area, 0, 0); |
| 243 | |||
| 244 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
| 245 | 0, ts->chip_info->max_x, 0, 0); | ||
| 246 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
| 247 | 0, ts->chip_info->max_y, 0, 0); | ||
| 198 | 248 | ||
| 199 | error = devm_request_threaded_irq(&client->dev, client->irq, | 249 | error = devm_request_threaded_irq(&client->dev, client->irq, |
| 200 | NULL, st1232_ts_irq_handler, | 250 | NULL, st1232_ts_irq_handler, |
| @@ -261,13 +311,15 @@ static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, | |||
| 261 | st1232_ts_suspend, st1232_ts_resume); | 311 | st1232_ts_suspend, st1232_ts_resume); |
| 262 | 312 | ||
| 263 | static const struct i2c_device_id st1232_ts_id[] = { | 313 | static const struct i2c_device_id st1232_ts_id[] = { |
| 264 | { ST1232_TS_NAME, 0 }, | 314 | { ST1232_TS_NAME, (unsigned long)&st1232_chip_info }, |
| 315 | { ST1633_TS_NAME, (unsigned long)&st1633_chip_info }, | ||
| 265 | { } | 316 | { } |
| 266 | }; | 317 | }; |
| 267 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | 318 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); |
| 268 | 319 | ||
| 269 | static const struct of_device_id st1232_ts_dt_ids[] = { | 320 | static const struct of_device_id st1232_ts_dt_ids[] = { |
| 270 | { .compatible = "sitronix,st1232", }, | 321 | { .compatible = "sitronix,st1232", .data = &st1232_chip_info }, |
| 322 | { .compatible = "sitronix,st1633", .data = &st1633_chip_info }, | ||
| 271 | { } | 323 | { } |
| 272 | }; | 324 | }; |
| 273 | MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); | 325 | MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); |
