18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TSI driver for Dialog DA9052 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright(c) 2012 Dialog Semiconductor Ltd. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: David Dajun Chen <dchen@diasemi.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/input.h> 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/mfd/da9052/reg.h> 168c2ecf20Sopenharmony_ci#include <linux/mfd/da9052/da9052.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define TSI_PEN_DOWN_STATUS 0x40 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct da9052_tsi { 218c2ecf20Sopenharmony_ci struct da9052 *da9052; 228c2ecf20Sopenharmony_ci struct input_dev *dev; 238c2ecf20Sopenharmony_ci struct delayed_work ts_pen_work; 248c2ecf20Sopenharmony_ci bool stopped; 258c2ecf20Sopenharmony_ci bool adc_on; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void da9052_ts_adc_toggle(struct da9052_tsi *tsi, bool on) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 0, on); 318c2ecf20Sopenharmony_ci tsi->adc_on = on; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = data; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (!tsi->stopped) { 398c2ecf20Sopenharmony_ci /* Mask PEN_DOWN event and unmask TSI_READY event */ 408c2ecf20Sopenharmony_ci da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN); 418c2ecf20Sopenharmony_ci da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci da9052_ts_adc_toggle(tsi, true); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return IRQ_HANDLED; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic void da9052_ts_read(struct da9052_tsi *tsi) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct input_dev *input = tsi->dev; 548c2ecf20Sopenharmony_ci int ret; 558c2ecf20Sopenharmony_ci u16 x, y, z; 568c2ecf20Sopenharmony_ci u8 v; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci ret = da9052_reg_read(tsi->da9052, DA9052_TSI_X_MSB_REG); 598c2ecf20Sopenharmony_ci if (ret < 0) 608c2ecf20Sopenharmony_ci return; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci x = (u16) ret; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Y_MSB_REG); 658c2ecf20Sopenharmony_ci if (ret < 0) 668c2ecf20Sopenharmony_ci return; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci y = (u16) ret; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Z_MSB_REG); 718c2ecf20Sopenharmony_ci if (ret < 0) 728c2ecf20Sopenharmony_ci return; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci z = (u16) ret; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); 778c2ecf20Sopenharmony_ci if (ret < 0) 788c2ecf20Sopenharmony_ci return; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci v = (u8) ret; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci x = ((x << 2) & 0x3fc) | (v & 0x3); 838c2ecf20Sopenharmony_ci y = ((y << 2) & 0x3fc) | ((v & 0xc) >> 2); 848c2ecf20Sopenharmony_ci z = ((z << 2) & 0x3fc) | ((v & 0x30) >> 4); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci input_report_key(input, BTN_TOUCH, 1); 878c2ecf20Sopenharmony_ci input_report_abs(input, ABS_X, x); 888c2ecf20Sopenharmony_ci input_report_abs(input, ABS_Y, y); 898c2ecf20Sopenharmony_ci input_report_abs(input, ABS_PRESSURE, z); 908c2ecf20Sopenharmony_ci input_sync(input); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic irqreturn_t da9052_ts_datardy_irq(int irq, void *data) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = data; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci da9052_ts_read(tsi); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic void da9052_ts_pen_work(struct work_struct *work) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, 1058c2ecf20Sopenharmony_ci ts_pen_work.work); 1068c2ecf20Sopenharmony_ci if (!tsi->stopped) { 1078c2ecf20Sopenharmony_ci int ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); 1088c2ecf20Sopenharmony_ci if (ret < 0 || (ret & TSI_PEN_DOWN_STATUS)) { 1098c2ecf20Sopenharmony_ci /* Pen is still DOWN (or read error) */ 1108c2ecf20Sopenharmony_ci schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci struct input_dev *input = tsi->dev; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Pen UP */ 1158c2ecf20Sopenharmony_ci da9052_ts_adc_toggle(tsi, false); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Report Pen UP */ 1188c2ecf20Sopenharmony_ci input_report_key(input, BTN_TOUCH, 0); 1198c2ecf20Sopenharmony_ci input_report_abs(input, ABS_PRESSURE, 0); 1208c2ecf20Sopenharmony_ci input_sync(input); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* 1238c2ecf20Sopenharmony_ci * FIXME: Fixes the unhandled irq issue when quick 1248c2ecf20Sopenharmony_ci * pen down and pen up events occurs 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_ci ret = da9052_reg_update(tsi->da9052, 1278c2ecf20Sopenharmony_ci DA9052_EVENT_B_REG, 0xC0, 0xC0); 1288c2ecf20Sopenharmony_ci if (ret < 0) 1298c2ecf20Sopenharmony_ci return; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* Mask TSI_READY event and unmask PEN_DOWN event */ 1328c2ecf20Sopenharmony_ci da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); 1338c2ecf20Sopenharmony_ci da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int da9052_ts_configure_gpio(struct da9052 *da9052) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci int error; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci error = da9052_reg_update(da9052, DA9052_GPIO_2_3_REG, 0x30, 0); 1438c2ecf20Sopenharmony_ci if (error < 0) 1448c2ecf20Sopenharmony_ci return error; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci error = da9052_reg_update(da9052, DA9052_GPIO_4_5_REG, 0x33, 0); 1478c2ecf20Sopenharmony_ci if (error < 0) 1488c2ecf20Sopenharmony_ci return error; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci error = da9052_reg_update(da9052, DA9052_GPIO_6_7_REG, 0x33, 0); 1518c2ecf20Sopenharmony_ci if (error < 0) 1528c2ecf20Sopenharmony_ci return error; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return 0; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic int da9052_configure_tsi(struct da9052_tsi *tsi) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci int error; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci error = da9052_ts_configure_gpio(tsi->da9052); 1628c2ecf20Sopenharmony_ci if (error) 1638c2ecf20Sopenharmony_ci return error; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Measure TSI sample every 1ms */ 1668c2ecf20Sopenharmony_ci error = da9052_reg_update(tsi->da9052, DA9052_ADC_CONT_REG, 1678c2ecf20Sopenharmony_ci 1 << 6, 1 << 6); 1688c2ecf20Sopenharmony_ci if (error < 0) 1698c2ecf20Sopenharmony_ci return error; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* TSI_DELAY: 3 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ 1728c2ecf20Sopenharmony_ci error = da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 0xFC, 0xC0); 1738c2ecf20Sopenharmony_ci if (error < 0) 1748c2ecf20Sopenharmony_ci return error; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* Supply TSIRef through LD09 */ 1778c2ecf20Sopenharmony_ci error = da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x59); 1788c2ecf20Sopenharmony_ci if (error < 0) 1798c2ecf20Sopenharmony_ci return error; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci return 0; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic int da9052_ts_input_open(struct input_dev *input_dev) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = input_get_drvdata(input_dev); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci tsi->stopped = false; 1898c2ecf20Sopenharmony_ci mb(); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Unmask PEN_DOWN event */ 1928c2ecf20Sopenharmony_ci da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* Enable Pen Detect Circuit */ 1958c2ecf20Sopenharmony_ci return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1968c2ecf20Sopenharmony_ci 1 << 1, 1 << 1); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic void da9052_ts_input_close(struct input_dev *input_dev) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = input_get_drvdata(input_dev); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci tsi->stopped = true; 2048c2ecf20Sopenharmony_ci mb(); 2058c2ecf20Sopenharmony_ci da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); 2068c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&tsi->ts_pen_work); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (tsi->adc_on) { 2098c2ecf20Sopenharmony_ci da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); 2108c2ecf20Sopenharmony_ci da9052_ts_adc_toggle(tsi, false); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* 2138c2ecf20Sopenharmony_ci * If ADC was on that means that pendwn IRQ was disabled 2148c2ecf20Sopenharmony_ci * twice and we need to enable it to keep enable/disable 2158c2ecf20Sopenharmony_ci * counter balanced. IRQ is still off though. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* Disable Pen Detect Circuit */ 2218c2ecf20Sopenharmony_ci da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic int da9052_ts_probe(struct platform_device *pdev) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci struct da9052 *da9052; 2278c2ecf20Sopenharmony_ci struct da9052_tsi *tsi; 2288c2ecf20Sopenharmony_ci struct input_dev *input_dev; 2298c2ecf20Sopenharmony_ci int error; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci da9052 = dev_get_drvdata(pdev->dev.parent); 2328c2ecf20Sopenharmony_ci if (!da9052) 2338c2ecf20Sopenharmony_ci return -EINVAL; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); 2368c2ecf20Sopenharmony_ci input_dev = input_allocate_device(); 2378c2ecf20Sopenharmony_ci if (!tsi || !input_dev) { 2388c2ecf20Sopenharmony_ci error = -ENOMEM; 2398c2ecf20Sopenharmony_ci goto err_free_mem; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci tsi->da9052 = da9052; 2438c2ecf20Sopenharmony_ci tsi->dev = input_dev; 2448c2ecf20Sopenharmony_ci tsi->stopped = true; 2458c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci input_dev->id.version = 0x0101; 2488c2ecf20Sopenharmony_ci input_dev->id.vendor = 0x15B6; 2498c2ecf20Sopenharmony_ci input_dev->id.product = 0x9052; 2508c2ecf20Sopenharmony_ci input_dev->name = "Dialog DA9052 TouchScreen Driver"; 2518c2ecf20Sopenharmony_ci input_dev->dev.parent = &pdev->dev; 2528c2ecf20Sopenharmony_ci input_dev->open = da9052_ts_input_open; 2538c2ecf20Sopenharmony_ci input_dev->close = da9052_ts_input_close; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci __set_bit(EV_ABS, input_dev->evbit); 2568c2ecf20Sopenharmony_ci __set_bit(EV_KEY, input_dev->evbit); 2578c2ecf20Sopenharmony_ci __set_bit(BTN_TOUCH, input_dev->keybit); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); 2608c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); 2618c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1023, 0, 0); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci input_set_drvdata(input_dev, tsi); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /* Disable Pen Detect Circuit */ 2668c2ecf20Sopenharmony_ci da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Disable ADC */ 2698c2ecf20Sopenharmony_ci da9052_ts_adc_toggle(tsi, false); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN, 2728c2ecf20Sopenharmony_ci "pendown-irq", da9052_ts_pendwn_irq, tsi); 2738c2ecf20Sopenharmony_ci if (error) { 2748c2ecf20Sopenharmony_ci dev_err(tsi->da9052->dev, 2758c2ecf20Sopenharmony_ci "Failed to register PENDWN IRQ: %d\n", error); 2768c2ecf20Sopenharmony_ci goto err_free_mem; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY, 2808c2ecf20Sopenharmony_ci "tsiready-irq", da9052_ts_datardy_irq, tsi); 2818c2ecf20Sopenharmony_ci if (error) { 2828c2ecf20Sopenharmony_ci dev_err(tsi->da9052->dev, 2838c2ecf20Sopenharmony_ci "Failed to register TSIRDY IRQ :%d\n", error); 2848c2ecf20Sopenharmony_ci goto err_free_pendwn_irq; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Mask PEN_DOWN and TSI_READY events */ 2888c2ecf20Sopenharmony_ci da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); 2898c2ecf20Sopenharmony_ci da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci error = da9052_configure_tsi(tsi); 2928c2ecf20Sopenharmony_ci if (error) 2938c2ecf20Sopenharmony_ci goto err_free_datardy_irq; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci error = input_register_device(tsi->dev); 2968c2ecf20Sopenharmony_ci if (error) 2978c2ecf20Sopenharmony_ci goto err_free_datardy_irq; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, tsi); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cierr_free_datardy_irq: 3048c2ecf20Sopenharmony_ci da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); 3058c2ecf20Sopenharmony_cierr_free_pendwn_irq: 3068c2ecf20Sopenharmony_ci da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); 3078c2ecf20Sopenharmony_cierr_free_mem: 3088c2ecf20Sopenharmony_ci kfree(tsi); 3098c2ecf20Sopenharmony_ci input_free_device(input_dev); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return error; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic int da9052_ts_remove(struct platform_device *pdev) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct da9052_tsi *tsi = platform_get_drvdata(pdev); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); 3218c2ecf20Sopenharmony_ci da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci input_unregister_device(tsi->dev); 3248c2ecf20Sopenharmony_ci kfree(tsi); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return 0; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic struct platform_driver da9052_tsi_driver = { 3308c2ecf20Sopenharmony_ci .probe = da9052_ts_probe, 3318c2ecf20Sopenharmony_ci .remove = da9052_ts_remove, 3328c2ecf20Sopenharmony_ci .driver = { 3338c2ecf20Sopenharmony_ci .name = "da9052-tsi", 3348c2ecf20Sopenharmony_ci }, 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cimodule_platform_driver(da9052_tsi_driver); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9052"); 3408c2ecf20Sopenharmony_ciMODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>"); 3418c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3428c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:da9052-tsi"); 343