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