18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Touchscreen driver for Dialog Semiconductor DA9034
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2008 Marvell International Ltd.
68c2ecf20Sopenharmony_ci *	Fengwei Yin <fengwei.yin@marvell.com>
78c2ecf20Sopenharmony_ci *	Bin Yang  <bin.yang@marvell.com>
88c2ecf20Sopenharmony_ci *	Eric Miao <eric.miao@marvell.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/delay.h>
148c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
158c2ecf20Sopenharmony_ci#include <linux/input.h>
168c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
178c2ecf20Sopenharmony_ci#include <linux/mfd/da903x.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define DA9034_MANUAL_CTRL	0x50
218c2ecf20Sopenharmony_ci#define DA9034_LDO_ADC_EN	(1 << 4)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define DA9034_AUTO_CTRL1	0x51
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define DA9034_AUTO_CTRL2	0x52
268c2ecf20Sopenharmony_ci#define DA9034_AUTO_TSI_EN	(1 << 3)
278c2ecf20Sopenharmony_ci#define DA9034_PEN_DETECT	(1 << 4)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define DA9034_TSI_CTRL1	0x53
308c2ecf20Sopenharmony_ci#define DA9034_TSI_CTRL2	0x54
318c2ecf20Sopenharmony_ci#define DA9034_TSI_X_MSB	0x6c
328c2ecf20Sopenharmony_ci#define DA9034_TSI_Y_MSB	0x6d
338c2ecf20Sopenharmony_ci#define DA9034_TSI_XY_LSB	0x6e
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cienum {
368c2ecf20Sopenharmony_ci	STATE_IDLE,	/* wait for pendown */
378c2ecf20Sopenharmony_ci	STATE_BUSY,	/* TSI busy sampling */
388c2ecf20Sopenharmony_ci	STATE_STOP,	/* sample available */
398c2ecf20Sopenharmony_ci	STATE_WAIT,	/* Wait to start next sample */
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cienum {
438c2ecf20Sopenharmony_ci	EVENT_PEN_DOWN,
448c2ecf20Sopenharmony_ci	EVENT_PEN_UP,
458c2ecf20Sopenharmony_ci	EVENT_TSI_READY,
468c2ecf20Sopenharmony_ci	EVENT_TIMEDOUT,
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct da9034_touch {
508c2ecf20Sopenharmony_ci	struct device		*da9034_dev;
518c2ecf20Sopenharmony_ci	struct input_dev	*input_dev;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	struct delayed_work	tsi_work;
548c2ecf20Sopenharmony_ci	struct notifier_block	notifier;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	int	state;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	int	interval_ms;
598c2ecf20Sopenharmony_ci	int	x_inverted;
608c2ecf20Sopenharmony_ci	int	y_inverted;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	int	last_x;
638c2ecf20Sopenharmony_ci	int	last_y;
648c2ecf20Sopenharmony_ci};
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic inline int is_pen_down(struct da9034_touch *touch)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	return da903x_query_status(touch->da9034_dev, DA9034_STATUS_PEN_DOWN);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline int detect_pen_down(struct da9034_touch *touch, int on)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	if (on)
748c2ecf20Sopenharmony_ci		return da903x_set_bits(touch->da9034_dev,
758c2ecf20Sopenharmony_ci				DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
768c2ecf20Sopenharmony_ci	else
778c2ecf20Sopenharmony_ci		return da903x_clr_bits(touch->da9034_dev,
788c2ecf20Sopenharmony_ci				DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic int read_tsi(struct da9034_touch *touch)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	uint8_t _x, _y, _v;
848c2ecf20Sopenharmony_ci	int ret;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	ret = da903x_read(touch->da9034_dev, DA9034_TSI_X_MSB, &_x);
878c2ecf20Sopenharmony_ci	if (ret)
888c2ecf20Sopenharmony_ci		return ret;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	ret = da903x_read(touch->da9034_dev, DA9034_TSI_Y_MSB, &_y);
918c2ecf20Sopenharmony_ci	if (ret)
928c2ecf20Sopenharmony_ci		return ret;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	ret = da903x_read(touch->da9034_dev, DA9034_TSI_XY_LSB, &_v);
958c2ecf20Sopenharmony_ci	if (ret)
968c2ecf20Sopenharmony_ci		return ret;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	touch->last_x = ((_x << 2) & 0x3fc) | (_v & 0x3);
998c2ecf20Sopenharmony_ci	touch->last_y = ((_y << 2) & 0x3fc) | ((_v & 0xc) >> 2);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return 0;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic inline int start_tsi(struct da9034_touch *touch)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	return da903x_set_bits(touch->da9034_dev,
1078c2ecf20Sopenharmony_ci			DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic inline int stop_tsi(struct da9034_touch *touch)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	return da903x_clr_bits(touch->da9034_dev,
1138c2ecf20Sopenharmony_ci			DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic inline void report_pen_down(struct da9034_touch *touch)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	int x = touch->last_x;
1198c2ecf20Sopenharmony_ci	int y = touch->last_y;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	x &= 0xfff;
1228c2ecf20Sopenharmony_ci	if (touch->x_inverted)
1238c2ecf20Sopenharmony_ci		x = 1024 - x;
1248c2ecf20Sopenharmony_ci	y &= 0xfff;
1258c2ecf20Sopenharmony_ci	if (touch->y_inverted)
1268c2ecf20Sopenharmony_ci		y = 1024 - y;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	input_report_abs(touch->input_dev, ABS_X, x);
1298c2ecf20Sopenharmony_ci	input_report_abs(touch->input_dev, ABS_Y, y);
1308c2ecf20Sopenharmony_ci	input_report_key(touch->input_dev, BTN_TOUCH, 1);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	input_sync(touch->input_dev);
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic inline void report_pen_up(struct da9034_touch *touch)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	input_report_key(touch->input_dev, BTN_TOUCH, 0);
1388c2ecf20Sopenharmony_ci	input_sync(touch->input_dev);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic void da9034_event_handler(struct da9034_touch *touch, int event)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	int err;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	switch (touch->state) {
1468c2ecf20Sopenharmony_ci	case STATE_IDLE:
1478c2ecf20Sopenharmony_ci		if (event != EVENT_PEN_DOWN)
1488c2ecf20Sopenharmony_ci			break;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci		/* Enable auto measurement of the TSI, this will
1518c2ecf20Sopenharmony_ci		 * automatically disable pen down detection
1528c2ecf20Sopenharmony_ci		 */
1538c2ecf20Sopenharmony_ci		err = start_tsi(touch);
1548c2ecf20Sopenharmony_ci		if (err)
1558c2ecf20Sopenharmony_ci			goto err_reset;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		touch->state = STATE_BUSY;
1588c2ecf20Sopenharmony_ci		break;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	case STATE_BUSY:
1618c2ecf20Sopenharmony_ci		if (event != EVENT_TSI_READY)
1628c2ecf20Sopenharmony_ci			break;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci		err = read_tsi(touch);
1658c2ecf20Sopenharmony_ci		if (err)
1668c2ecf20Sopenharmony_ci			goto err_reset;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci		/* Disable auto measurement of the TSI, so that
1698c2ecf20Sopenharmony_ci		 * pen down status will be available
1708c2ecf20Sopenharmony_ci		 */
1718c2ecf20Sopenharmony_ci		err = stop_tsi(touch);
1728c2ecf20Sopenharmony_ci		if (err)
1738c2ecf20Sopenharmony_ci			goto err_reset;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		touch->state = STATE_STOP;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		/* FIXME: PEN_{UP/DOWN} events are expected to be
1788c2ecf20Sopenharmony_ci		 * available by stopping TSI, but this is found not
1798c2ecf20Sopenharmony_ci		 * always true, delay and simulate such an event
1808c2ecf20Sopenharmony_ci		 * here is more reliable
1818c2ecf20Sopenharmony_ci		 */
1828c2ecf20Sopenharmony_ci		mdelay(1);
1838c2ecf20Sopenharmony_ci		da9034_event_handler(touch,
1848c2ecf20Sopenharmony_ci				     is_pen_down(touch) ? EVENT_PEN_DOWN :
1858c2ecf20Sopenharmony_ci							  EVENT_PEN_UP);
1868c2ecf20Sopenharmony_ci		break;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	case STATE_STOP:
1898c2ecf20Sopenharmony_ci		if (event == EVENT_PEN_DOWN) {
1908c2ecf20Sopenharmony_ci			report_pen_down(touch);
1918c2ecf20Sopenharmony_ci			schedule_delayed_work(&touch->tsi_work,
1928c2ecf20Sopenharmony_ci				msecs_to_jiffies(touch->interval_ms));
1938c2ecf20Sopenharmony_ci			touch->state = STATE_WAIT;
1948c2ecf20Sopenharmony_ci		}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		if (event == EVENT_PEN_UP) {
1978c2ecf20Sopenharmony_ci			report_pen_up(touch);
1988c2ecf20Sopenharmony_ci			touch->state = STATE_IDLE;
1998c2ecf20Sopenharmony_ci		}
2008c2ecf20Sopenharmony_ci		break;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	case STATE_WAIT:
2038c2ecf20Sopenharmony_ci		if (event != EVENT_TIMEDOUT)
2048c2ecf20Sopenharmony_ci			break;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		if (is_pen_down(touch)) {
2078c2ecf20Sopenharmony_ci			start_tsi(touch);
2088c2ecf20Sopenharmony_ci			touch->state = STATE_BUSY;
2098c2ecf20Sopenharmony_ci		} else {
2108c2ecf20Sopenharmony_ci			report_pen_up(touch);
2118c2ecf20Sopenharmony_ci			touch->state = STATE_IDLE;
2128c2ecf20Sopenharmony_ci		}
2138c2ecf20Sopenharmony_ci		break;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci	return;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cierr_reset:
2188c2ecf20Sopenharmony_ci	touch->state = STATE_IDLE;
2198c2ecf20Sopenharmony_ci	stop_tsi(touch);
2208c2ecf20Sopenharmony_ci	detect_pen_down(touch, 1);
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic void da9034_tsi_work(struct work_struct *work)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	struct da9034_touch *touch =
2268c2ecf20Sopenharmony_ci		container_of(work, struct da9034_touch, tsi_work.work);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	da9034_event_handler(touch, EVENT_TIMEDOUT);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic int da9034_touch_notifier(struct notifier_block *nb,
2328c2ecf20Sopenharmony_ci				 unsigned long event, void *data)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct da9034_touch *touch =
2358c2ecf20Sopenharmony_ci		container_of(nb, struct da9034_touch, notifier);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	if (event & DA9034_EVENT_TSI_READY)
2388c2ecf20Sopenharmony_ci		da9034_event_handler(touch, EVENT_TSI_READY);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if ((event & DA9034_EVENT_PEN_DOWN) && touch->state == STATE_IDLE)
2418c2ecf20Sopenharmony_ci		da9034_event_handler(touch, EVENT_PEN_DOWN);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return 0;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic int da9034_touch_open(struct input_dev *dev)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	struct da9034_touch *touch = input_get_drvdata(dev);
2498c2ecf20Sopenharmony_ci	int ret;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	ret = da903x_register_notifier(touch->da9034_dev, &touch->notifier,
2528c2ecf20Sopenharmony_ci			DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
2538c2ecf20Sopenharmony_ci	if (ret)
2548c2ecf20Sopenharmony_ci		return -EBUSY;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/* Enable ADC LDO */
2578c2ecf20Sopenharmony_ci	ret = da903x_set_bits(touch->da9034_dev,
2588c2ecf20Sopenharmony_ci			DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
2598c2ecf20Sopenharmony_ci	if (ret)
2608c2ecf20Sopenharmony_ci		return ret;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* TSI_DELAY: 3 slots, TSI_SKIP: 3 slots */
2638c2ecf20Sopenharmony_ci	ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL1, 0x1b);
2648c2ecf20Sopenharmony_ci	if (ret)
2658c2ecf20Sopenharmony_ci		return ret;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL2, 0x00);
2688c2ecf20Sopenharmony_ci	if (ret)
2698c2ecf20Sopenharmony_ci		return ret;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	touch->state = STATE_IDLE;
2728c2ecf20Sopenharmony_ci	detect_pen_down(touch, 1);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	return 0;
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic void da9034_touch_close(struct input_dev *dev)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct da9034_touch *touch = input_get_drvdata(dev);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	da903x_unregister_notifier(touch->da9034_dev, &touch->notifier,
2828c2ecf20Sopenharmony_ci			DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&touch->tsi_work);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	touch->state = STATE_IDLE;
2878c2ecf20Sopenharmony_ci	stop_tsi(touch);
2888c2ecf20Sopenharmony_ci	detect_pen_down(touch, 0);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* Disable ADC LDO */
2918c2ecf20Sopenharmony_ci	da903x_clr_bits(touch->da9034_dev,
2928c2ecf20Sopenharmony_ci			DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic int da9034_touch_probe(struct platform_device *pdev)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev);
2998c2ecf20Sopenharmony_ci	struct da9034_touch *touch;
3008c2ecf20Sopenharmony_ci	struct input_dev *input_dev;
3018c2ecf20Sopenharmony_ci	int error;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	touch = devm_kzalloc(&pdev->dev, sizeof(struct da9034_touch),
3048c2ecf20Sopenharmony_ci			     GFP_KERNEL);
3058c2ecf20Sopenharmony_ci	if (!touch) {
3068c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to allocate driver data\n");
3078c2ecf20Sopenharmony_ci		return -ENOMEM;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	touch->da9034_dev = pdev->dev.parent;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (pdata) {
3138c2ecf20Sopenharmony_ci		touch->interval_ms	= pdata->interval_ms;
3148c2ecf20Sopenharmony_ci		touch->x_inverted	= pdata->x_inverted;
3158c2ecf20Sopenharmony_ci		touch->y_inverted	= pdata->y_inverted;
3168c2ecf20Sopenharmony_ci	} else {
3178c2ecf20Sopenharmony_ci		/* fallback into default */
3188c2ecf20Sopenharmony_ci		touch->interval_ms	= 10;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work);
3228c2ecf20Sopenharmony_ci	touch->notifier.notifier_call = da9034_touch_notifier;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	input_dev = devm_input_allocate_device(&pdev->dev);
3258c2ecf20Sopenharmony_ci	if (!input_dev) {
3268c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to allocate input device\n");
3278c2ecf20Sopenharmony_ci		return -ENOMEM;
3288c2ecf20Sopenharmony_ci	}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	input_dev->name		= pdev->name;
3318c2ecf20Sopenharmony_ci	input_dev->open		= da9034_touch_open;
3328c2ecf20Sopenharmony_ci	input_dev->close	= da9034_touch_close;
3338c2ecf20Sopenharmony_ci	input_dev->dev.parent	= &pdev->dev;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	__set_bit(EV_ABS, input_dev->evbit);
3368c2ecf20Sopenharmony_ci	__set_bit(ABS_X, input_dev->absbit);
3378c2ecf20Sopenharmony_ci	__set_bit(ABS_Y, input_dev->absbit);
3388c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
3398c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	__set_bit(EV_KEY, input_dev->evbit);
3428c2ecf20Sopenharmony_ci	__set_bit(BTN_TOUCH, input_dev->keybit);
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	touch->input_dev = input_dev;
3458c2ecf20Sopenharmony_ci	input_set_drvdata(input_dev, touch);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	error = input_register_device(input_dev);
3488c2ecf20Sopenharmony_ci	if (error)
3498c2ecf20Sopenharmony_ci		return error;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic struct platform_driver da9034_touch_driver = {
3558c2ecf20Sopenharmony_ci	.driver	= {
3568c2ecf20Sopenharmony_ci		.name	= "da9034-touch",
3578c2ecf20Sopenharmony_ci	},
3588c2ecf20Sopenharmony_ci	.probe		= da9034_touch_probe,
3598c2ecf20Sopenharmony_ci};
3608c2ecf20Sopenharmony_cimodule_platform_driver(da9034_touch_driver);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
3638c2ecf20Sopenharmony_ciMODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>");
3648c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3658c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:da9034-touch");
366