1 /* 2 * Touchscreen driver for the tps6507x chip. 3 * 4 * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) 5 * 6 * Credits: 7 * 8 * Using code from tsc2007, MtekVision Co., Ltd. 9 * 10 * For licencing details see kernel-base/COPYING 11 * 12 * TPS65070, TPS65073, TPS650731, and TPS650732 support 13 * 10 bit touch screen interface. 14 */ 15 16 #include <linux/module.h> 17 #include <linux/workqueue.h> 18 #include <linux/slab.h> 19 #include <linux/input.h> 20 #include <linux/platform_device.h> 21 #include <linux/mfd/tps6507x.h> 22 #include <linux/input/tps6507x-ts.h> 23 #include <linux/delay.h> 24 25 #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */ 26 #define TPS_DEFAULT_MIN_PRESSURE 0x30 27 #define MAX_10BIT ((1 << 10) - 1) 28 29 #define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \ 30 TPS6507X_ADCONFIG_START_CONVERSION | \ 31 TPS6507X_ADCONFIG_INPUT_REAL_TSC) 32 #define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC) 33 34 struct ts_event { 35 u16 x; 36 u16 y; 37 u16 pressure; 38 }; 39 40 struct tps6507x_ts { 41 struct device *dev; 42 struct input_dev *input; 43 struct tps6507x_dev *mfd; 44 char phys[32]; 45 struct ts_event tc; 46 u16 min_pressure; 47 bool pendown; 48 }; 49 50 static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) 51 { 52 return tsc->mfd->read_dev(tsc->mfd, reg, 1, data); 53 } 54 55 static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data) 56 { 57 return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data); 58 } 59 60 static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc, 61 u8 tsc_mode, u16 *value) 62 { 63 s32 ret; 64 u8 adc_status; 65 u8 result; 66 67 /* Route input signal to A/D converter */ 68 69 ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode); 70 if (ret) { 71 dev_err(tsc->dev, "TSC mode read failed\n"); 72 goto err; 73 } 74 75 /* Start A/D conversion */ 76 77 ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, 78 TPS6507X_ADCONFIG_CONVERT_TS); 79 if (ret) { 80 dev_err(tsc->dev, "ADC config write failed\n"); 81 return ret; 82 } 83 84 do { 85 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG, 86 &adc_status); 87 if (ret) { 88 dev_err(tsc->dev, "ADC config read failed\n"); 89 goto err; 90 } 91 } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION); 92 93 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result); 94 if (ret) { 95 dev_err(tsc->dev, "ADC result 2 read failed\n"); 96 goto err; 97 } 98 99 *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8; 100 101 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result); 102 if (ret) { 103 dev_err(tsc->dev, "ADC result 1 read failed\n"); 104 goto err; 105 } 106 107 *value |= result; 108 109 dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value); 110 111 err: 112 return ret; 113 } 114 115 /* Need to call tps6507x_adc_standby() after using A/D converter for the 116 * touch screen interrupt to work properly. 117 */ 118 119 static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) 120 { 121 s32 ret; 122 u8 val; 123 124 ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, 125 TPS6507X_ADCONFIG_INPUT_TSC); 126 if (ret) 127 return ret; 128 129 ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, 130 TPS6507X_TSCMODE_STANDBY); 131 if (ret) 132 return ret; 133 134 ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); 135 if (ret) 136 return ret; 137 138 while (val & TPS6507X_REG_TSC_INT) { 139 mdelay(10); 140 ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); 141 if (ret) 142 return ret; 143 } 144 145 return ret; 146 } 147 148 static void tps6507x_ts_poll(struct input_dev *input_dev) 149 { 150 struct tps6507x_ts *tsc = input_get_drvdata(input_dev); 151 bool pendown; 152 s32 ret; 153 154 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE, 155 &tsc->tc.pressure); 156 if (ret) 157 goto done; 158 159 pendown = tsc->tc.pressure > tsc->min_pressure; 160 161 if (unlikely(!pendown && tsc->pendown)) { 162 dev_dbg(tsc->dev, "UP\n"); 163 input_report_key(input_dev, BTN_TOUCH, 0); 164 input_report_abs(input_dev, ABS_PRESSURE, 0); 165 input_sync(input_dev); 166 tsc->pendown = false; 167 } 168 169 if (pendown) { 170 171 if (!tsc->pendown) { 172 dev_dbg(tsc->dev, "DOWN\n"); 173 input_report_key(input_dev, BTN_TOUCH, 1); 174 } else 175 dev_dbg(tsc->dev, "still down\n"); 176 177 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION, 178 &tsc->tc.x); 179 if (ret) 180 goto done; 181 182 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION, 183 &tsc->tc.y); 184 if (ret) 185 goto done; 186 187 input_report_abs(input_dev, ABS_X, tsc->tc.x); 188 input_report_abs(input_dev, ABS_Y, tsc->tc.y); 189 input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure); 190 input_sync(input_dev); 191 tsc->pendown = true; 192 } 193 194 done: 195 tps6507x_adc_standby(tsc); 196 } 197 198 static int tps6507x_ts_probe(struct platform_device *pdev) 199 { 200 struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); 201 const struct tps6507x_board *tps_board; 202 const struct touchscreen_init_data *init_data; 203 struct tps6507x_ts *tsc; 204 struct input_dev *input_dev; 205 int error; 206 207 /* 208 * tps_board points to pmic related constants 209 * coming from the board-evm file. 210 */ 211 tps_board = dev_get_platdata(tps6507x_dev->dev); 212 if (!tps_board) { 213 dev_err(tps6507x_dev->dev, 214 "Could not find tps6507x platform data\n"); 215 return -ENODEV; 216 } 217 218 /* 219 * init_data points to array of regulator_init structures 220 * coming from the board-evm file. 221 */ 222 init_data = tps_board->tps6507x_ts_init_data; 223 224 tsc = devm_kzalloc(&pdev->dev, sizeof(struct tps6507x_ts), GFP_KERNEL); 225 if (!tsc) { 226 dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); 227 return -ENOMEM; 228 } 229 230 tsc->mfd = tps6507x_dev; 231 tsc->dev = tps6507x_dev->dev; 232 tsc->min_pressure = init_data ? 233 init_data->min_pressure : TPS_DEFAULT_MIN_PRESSURE; 234 235 snprintf(tsc->phys, sizeof(tsc->phys), 236 "%s/input0", dev_name(tsc->dev)); 237 238 input_dev = devm_input_allocate_device(&pdev->dev); 239 if (!input_dev) { 240 dev_err(tsc->dev, "Failed to allocate polled input device.\n"); 241 return -ENOMEM; 242 } 243 244 tsc->input = input_dev; 245 input_set_drvdata(input_dev, tsc); 246 247 input_set_capability(input_dev, EV_KEY, BTN_TOUCH); 248 input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0); 249 input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0); 250 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); 251 252 input_dev->name = "TPS6507x Touchscreen"; 253 input_dev->phys = tsc->phys; 254 input_dev->dev.parent = tsc->dev; 255 input_dev->id.bustype = BUS_I2C; 256 if (init_data) { 257 input_dev->id.vendor = init_data->vendor; 258 input_dev->id.product = init_data->product; 259 input_dev->id.version = init_data->version; 260 } 261 262 error = tps6507x_adc_standby(tsc); 263 if (error) 264 return error; 265 266 error = input_setup_polling(input_dev, tps6507x_ts_poll); 267 if (error) 268 return error; 269 270 input_set_poll_interval(input_dev, 271 init_data ? init_data->poll_period : 272 TSC_DEFAULT_POLL_PERIOD); 273 274 error = input_register_device(input_dev); 275 if (error) 276 return error; 277 278 return 0; 279 } 280 281 static struct platform_driver tps6507x_ts_driver = { 282 .driver = { 283 .name = "tps6507x-ts", 284 }, 285 .probe = tps6507x_ts_probe, 286 }; 287 module_platform_driver(tps6507x_ts_driver); 288 289 MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); 290 MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); 291 MODULE_LICENSE("GPL v2"); 292 MODULE_ALIAS("platform:tps6507x-ts"); 293