cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ilitek_ts_i2c.c (15661B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * ILITEK Touch IC driver for 23XX, 25XX and Lego series
      4 *
      5 * Copyright (C) 2011 ILI Technology Corporation.
      6 * Copyright (C) 2020 Luca Hsu <luca_hsu@ilitek.com>
      7 * Copyright (C) 2021 Joe Hung <joe_hung@ilitek.com>
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/input.h>
     13#include <linux/input/mt.h>
     14#include <linux/i2c.h>
     15#include <linux/slab.h>
     16#include <linux/delay.h>
     17#include <linux/interrupt.h>
     18#include <linux/gpio.h>
     19#include <linux/gpio/consumer.h>
     20#include <linux/errno.h>
     21#include <linux/acpi.h>
     22#include <linux/input/touchscreen.h>
     23#include <asm/unaligned.h>
     24
     25
     26#define ILITEK_TS_NAME					"ilitek_ts"
     27#define BL_V1_8						0x108
     28#define BL_V1_7						0x107
     29#define BL_V1_6						0x106
     30
     31#define ILITEK_TP_CMD_GET_TP_RES			0x20
     32#define ILITEK_TP_CMD_GET_SCRN_RES			0x21
     33#define ILITEK_TP_CMD_SET_IC_SLEEP			0x30
     34#define ILITEK_TP_CMD_SET_IC_WAKE			0x31
     35#define ILITEK_TP_CMD_GET_FW_VER			0x40
     36#define ILITEK_TP_CMD_GET_PRL_VER			0x42
     37#define ILITEK_TP_CMD_GET_MCU_VER			0x61
     38#define ILITEK_TP_CMD_GET_IC_MODE			0xC0
     39
     40#define REPORT_COUNT_ADDRESS				61
     41#define ILITEK_SUPPORT_MAX_POINT			40
     42
     43struct ilitek_protocol_info {
     44	u16 ver;
     45	u8 ver_major;
     46};
     47
     48struct ilitek_ts_data {
     49	struct i2c_client		*client;
     50	struct gpio_desc		*reset_gpio;
     51	struct input_dev		*input_dev;
     52	struct touchscreen_properties	prop;
     53
     54	const struct ilitek_protocol_map *ptl_cb_func;
     55	struct ilitek_protocol_info	ptl;
     56
     57	char				product_id[30];
     58	u16				mcu_ver;
     59	u8				ic_mode;
     60	u8				firmware_ver[8];
     61
     62	s32				reset_time;
     63	s32				screen_max_x;
     64	s32				screen_max_y;
     65	s32				screen_min_x;
     66	s32				screen_min_y;
     67	s32				max_tp;
     68};
     69
     70struct ilitek_protocol_map {
     71	u16 cmd;
     72	const char *name;
     73	int (*func)(struct ilitek_ts_data *ts, u16 cmd, u8 *inbuf, u8 *outbuf);
     74};
     75
     76enum ilitek_cmds {
     77	/* common cmds */
     78	GET_PTL_VER = 0,
     79	GET_FW_VER,
     80	GET_SCRN_RES,
     81	GET_TP_RES,
     82	GET_IC_MODE,
     83	GET_MCU_VER,
     84	SET_IC_SLEEP,
     85	SET_IC_WAKE,
     86
     87	/* ALWAYS keep at the end */
     88	MAX_CMD_CNT
     89};
     90
     91/* ILITEK I2C R/W APIs */
     92static int ilitek_i2c_write_and_read(struct ilitek_ts_data *ts,
     93				     u8 *cmd, int write_len, int delay,
     94				     u8 *data, int read_len)
     95{
     96	int error;
     97	struct i2c_client *client = ts->client;
     98	struct i2c_msg msgs[] = {
     99		{
    100			.addr = client->addr,
    101			.flags = 0,
    102			.len = write_len,
    103			.buf = cmd,
    104		},
    105		{
    106			.addr = client->addr,
    107			.flags = I2C_M_RD,
    108			.len = read_len,
    109			.buf = data,
    110		},
    111	};
    112
    113	if (delay == 0 && write_len > 0 && read_len > 0) {
    114		error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
    115		if (error < 0)
    116			return error;
    117	} else {
    118		if (write_len > 0) {
    119			error = i2c_transfer(client->adapter, msgs, 1);
    120			if (error < 0)
    121				return error;
    122		}
    123		if (delay > 0)
    124			mdelay(delay);
    125
    126		if (read_len > 0) {
    127			error = i2c_transfer(client->adapter, msgs + 1, 1);
    128			if (error < 0)
    129				return error;
    130		}
    131	}
    132
    133	return 0;
    134}
    135
    136/* ILITEK ISR APIs */
    137static void ilitek_touch_down(struct ilitek_ts_data *ts, unsigned int id,
    138			      unsigned int x, unsigned int y)
    139{
    140	struct input_dev *input = ts->input_dev;
    141
    142	input_mt_slot(input, id);
    143	input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
    144
    145	touchscreen_report_pos(input, &ts->prop, x, y, true);
    146}
    147
    148static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts)
    149{
    150	int error = 0;
    151	u8 buf[512];
    152	int packet_len = 5;
    153	int packet_max_point = 10;
    154	int report_max_point;
    155	int i, count;
    156	struct input_dev *input = ts->input_dev;
    157	struct device *dev = &ts->client->dev;
    158	unsigned int x, y, status, id;
    159
    160	error = ilitek_i2c_write_and_read(ts, NULL, 0, 0, buf, 64);
    161	if (error) {
    162		dev_err(dev, "get touch info failed, err:%d\n", error);
    163		goto err_sync_frame;
    164	}
    165
    166	report_max_point = buf[REPORT_COUNT_ADDRESS];
    167	if (report_max_point > ts->max_tp) {
    168		dev_err(dev, "FW report max point:%d > panel info. max:%d\n",
    169			report_max_point, ts->max_tp);
    170		error = -EINVAL;
    171		goto err_sync_frame;
    172	}
    173
    174	count = DIV_ROUND_UP(report_max_point, packet_max_point);
    175	for (i = 1; i < count; i++) {
    176		error = ilitek_i2c_write_and_read(ts, NULL, 0, 0,
    177						  buf + i * 64, 64);
    178		if (error) {
    179			dev_err(dev, "get touch info. failed, cnt:%d, err:%d\n",
    180				count, error);
    181			goto err_sync_frame;
    182		}
    183	}
    184
    185	for (i = 0; i < report_max_point; i++) {
    186		status = buf[i * packet_len + 1] & 0x40;
    187		if (!status)
    188			continue;
    189
    190		id = buf[i * packet_len + 1] & 0x3F;
    191
    192		x = get_unaligned_le16(buf + i * packet_len + 2);
    193		y = get_unaligned_le16(buf + i * packet_len + 4);
    194
    195		if (x > ts->screen_max_x || x < ts->screen_min_x ||
    196		    y > ts->screen_max_y || y < ts->screen_min_y) {
    197			dev_warn(dev, "invalid position, X[%d,%u,%d], Y[%d,%u,%d]\n",
    198				 ts->screen_min_x, x, ts->screen_max_x,
    199				 ts->screen_min_y, y, ts->screen_max_y);
    200			continue;
    201		}
    202
    203		ilitek_touch_down(ts, id, x, y);
    204	}
    205
    206err_sync_frame:
    207	input_mt_sync_frame(input);
    208	input_sync(input);
    209	return error;
    210}
    211
    212/* APIs of cmds for ILITEK Touch IC */
    213static int api_protocol_set_cmd(struct ilitek_ts_data *ts,
    214				u16 idx, u8 *inbuf, u8 *outbuf)
    215{
    216	u16 cmd;
    217	int error;
    218
    219	if (idx >= MAX_CMD_CNT)
    220		return -EINVAL;
    221
    222	cmd = ts->ptl_cb_func[idx].cmd;
    223	error = ts->ptl_cb_func[idx].func(ts, cmd, inbuf, outbuf);
    224	if (error)
    225		return error;
    226
    227	return 0;
    228}
    229
    230static int api_protocol_get_ptl_ver(struct ilitek_ts_data *ts,
    231				    u16 cmd, u8 *inbuf, u8 *outbuf)
    232{
    233	int error;
    234	u8 buf[64];
    235
    236	buf[0] = cmd;
    237	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 3);
    238	if (error)
    239		return error;
    240
    241	ts->ptl.ver = get_unaligned_be16(outbuf);
    242	ts->ptl.ver_major = outbuf[0];
    243
    244	return 0;
    245}
    246
    247static int api_protocol_get_mcu_ver(struct ilitek_ts_data *ts,
    248				    u16 cmd, u8 *inbuf, u8 *outbuf)
    249{
    250	int error;
    251	u8 buf[64];
    252
    253	buf[0] = cmd;
    254	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 32);
    255	if (error)
    256		return error;
    257
    258	ts->mcu_ver = get_unaligned_le16(outbuf);
    259	memset(ts->product_id, 0, sizeof(ts->product_id));
    260	memcpy(ts->product_id, outbuf + 6, 26);
    261
    262	return 0;
    263}
    264
    265static int api_protocol_get_fw_ver(struct ilitek_ts_data *ts,
    266				   u16 cmd, u8 *inbuf, u8 *outbuf)
    267{
    268	int error;
    269	u8 buf[64];
    270
    271	buf[0] = cmd;
    272	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 8);
    273	if (error)
    274		return error;
    275
    276	memcpy(ts->firmware_ver, outbuf, 8);
    277
    278	return 0;
    279}
    280
    281static int api_protocol_get_scrn_res(struct ilitek_ts_data *ts,
    282				     u16 cmd, u8 *inbuf, u8 *outbuf)
    283{
    284	int error;
    285	u8 buf[64];
    286
    287	buf[0] = cmd;
    288	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 8);
    289	if (error)
    290		return error;
    291
    292	ts->screen_min_x = get_unaligned_le16(outbuf);
    293	ts->screen_min_y = get_unaligned_le16(outbuf + 2);
    294	ts->screen_max_x = get_unaligned_le16(outbuf + 4);
    295	ts->screen_max_y = get_unaligned_le16(outbuf + 6);
    296
    297	return 0;
    298}
    299
    300static int api_protocol_get_tp_res(struct ilitek_ts_data *ts,
    301				   u16 cmd, u8 *inbuf, u8 *outbuf)
    302{
    303	int error;
    304	u8 buf[64];
    305
    306	buf[0] = cmd;
    307	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 15);
    308	if (error)
    309		return error;
    310
    311	ts->max_tp = outbuf[8];
    312	if (ts->max_tp > ILITEK_SUPPORT_MAX_POINT) {
    313		dev_err(&ts->client->dev, "Invalid MAX_TP:%d from FW\n",
    314			ts->max_tp);
    315		return -EINVAL;
    316	}
    317
    318	return 0;
    319}
    320
    321static int api_protocol_get_ic_mode(struct ilitek_ts_data *ts,
    322				    u16 cmd, u8 *inbuf, u8 *outbuf)
    323{
    324	int error;
    325	u8 buf[64];
    326
    327	buf[0] = cmd;
    328	error = ilitek_i2c_write_and_read(ts, buf, 1, 5, outbuf, 2);
    329	if (error)
    330		return error;
    331
    332	ts->ic_mode = outbuf[0];
    333	return 0;
    334}
    335
    336static int api_protocol_set_ic_sleep(struct ilitek_ts_data *ts,
    337				     u16 cmd, u8 *inbuf, u8 *outbuf)
    338{
    339	u8 buf[64];
    340
    341	buf[0] = cmd;
    342	return ilitek_i2c_write_and_read(ts, buf, 1, 0, NULL, 0);
    343}
    344
    345static int api_protocol_set_ic_wake(struct ilitek_ts_data *ts,
    346				    u16 cmd, u8 *inbuf, u8 *outbuf)
    347{
    348	u8 buf[64];
    349
    350	buf[0] = cmd;
    351	return ilitek_i2c_write_and_read(ts, buf, 1, 0, NULL, 0);
    352}
    353
    354static const struct ilitek_protocol_map ptl_func_map[] = {
    355	/* common cmds */
    356	[GET_PTL_VER] = {
    357		ILITEK_TP_CMD_GET_PRL_VER, "GET_PTL_VER",
    358		api_protocol_get_ptl_ver
    359	},
    360	[GET_FW_VER] = {
    361		ILITEK_TP_CMD_GET_FW_VER, "GET_FW_VER",
    362		api_protocol_get_fw_ver
    363	},
    364	[GET_SCRN_RES] = {
    365		ILITEK_TP_CMD_GET_SCRN_RES, "GET_SCRN_RES",
    366		api_protocol_get_scrn_res
    367	},
    368	[GET_TP_RES] = {
    369		ILITEK_TP_CMD_GET_TP_RES, "GET_TP_RES",
    370		api_protocol_get_tp_res
    371	},
    372	[GET_IC_MODE] = {
    373		ILITEK_TP_CMD_GET_IC_MODE, "GET_IC_MODE",
    374			   api_protocol_get_ic_mode
    375	},
    376	[GET_MCU_VER] = {
    377		ILITEK_TP_CMD_GET_MCU_VER, "GET_MOD_VER",
    378			   api_protocol_get_mcu_ver
    379	},
    380	[SET_IC_SLEEP] = {
    381		ILITEK_TP_CMD_SET_IC_SLEEP, "SET_IC_SLEEP",
    382		api_protocol_set_ic_sleep
    383	},
    384	[SET_IC_WAKE] = {
    385		ILITEK_TP_CMD_SET_IC_WAKE, "SET_IC_WAKE",
    386		api_protocol_set_ic_wake
    387	},
    388};
    389
    390/* Probe APIs */
    391static void ilitek_reset(struct ilitek_ts_data *ts, int delay)
    392{
    393	if (ts->reset_gpio) {
    394		gpiod_set_value(ts->reset_gpio, 1);
    395		mdelay(10);
    396		gpiod_set_value(ts->reset_gpio, 0);
    397		mdelay(delay);
    398	}
    399}
    400
    401static int ilitek_protocol_init(struct ilitek_ts_data *ts)
    402{
    403	int error;
    404	u8 outbuf[64];
    405
    406	ts->ptl_cb_func = ptl_func_map;
    407	ts->reset_time = 600;
    408
    409	error = api_protocol_set_cmd(ts, GET_PTL_VER, NULL, outbuf);
    410	if (error)
    411		return error;
    412
    413	/* Protocol v3 is not support currently */
    414	if (ts->ptl.ver_major == 0x3 ||
    415	    ts->ptl.ver == BL_V1_6 ||
    416	    ts->ptl.ver == BL_V1_7)
    417		return -EINVAL;
    418
    419	return 0;
    420}
    421
    422static int ilitek_read_tp_info(struct ilitek_ts_data *ts, bool boot)
    423{
    424	u8 outbuf[256];
    425	int error;
    426
    427	error = api_protocol_set_cmd(ts, GET_PTL_VER, NULL, outbuf);
    428	if (error)
    429		return error;
    430
    431	error = api_protocol_set_cmd(ts, GET_MCU_VER, NULL, outbuf);
    432	if (error)
    433		return error;
    434
    435	error = api_protocol_set_cmd(ts, GET_FW_VER, NULL, outbuf);
    436	if (error)
    437		return error;
    438
    439	if (boot) {
    440		error = api_protocol_set_cmd(ts, GET_SCRN_RES, NULL,
    441					     outbuf);
    442		if (error)
    443			return error;
    444	}
    445
    446	error = api_protocol_set_cmd(ts, GET_TP_RES, NULL, outbuf);
    447	if (error)
    448		return error;
    449
    450	error = api_protocol_set_cmd(ts, GET_IC_MODE, NULL, outbuf);
    451	if (error)
    452		return error;
    453
    454	return 0;
    455}
    456
    457static int ilitek_input_dev_init(struct device *dev, struct ilitek_ts_data *ts)
    458{
    459	int error;
    460	struct input_dev *input;
    461
    462	input = devm_input_allocate_device(dev);
    463	if (!input)
    464		return -ENOMEM;
    465
    466	ts->input_dev = input;
    467	input->name = ILITEK_TS_NAME;
    468	input->id.bustype = BUS_I2C;
    469
    470	__set_bit(INPUT_PROP_DIRECT, input->propbit);
    471
    472	input_set_abs_params(input, ABS_MT_POSITION_X,
    473			     ts->screen_min_x, ts->screen_max_x, 0, 0);
    474	input_set_abs_params(input, ABS_MT_POSITION_Y,
    475			     ts->screen_min_y, ts->screen_max_y, 0, 0);
    476
    477	touchscreen_parse_properties(input, true, &ts->prop);
    478
    479	error = input_mt_init_slots(input, ts->max_tp,
    480				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
    481	if (error) {
    482		dev_err(dev, "initialize MT slots failed, err:%d\n", error);
    483		return error;
    484	}
    485
    486	error = input_register_device(input);
    487	if (error) {
    488		dev_err(dev, "register input device failed, err:%d\n", error);
    489		return error;
    490	}
    491
    492	return 0;
    493}
    494
    495static irqreturn_t ilitek_i2c_isr(int irq, void *dev_id)
    496{
    497	struct ilitek_ts_data *ts = dev_id;
    498	int error;
    499
    500	error = ilitek_process_and_report_v6(ts);
    501	if (error < 0) {
    502		dev_err(&ts->client->dev, "[%s] err:%d\n", __func__, error);
    503		return IRQ_NONE;
    504	}
    505
    506	return IRQ_HANDLED;
    507}
    508
    509static ssize_t firmware_version_show(struct device *dev,
    510				     struct device_attribute *attr, char *buf)
    511{
    512	struct i2c_client *client = to_i2c_client(dev);
    513	struct ilitek_ts_data *ts = i2c_get_clientdata(client);
    514
    515	return scnprintf(buf, PAGE_SIZE,
    516			 "fw version: [%02X%02X.%02X%02X.%02X%02X.%02X%02X]\n",
    517			 ts->firmware_ver[0], ts->firmware_ver[1],
    518			 ts->firmware_ver[2], ts->firmware_ver[3],
    519			 ts->firmware_ver[4], ts->firmware_ver[5],
    520			 ts->firmware_ver[6], ts->firmware_ver[7]);
    521}
    522static DEVICE_ATTR_RO(firmware_version);
    523
    524static ssize_t product_id_show(struct device *dev,
    525			       struct device_attribute *attr, char *buf)
    526{
    527	struct i2c_client *client = to_i2c_client(dev);
    528	struct ilitek_ts_data *ts = i2c_get_clientdata(client);
    529
    530	return scnprintf(buf, PAGE_SIZE, "product id: [%04X], module: [%s]\n",
    531			 ts->mcu_ver, ts->product_id);
    532}
    533static DEVICE_ATTR_RO(product_id);
    534
    535static struct attribute *ilitek_sysfs_attrs[] = {
    536	&dev_attr_firmware_version.attr,
    537	&dev_attr_product_id.attr,
    538	NULL
    539};
    540
    541static struct attribute_group ilitek_attrs_group = {
    542	.attrs = ilitek_sysfs_attrs,
    543};
    544
    545static int ilitek_ts_i2c_probe(struct i2c_client *client,
    546			       const struct i2c_device_id *id)
    547{
    548	struct ilitek_ts_data *ts;
    549	struct device *dev = &client->dev;
    550	int error;
    551
    552	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    553		dev_err(dev, "i2c check functionality failed\n");
    554		return -ENXIO;
    555	}
    556
    557	ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
    558	if (!ts)
    559		return -ENOMEM;
    560
    561	ts->client = client;
    562	i2c_set_clientdata(client, ts);
    563
    564	ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
    565	if (IS_ERR(ts->reset_gpio)) {
    566		error = PTR_ERR(ts->reset_gpio);
    567		dev_err(dev, "request gpiod failed: %d", error);
    568		return error;
    569	}
    570
    571	ilitek_reset(ts, 1000);
    572
    573	error = ilitek_protocol_init(ts);
    574	if (error) {
    575		dev_err(dev, "protocol init failed: %d", error);
    576		return error;
    577	}
    578
    579	error = ilitek_read_tp_info(ts, true);
    580	if (error) {
    581		dev_err(dev, "read tp info failed: %d", error);
    582		return error;
    583	}
    584
    585	error = ilitek_input_dev_init(dev, ts);
    586	if (error) {
    587		dev_err(dev, "input dev init failed: %d", error);
    588		return error;
    589	}
    590
    591	error = devm_request_threaded_irq(dev, ts->client->irq,
    592					  NULL, ilitek_i2c_isr, IRQF_ONESHOT,
    593					  "ilitek_touch_irq", ts);
    594	if (error) {
    595		dev_err(dev, "request threaded irq failed: %d\n", error);
    596		return error;
    597	}
    598
    599	error = devm_device_add_group(dev, &ilitek_attrs_group);
    600	if (error) {
    601		dev_err(dev, "sysfs create group failed: %d\n", error);
    602		return error;
    603	}
    604
    605	return 0;
    606}
    607
    608static int __maybe_unused ilitek_suspend(struct device *dev)
    609{
    610	struct i2c_client *client = to_i2c_client(dev);
    611	struct ilitek_ts_data *ts = i2c_get_clientdata(client);
    612	int error;
    613
    614	disable_irq(client->irq);
    615
    616	if (!device_may_wakeup(dev)) {
    617		error = api_protocol_set_cmd(ts, SET_IC_SLEEP, NULL, NULL);
    618		if (error)
    619			return error;
    620	}
    621
    622	return 0;
    623}
    624
    625static int __maybe_unused ilitek_resume(struct device *dev)
    626{
    627	struct i2c_client *client = to_i2c_client(dev);
    628	struct ilitek_ts_data *ts = i2c_get_clientdata(client);
    629	int error;
    630
    631	if (!device_may_wakeup(dev)) {
    632		error = api_protocol_set_cmd(ts, SET_IC_WAKE, NULL, NULL);
    633		if (error)
    634			return error;
    635
    636		ilitek_reset(ts, ts->reset_time);
    637	}
    638
    639	enable_irq(client->irq);
    640
    641	return 0;
    642}
    643
    644static SIMPLE_DEV_PM_OPS(ilitek_pm_ops, ilitek_suspend, ilitek_resume);
    645
    646static const struct i2c_device_id ilitek_ts_i2c_id[] = {
    647	{ ILITEK_TS_NAME, 0 },
    648	{ },
    649};
    650MODULE_DEVICE_TABLE(i2c, ilitek_ts_i2c_id);
    651
    652#ifdef CONFIG_ACPI
    653static const struct acpi_device_id ilitekts_acpi_id[] = {
    654	{ "ILTK0001", 0 },
    655	{ },
    656};
    657MODULE_DEVICE_TABLE(acpi, ilitekts_acpi_id);
    658#endif
    659
    660#ifdef CONFIG_OF
    661static const struct of_device_id ilitek_ts_i2c_match[] = {
    662	{.compatible = "ilitek,ili2130",},
    663	{.compatible = "ilitek,ili2131",},
    664	{.compatible = "ilitek,ili2132",},
    665	{.compatible = "ilitek,ili2316",},
    666	{.compatible = "ilitek,ili2322",},
    667	{.compatible = "ilitek,ili2323",},
    668	{.compatible = "ilitek,ili2326",},
    669	{.compatible = "ilitek,ili2520",},
    670	{.compatible = "ilitek,ili2521",},
    671	{ },
    672};
    673MODULE_DEVICE_TABLE(of, ilitek_ts_i2c_match);
    674#endif
    675
    676static struct i2c_driver ilitek_ts_i2c_driver = {
    677	.driver = {
    678		.name = ILITEK_TS_NAME,
    679		.pm = &ilitek_pm_ops,
    680		.of_match_table = of_match_ptr(ilitek_ts_i2c_match),
    681		.acpi_match_table = ACPI_PTR(ilitekts_acpi_id),
    682	},
    683	.probe = ilitek_ts_i2c_probe,
    684	.id_table = ilitek_ts_i2c_id,
    685};
    686module_i2c_driver(ilitek_ts_i2c_driver);
    687
    688MODULE_AUTHOR("ILITEK");
    689MODULE_DESCRIPTION("ILITEK I2C Touchscreen Driver");
    690MODULE_LICENSE("GPL");