162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * STMicroelectronics STMPE811 Touchscreen Driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (C) 2010 Luotao Fu <l.fu@pengutronix.de> 662306a36Sopenharmony_ci * All rights reserved. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/interrupt.h> 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/input.h> 1762306a36Sopenharmony_ci#include <linux/input/touchscreen.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/delay.h> 2062306a36Sopenharmony_ci#include <linux/i2c.h> 2162306a36Sopenharmony_ci#include <linux/workqueue.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/mfd/stmpe.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Register layouts and functionalities are identical on all stmpexxx variants 2662306a36Sopenharmony_ci * with touchscreen controller 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci#define STMPE_REG_INT_STA 0x0B 2962306a36Sopenharmony_ci#define STMPE_REG_TSC_CTRL 0x40 3062306a36Sopenharmony_ci#define STMPE_REG_TSC_CFG 0x41 3162306a36Sopenharmony_ci#define STMPE_REG_FIFO_TH 0x4A 3262306a36Sopenharmony_ci#define STMPE_REG_FIFO_STA 0x4B 3362306a36Sopenharmony_ci#define STMPE_REG_FIFO_SIZE 0x4C 3462306a36Sopenharmony_ci#define STMPE_REG_TSC_DATA_XYZ 0x52 3562306a36Sopenharmony_ci#define STMPE_REG_TSC_FRACTION_Z 0x56 3662306a36Sopenharmony_ci#define STMPE_REG_TSC_I_DRIVE 0x58 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define OP_MOD_XYZ 0 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define STMPE_TSC_CTRL_TSC_EN (1<<0) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define STMPE_FIFO_STA_RESET (1<<0) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define STMPE_IRQ_TOUCH_DET 0 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define STMPE_TS_NAME "stmpe-ts" 4762306a36Sopenharmony_ci#define XY_MASK 0xfff 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * struct stmpe_touch - stmpe811 touch screen controller state 5162306a36Sopenharmony_ci * @stmpe: pointer back to STMPE MFD container 5262306a36Sopenharmony_ci * @idev: registered input device 5362306a36Sopenharmony_ci * @work: a work item used to scan the device 5462306a36Sopenharmony_ci * @dev: a pointer back to the MFD cell struct device* 5562306a36Sopenharmony_ci * @prop: Touchscreen properties 5662306a36Sopenharmony_ci * @ave_ctrl: Sample average control 5762306a36Sopenharmony_ci * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples) 5862306a36Sopenharmony_ci * @touch_det_delay: Touch detect interrupt delay 5962306a36Sopenharmony_ci * (0 -> 10 us, 1 -> 50 us, 2 -> 100 us, 3 -> 500 us, 6062306a36Sopenharmony_ci * 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) 6162306a36Sopenharmony_ci * recommended is 3 6262306a36Sopenharmony_ci * @settling: Panel driver settling time 6362306a36Sopenharmony_ci * (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 -> 1 ms, 6462306a36Sopenharmony_ci * 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) 6562306a36Sopenharmony_ci * recommended is 2 6662306a36Sopenharmony_ci * @fraction_z: Length of the fractional part in z 6762306a36Sopenharmony_ci * (fraction_z ([0..7]) = Count of the fractional part) 6862306a36Sopenharmony_ci * recommended is 7 6962306a36Sopenharmony_ci * @i_drive: current limit value of the touchscreen drivers 7062306a36Sopenharmony_ci * (0 -> 20 mA typical 35 mA max, 1 -> 50 mA typical 80 mA max) 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_cistruct stmpe_touch { 7362306a36Sopenharmony_ci struct stmpe *stmpe; 7462306a36Sopenharmony_ci struct input_dev *idev; 7562306a36Sopenharmony_ci struct delayed_work work; 7662306a36Sopenharmony_ci struct device *dev; 7762306a36Sopenharmony_ci struct touchscreen_properties prop; 7862306a36Sopenharmony_ci u8 ave_ctrl; 7962306a36Sopenharmony_ci u8 touch_det_delay; 8062306a36Sopenharmony_ci u8 settling; 8162306a36Sopenharmony_ci u8 fraction_z; 8262306a36Sopenharmony_ci u8 i_drive; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int __stmpe_reset_fifo(struct stmpe *stmpe) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci int ret; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, 9062306a36Sopenharmony_ci STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET); 9162306a36Sopenharmony_ci if (ret) 9262306a36Sopenharmony_ci return ret; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, 9562306a36Sopenharmony_ci STMPE_FIFO_STA_RESET, 0); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic void stmpe_work(struct work_struct *work) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci int int_sta; 10162306a36Sopenharmony_ci u32 timeout = 40; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci struct stmpe_touch *ts = 10462306a36Sopenharmony_ci container_of(work, struct stmpe_touch, work.work); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * touch_det sometimes get desasserted or just get stuck. This appears 11062306a36Sopenharmony_ci * to be a silicon bug, We still have to clearify this with the 11162306a36Sopenharmony_ci * manufacture. As a workaround We release the key anyway if the 11262306a36Sopenharmony_ci * touch_det keeps coming in after 4ms, while the FIFO contains no value 11362306a36Sopenharmony_ci * during the whole time. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) { 11662306a36Sopenharmony_ci timeout--; 11762306a36Sopenharmony_ci int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); 11862306a36Sopenharmony_ci udelay(100); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* reset the FIFO before we report release event */ 12262306a36Sopenharmony_ci __stmpe_reset_fifo(ts->stmpe); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci input_report_abs(ts->idev, ABS_PRESSURE, 0); 12562306a36Sopenharmony_ci input_report_key(ts->idev, BTN_TOUCH, 0); 12662306a36Sopenharmony_ci input_sync(ts->idev); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic irqreturn_t stmpe_ts_handler(int irq, void *data) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci u8 data_set[4]; 13262306a36Sopenharmony_ci int x, y, z; 13362306a36Sopenharmony_ci struct stmpe_touch *ts = data; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* 13662306a36Sopenharmony_ci * Cancel scheduled polling for release if we have new value 13762306a36Sopenharmony_ci * available. Wait if the polling is already running. 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci cancel_delayed_work_sync(&ts->work); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* 14262306a36Sopenharmony_ci * The FIFO sometimes just crashes and stops generating interrupts. This 14362306a36Sopenharmony_ci * appears to be a silicon bug. We still have to clearify this with 14462306a36Sopenharmony_ci * the manufacture. As a workaround we disable the TSC while we are 14562306a36Sopenharmony_ci * collecting data and flush the FIFO after reading 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_ci stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, 14862306a36Sopenharmony_ci STMPE_TSC_CTRL_TSC_EN, 0); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci x = (data_set[0] << 4) | (data_set[1] >> 4); 15362306a36Sopenharmony_ci y = ((data_set[1] & 0xf) << 8) | data_set[2]; 15462306a36Sopenharmony_ci z = data_set[3]; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci touchscreen_report_pos(ts->idev, &ts->prop, x, y, false); 15762306a36Sopenharmony_ci input_report_abs(ts->idev, ABS_PRESSURE, z); 15862306a36Sopenharmony_ci input_report_key(ts->idev, BTN_TOUCH, 1); 15962306a36Sopenharmony_ci input_sync(ts->idev); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* flush the FIFO after we have read out our values. */ 16262306a36Sopenharmony_ci __stmpe_reset_fifo(ts->stmpe); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* reenable the tsc */ 16562306a36Sopenharmony_ci stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, 16662306a36Sopenharmony_ci STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* start polling for touch_det to detect release */ 16962306a36Sopenharmony_ci schedule_delayed_work(&ts->work, msecs_to_jiffies(50)); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return IRQ_HANDLED; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int stmpe_init_hw(struct stmpe_touch *ts) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci int ret; 17762306a36Sopenharmony_ci u8 tsc_cfg, tsc_cfg_mask; 17862306a36Sopenharmony_ci struct stmpe *stmpe = ts->stmpe; 17962306a36Sopenharmony_ci struct device *dev = ts->dev; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC); 18262306a36Sopenharmony_ci if (ret) { 18362306a36Sopenharmony_ci dev_err(dev, "Could not enable clock for ADC and TS\n"); 18462306a36Sopenharmony_ci return ret; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci ret = stmpe811_adc_common_init(stmpe); 18862306a36Sopenharmony_ci if (ret) { 18962306a36Sopenharmony_ci stmpe_disable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC); 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) | 19462306a36Sopenharmony_ci STMPE_DET_DELAY(ts->touch_det_delay) | 19562306a36Sopenharmony_ci STMPE_SETTLING(ts->settling); 19662306a36Sopenharmony_ci tsc_cfg_mask = STMPE_AVE_CTRL(0xff) | STMPE_DET_DELAY(0xff) | 19762306a36Sopenharmony_ci STMPE_SETTLING(0xff); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg); 20062306a36Sopenharmony_ci if (ret) { 20162306a36Sopenharmony_ci dev_err(dev, "Could not config touch\n"); 20262306a36Sopenharmony_ci return ret; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, 20662306a36Sopenharmony_ci STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z)); 20762306a36Sopenharmony_ci if (ret) { 20862306a36Sopenharmony_ci dev_err(dev, "Could not config touch\n"); 20962306a36Sopenharmony_ci return ret; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, 21362306a36Sopenharmony_ci STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive)); 21462306a36Sopenharmony_ci if (ret) { 21562306a36Sopenharmony_ci dev_err(dev, "Could not config touch\n"); 21662306a36Sopenharmony_ci return ret; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /* set FIFO to 1 for single point reading */ 22062306a36Sopenharmony_ci ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1); 22162306a36Sopenharmony_ci if (ret) { 22262306a36Sopenharmony_ci dev_err(dev, "Could not set FIFO\n"); 22362306a36Sopenharmony_ci return ret; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, 22762306a36Sopenharmony_ci STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ)); 22862306a36Sopenharmony_ci if (ret) { 22962306a36Sopenharmony_ci dev_err(dev, "Could not set mode\n"); 23062306a36Sopenharmony_ci return ret; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci return 0; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic int stmpe_ts_open(struct input_dev *dev) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct stmpe_touch *ts = input_get_drvdata(dev); 23962306a36Sopenharmony_ci int ret = 0; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci ret = __stmpe_reset_fifo(ts->stmpe); 24262306a36Sopenharmony_ci if (ret) 24362306a36Sopenharmony_ci return ret; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, 24662306a36Sopenharmony_ci STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void stmpe_ts_close(struct input_dev *dev) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct stmpe_touch *ts = input_get_drvdata(dev); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci cancel_delayed_work_sync(&ts->work); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, 25662306a36Sopenharmony_ci STMPE_TSC_CTRL_TSC_EN, 0); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void stmpe_ts_get_platform_info(struct platform_device *pdev, 26062306a36Sopenharmony_ci struct stmpe_touch *ts) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 26362306a36Sopenharmony_ci u32 val; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (np) { 26662306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,sample-time", &val)) 26762306a36Sopenharmony_ci ts->stmpe->sample_time = val; 26862306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,mod-12b", &val)) 26962306a36Sopenharmony_ci ts->stmpe->mod_12b = val; 27062306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,ref-sel", &val)) 27162306a36Sopenharmony_ci ts->stmpe->ref_sel = val; 27262306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,adc-freq", &val)) 27362306a36Sopenharmony_ci ts->stmpe->adc_freq = val; 27462306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,ave-ctrl", &val)) 27562306a36Sopenharmony_ci ts->ave_ctrl = val; 27662306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,touch-det-delay", &val)) 27762306a36Sopenharmony_ci ts->touch_det_delay = val; 27862306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,settling", &val)) 27962306a36Sopenharmony_ci ts->settling = val; 28062306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,fraction-z", &val)) 28162306a36Sopenharmony_ci ts->fraction_z = val; 28262306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,i-drive", &val)) 28362306a36Sopenharmony_ci ts->i_drive = val; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic int stmpe_input_probe(struct platform_device *pdev) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); 29062306a36Sopenharmony_ci struct stmpe_touch *ts; 29162306a36Sopenharmony_ci struct input_dev *idev; 29262306a36Sopenharmony_ci int error; 29362306a36Sopenharmony_ci int ts_irq; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); 29662306a36Sopenharmony_ci if (ts_irq < 0) 29762306a36Sopenharmony_ci return ts_irq; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL); 30062306a36Sopenharmony_ci if (!ts) 30162306a36Sopenharmony_ci return -ENOMEM; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci idev = devm_input_allocate_device(&pdev->dev); 30462306a36Sopenharmony_ci if (!idev) 30562306a36Sopenharmony_ci return -ENOMEM; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci platform_set_drvdata(pdev, ts); 30862306a36Sopenharmony_ci ts->stmpe = stmpe; 30962306a36Sopenharmony_ci ts->idev = idev; 31062306a36Sopenharmony_ci ts->dev = &pdev->dev; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci stmpe_ts_get_platform_info(pdev, ts); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci INIT_DELAYED_WORK(&ts->work, stmpe_work); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci error = devm_request_threaded_irq(&pdev->dev, ts_irq, 31762306a36Sopenharmony_ci NULL, stmpe_ts_handler, 31862306a36Sopenharmony_ci IRQF_ONESHOT, STMPE_TS_NAME, ts); 31962306a36Sopenharmony_ci if (error) { 32062306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); 32162306a36Sopenharmony_ci return error; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci error = stmpe_init_hw(ts); 32562306a36Sopenharmony_ci if (error) 32662306a36Sopenharmony_ci return error; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci idev->name = STMPE_TS_NAME; 32962306a36Sopenharmony_ci idev->phys = STMPE_TS_NAME"/input0"; 33062306a36Sopenharmony_ci idev->id.bustype = BUS_I2C; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci idev->open = stmpe_ts_open; 33362306a36Sopenharmony_ci idev->close = stmpe_ts_close; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci input_set_drvdata(idev, ts); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci input_set_capability(idev, EV_KEY, BTN_TOUCH); 33862306a36Sopenharmony_ci input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0); 33962306a36Sopenharmony_ci input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); 34062306a36Sopenharmony_ci input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci touchscreen_parse_properties(idev, false, &ts->prop); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci error = input_register_device(idev); 34562306a36Sopenharmony_ci if (error) { 34662306a36Sopenharmony_ci dev_err(&pdev->dev, "Could not register input device\n"); 34762306a36Sopenharmony_ci return error; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return 0; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic int stmpe_ts_remove(struct platform_device *pdev) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct stmpe_touch *ts = platform_get_drvdata(pdev); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic struct platform_driver stmpe_ts_driver = { 36362306a36Sopenharmony_ci .driver = { 36462306a36Sopenharmony_ci .name = STMPE_TS_NAME, 36562306a36Sopenharmony_ci }, 36662306a36Sopenharmony_ci .probe = stmpe_input_probe, 36762306a36Sopenharmony_ci .remove = stmpe_ts_remove, 36862306a36Sopenharmony_ci}; 36962306a36Sopenharmony_cimodule_platform_driver(stmpe_ts_driver); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic const struct of_device_id stmpe_ts_ids[] = { 37262306a36Sopenharmony_ci { .compatible = "st,stmpe-ts", }, 37362306a36Sopenharmony_ci { }, 37462306a36Sopenharmony_ci}; 37562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stmpe_ts_ids); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciMODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); 37862306a36Sopenharmony_ciMODULE_DESCRIPTION("STMPEXXX touchscreen driver"); 37962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 380