1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Driver for Himax hx83112b touchscreens 4 * 5 * Copyright (C) 2022 Job Noorman <job@noorman.info> 6 * 7 * This code is based on "Himax Android Driver Sample Code for QCT platform": 8 * 9 * Copyright (C) 2017 Himax Corporation. 10 */ 11 12 #include <linux/delay.h> 13 #include <linux/err.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/i2c.h> 16 #include <linux/input.h> 17 #include <linux/input/mt.h> 18 #include <linux/input/touchscreen.h> 19 #include <linux/interrupt.h> 20 #include <linux/kernel.h> 21 #include <linux/regmap.h> 22 23 #define HIMAX_ID_83112B 0x83112b 24 25 #define HIMAX_MAX_POINTS 10 26 27 #define HIMAX_REG_CFG_SET_ADDR 0x00 28 #define HIMAX_REG_CFG_INIT_READ 0x0c 29 #define HIMAX_REG_CFG_READ_VALUE 0x08 30 #define HIMAX_REG_READ_EVENT 0x30 31 32 #define HIMAX_CFG_PRODUCT_ID 0x900000d0 33 34 #define HIMAX_INVALID_COORD 0xffff 35 36 struct himax_event_point { 37 __be16 x; 38 __be16 y; 39 } __packed; 40 41 struct himax_event { 42 struct himax_event_point points[HIMAX_MAX_POINTS]; 43 u8 majors[HIMAX_MAX_POINTS]; 44 u8 pad0[2]; 45 u8 num_points; 46 u8 pad1[2]; 47 u8 checksum_fix; 48 } __packed; 49 50 static_assert(sizeof(struct himax_event) == 56); 51 52 struct himax_ts_data { 53 struct gpio_desc *gpiod_rst; 54 struct input_dev *input_dev; 55 struct i2c_client *client; 56 struct regmap *regmap; 57 struct touchscreen_properties props; 58 }; 59 60 static const struct regmap_config himax_regmap_config = { 61 .reg_bits = 8, 62 .val_bits = 32, 63 .val_format_endian = REGMAP_ENDIAN_LITTLE, 64 }; 65 66 static int himax_read_config(struct himax_ts_data *ts, u32 address, u32 *dst) 67 { 68 int error; 69 70 error = regmap_write(ts->regmap, HIMAX_REG_CFG_SET_ADDR, address); 71 if (error) 72 return error; 73 74 error = regmap_write(ts->regmap, HIMAX_REG_CFG_INIT_READ, 0x0); 75 if (error) 76 return error; 77 78 error = regmap_read(ts->regmap, HIMAX_REG_CFG_READ_VALUE, dst); 79 if (error) 80 return error; 81 82 return 0; 83 } 84 85 static void himax_reset(struct himax_ts_data *ts) 86 { 87 gpiod_set_value_cansleep(ts->gpiod_rst, 1); 88 89 /* Delay copied from downstream driver */ 90 msleep(20); 91 gpiod_set_value_cansleep(ts->gpiod_rst, 0); 92 93 /* 94 * The downstream driver doesn't contain this delay but is seems safer 95 * to include it. The range is just a guess that seems to work well. 96 */ 97 usleep_range(1000, 1100); 98 } 99 100 static int himax_read_product_id(struct himax_ts_data *ts, u32 *product_id) 101 { 102 int error; 103 104 error = himax_read_config(ts, HIMAX_CFG_PRODUCT_ID, product_id); 105 if (error) 106 return error; 107 108 *product_id >>= 8; 109 return 0; 110 } 111 112 static int himax_check_product_id(struct himax_ts_data *ts) 113 { 114 int error; 115 u32 product_id; 116 117 error = himax_read_product_id(ts, &product_id); 118 if (error) 119 return error; 120 121 dev_dbg(&ts->client->dev, "Product id: %x\n", product_id); 122 123 switch (product_id) { 124 case HIMAX_ID_83112B: 125 return 0; 126 127 default: 128 dev_err(&ts->client->dev, 129 "Unknown product id: %x\n", product_id); 130 return -EINVAL; 131 } 132 } 133 134 static int himax_input_register(struct himax_ts_data *ts) 135 { 136 int error; 137 138 ts->input_dev = devm_input_allocate_device(&ts->client->dev); 139 if (!ts->input_dev) { 140 dev_err(&ts->client->dev, "Failed to allocate input device\n"); 141 return -ENOMEM; 142 } 143 144 ts->input_dev->name = "Himax Touchscreen"; 145 146 input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X); 147 input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y); 148 input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); 149 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 200, 0, 0); 150 151 touchscreen_parse_properties(ts->input_dev, true, &ts->props); 152 153 error = input_mt_init_slots(ts->input_dev, HIMAX_MAX_POINTS, 154 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 155 if (error) { 156 dev_err(&ts->client->dev, 157 "Failed to initialize MT slots: %d\n", error); 158 return error; 159 } 160 161 error = input_register_device(ts->input_dev); 162 if (error) { 163 dev_err(&ts->client->dev, 164 "Failed to register input device: %d\n", error); 165 return error; 166 } 167 168 return 0; 169 } 170 171 static u8 himax_event_get_num_points(const struct himax_event *event) 172 { 173 if (event->num_points == 0xff) 174 return 0; 175 else 176 return event->num_points & 0x0f; 177 } 178 179 static bool himax_process_event_point(struct himax_ts_data *ts, 180 const struct himax_event *event, 181 int point_index) 182 { 183 const struct himax_event_point *point = &event->points[point_index]; 184 u16 x = be16_to_cpu(point->x); 185 u16 y = be16_to_cpu(point->y); 186 u8 w = event->majors[point_index]; 187 188 if (x == HIMAX_INVALID_COORD || y == HIMAX_INVALID_COORD) 189 return false; 190 191 input_mt_slot(ts->input_dev, point_index); 192 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); 193 touchscreen_report_pos(ts->input_dev, &ts->props, x, y, true); 194 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); 195 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); 196 return true; 197 } 198 199 static void himax_process_event(struct himax_ts_data *ts, 200 const struct himax_event *event) 201 { 202 int i; 203 int num_points_left = himax_event_get_num_points(event); 204 205 for (i = 0; i < HIMAX_MAX_POINTS && num_points_left > 0; i++) { 206 if (himax_process_event_point(ts, event, i)) 207 num_points_left--; 208 } 209 210 input_mt_sync_frame(ts->input_dev); 211 input_sync(ts->input_dev); 212 } 213 214 static bool himax_verify_checksum(struct himax_ts_data *ts, 215 const struct himax_event *event) 216 { 217 u8 *data = (u8 *)event; 218 int i; 219 u16 checksum = 0; 220 221 for (i = 0; i < sizeof(*event); i++) 222 checksum += data[i]; 223 224 if ((checksum & 0x00ff) != 0) { 225 dev_err(&ts->client->dev, "Wrong event checksum: %04x\n", 226 checksum); 227 return false; 228 } 229 230 return true; 231 } 232 233 static int himax_handle_input(struct himax_ts_data *ts) 234 { 235 int error; 236 struct himax_event event; 237 238 error = regmap_raw_read(ts->regmap, HIMAX_REG_READ_EVENT, &event, 239 sizeof(event)); 240 if (error) { 241 dev_err(&ts->client->dev, "Failed to read input event: %d\n", 242 error); 243 return error; 244 } 245 246 /* 247 * Only process the current event when it has a valid checksum but 248 * don't consider it a fatal error when it doesn't. 249 */ 250 if (himax_verify_checksum(ts, &event)) 251 himax_process_event(ts, &event); 252 253 return 0; 254 } 255 256 static irqreturn_t himax_irq_handler(int irq, void *dev_id) 257 { 258 int error; 259 struct himax_ts_data *ts = dev_id; 260 261 error = himax_handle_input(ts); 262 if (error) 263 return IRQ_NONE; 264 265 return IRQ_HANDLED; 266 } 267 268 static int himax_probe(struct i2c_client *client) 269 { 270 int error; 271 struct device *dev = &client->dev; 272 struct himax_ts_data *ts; 273 274 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 275 dev_err(dev, "I2C check functionality failed\n"); 276 return -ENXIO; 277 } 278 279 ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); 280 if (!ts) 281 return -ENOMEM; 282 283 i2c_set_clientdata(client, ts); 284 ts->client = client; 285 286 ts->regmap = devm_regmap_init_i2c(client, &himax_regmap_config); 287 error = PTR_ERR_OR_ZERO(ts->regmap); 288 if (error) { 289 dev_err(dev, "Failed to initialize regmap: %d\n", error); 290 return error; 291 } 292 293 ts->gpiod_rst = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 294 error = PTR_ERR_OR_ZERO(ts->gpiod_rst); 295 if (error) { 296 dev_err(dev, "Failed to get reset GPIO: %d\n", error); 297 return error; 298 } 299 300 himax_reset(ts); 301 302 error = himax_check_product_id(ts); 303 if (error) 304 return error; 305 306 error = himax_input_register(ts); 307 if (error) 308 return error; 309 310 error = devm_request_threaded_irq(dev, client->irq, NULL, 311 himax_irq_handler, IRQF_ONESHOT, 312 client->name, ts); 313 if (error) 314 return error; 315 316 return 0; 317 } 318 319 static int himax_suspend(struct device *dev) 320 { 321 struct himax_ts_data *ts = dev_get_drvdata(dev); 322 323 disable_irq(ts->client->irq); 324 return 0; 325 } 326 327 static int himax_resume(struct device *dev) 328 { 329 struct himax_ts_data *ts = dev_get_drvdata(dev); 330 331 enable_irq(ts->client->irq); 332 return 0; 333 } 334 335 static DEFINE_SIMPLE_DEV_PM_OPS(himax_pm_ops, himax_suspend, himax_resume); 336 337 static const struct i2c_device_id himax_ts_id[] = { 338 { "hx83112b", 0 }, 339 { /* sentinel */ } 340 }; 341 MODULE_DEVICE_TABLE(i2c, himax_ts_id); 342 343 #ifdef CONFIG_OF 344 static const struct of_device_id himax_of_match[] = { 345 { .compatible = "himax,hx83112b" }, 346 { /* sentinel */ } 347 }; 348 MODULE_DEVICE_TABLE(of, himax_of_match); 349 #endif 350 351 static struct i2c_driver himax_ts_driver = { 352 .probe = himax_probe, 353 .id_table = himax_ts_id, 354 .driver = { 355 .name = "Himax-hx83112b-TS", 356 .of_match_table = of_match_ptr(himax_of_match), 357 .pm = pm_sleep_ptr(&himax_pm_ops), 358 }, 359 }; 360 module_i2c_driver(himax_ts_driver); 361 362 MODULE_AUTHOR("Job Noorman <job@noorman.info>"); 363 MODULE_DESCRIPTION("Himax hx83112b touchscreen driver"); 364 MODULE_LICENSE("GPL"); 365