| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Synaptics touchpad with I2C interface | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2009 Compulab, Ltd. | 
 | 5 |  * Mike Rapoport <mike@compulab.co.il> | 
 | 6 |  * Igor Grinberg <grinberg@compulab.co.il> | 
 | 7 |  * | 
 | 8 |  * This file is subject to the terms and conditions of the GNU General Public | 
 | 9 |  * License.  See the file COPYING in the main directory of this archive for | 
 | 10 |  * more details. | 
 | 11 |  */ | 
 | 12 |  | 
 | 13 | #include <linux/module.h> | 
 | 14 | #include <linux/i2c.h> | 
 | 15 | #include <linux/irq.h> | 
 | 16 | #include <linux/interrupt.h> | 
 | 17 | #include <linux/input.h> | 
 | 18 | #include <linux/delay.h> | 
 | 19 | #include <linux/workqueue.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 20 | #include <linux/slab.h> | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 21 |  | 
 | 22 | #define DRIVER_NAME		"synaptics_i2c" | 
 | 23 | /* maximum product id is 15 characters */ | 
 | 24 | #define PRODUCT_ID_LENGTH	15 | 
 | 25 | #define REGISTER_LENGTH		8 | 
 | 26 |  | 
 | 27 | /* | 
 | 28 |  * after soft reset, we should wait for 1 ms | 
 | 29 |  * before the device becomes operational | 
 | 30 |  */ | 
 | 31 | #define SOFT_RESET_DELAY_MS	3 | 
 | 32 | /* and after hard reset, we should wait for max 500ms */ | 
 | 33 | #define HARD_RESET_DELAY_MS	500 | 
 | 34 |  | 
 | 35 | /* Registers by SMBus address */ | 
 | 36 | #define PAGE_SEL_REG		0xff | 
 | 37 | #define DEVICE_STATUS_REG	0x09 | 
 | 38 |  | 
 | 39 | /* Registers by RMI address */ | 
 | 40 | #define DEV_CONTROL_REG		0x0000 | 
 | 41 | #define INTERRUPT_EN_REG	0x0001 | 
 | 42 | #define ERR_STAT_REG		0x0002 | 
 | 43 | #define INT_REQ_STAT_REG	0x0003 | 
 | 44 | #define DEV_COMMAND_REG		0x0004 | 
 | 45 |  | 
 | 46 | #define RMI_PROT_VER_REG	0x0200 | 
 | 47 | #define MANUFACT_ID_REG		0x0201 | 
 | 48 | #define PHYS_INT_VER_REG	0x0202 | 
 | 49 | #define PROD_PROPERTY_REG	0x0203 | 
 | 50 | #define INFO_QUERY_REG0		0x0204 | 
 | 51 | #define INFO_QUERY_REG1		(INFO_QUERY_REG0 + 1) | 
 | 52 | #define INFO_QUERY_REG2		(INFO_QUERY_REG0 + 2) | 
 | 53 | #define INFO_QUERY_REG3		(INFO_QUERY_REG0 + 3) | 
 | 54 |  | 
 | 55 | #define PRODUCT_ID_REG0		0x0210 | 
 | 56 | #define PRODUCT_ID_REG1		(PRODUCT_ID_REG0 + 1) | 
 | 57 | #define PRODUCT_ID_REG2		(PRODUCT_ID_REG0 + 2) | 
 | 58 | #define PRODUCT_ID_REG3		(PRODUCT_ID_REG0 + 3) | 
 | 59 | #define PRODUCT_ID_REG4		(PRODUCT_ID_REG0 + 4) | 
 | 60 | #define PRODUCT_ID_REG5		(PRODUCT_ID_REG0 + 5) | 
 | 61 | #define PRODUCT_ID_REG6		(PRODUCT_ID_REG0 + 6) | 
 | 62 | #define PRODUCT_ID_REG7		(PRODUCT_ID_REG0 + 7) | 
 | 63 | #define PRODUCT_ID_REG8		(PRODUCT_ID_REG0 + 8) | 
 | 64 | #define PRODUCT_ID_REG9		(PRODUCT_ID_REG0 + 9) | 
 | 65 | #define PRODUCT_ID_REG10	(PRODUCT_ID_REG0 + 10) | 
 | 66 | #define PRODUCT_ID_REG11	(PRODUCT_ID_REG0 + 11) | 
 | 67 | #define PRODUCT_ID_REG12	(PRODUCT_ID_REG0 + 12) | 
 | 68 | #define PRODUCT_ID_REG13	(PRODUCT_ID_REG0 + 13) | 
 | 69 | #define PRODUCT_ID_REG14	(PRODUCT_ID_REG0 + 14) | 
 | 70 | #define PRODUCT_ID_REG15	(PRODUCT_ID_REG0 + 15) | 
 | 71 |  | 
 | 72 | #define DATA_REG0		0x0400 | 
 | 73 | #define ABS_PRESSURE_REG	0x0401 | 
 | 74 | #define ABS_MSB_X_REG		0x0402 | 
 | 75 | #define ABS_LSB_X_REG		(ABS_MSB_X_REG + 1) | 
 | 76 | #define ABS_MSB_Y_REG		0x0404 | 
 | 77 | #define ABS_LSB_Y_REG		(ABS_MSB_Y_REG + 1) | 
 | 78 | #define REL_X_REG		0x0406 | 
 | 79 | #define REL_Y_REG		0x0407 | 
 | 80 |  | 
 | 81 | #define DEV_QUERY_REG0		0x1000 | 
 | 82 | #define DEV_QUERY_REG1		(DEV_QUERY_REG0 + 1) | 
 | 83 | #define DEV_QUERY_REG2		(DEV_QUERY_REG0 + 2) | 
 | 84 | #define DEV_QUERY_REG3		(DEV_QUERY_REG0 + 3) | 
 | 85 | #define DEV_QUERY_REG4		(DEV_QUERY_REG0 + 4) | 
 | 86 | #define DEV_QUERY_REG5		(DEV_QUERY_REG0 + 5) | 
 | 87 | #define DEV_QUERY_REG6		(DEV_QUERY_REG0 + 6) | 
 | 88 | #define DEV_QUERY_REG7		(DEV_QUERY_REG0 + 7) | 
 | 89 | #define DEV_QUERY_REG8		(DEV_QUERY_REG0 + 8) | 
 | 90 |  | 
 | 91 | #define GENERAL_2D_CONTROL_REG	0x1041 | 
 | 92 | #define SENSOR_SENSITIVITY_REG	0x1044 | 
 | 93 | #define SENS_MAX_POS_MSB_REG	0x1046 | 
 | 94 | #define SENS_MAX_POS_LSB_REG	(SENS_MAX_POS_UPPER_REG + 1) | 
 | 95 |  | 
 | 96 | /* Register bits */ | 
 | 97 | /* Device Control Register Bits */ | 
 | 98 | #define REPORT_RATE_1ST_BIT	6 | 
 | 99 |  | 
 | 100 | /* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ | 
 | 101 | #define F10_ABS_INT_ENA		0 | 
 | 102 | #define F10_REL_INT_ENA		1 | 
 | 103 | #define F20_INT_ENA		2 | 
 | 104 |  | 
 | 105 | /* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */ | 
 | 106 | #define F10_ABS_INT_REQ		0 | 
 | 107 | #define F10_REL_INT_REQ		1 | 
 | 108 | #define F20_INT_REQ		2 | 
 | 109 | /* Device Status Register Bits (DEVICE_STATUS_REG) */ | 
 | 110 | #define STAT_CONFIGURED		6 | 
 | 111 | #define STAT_ERROR		7 | 
 | 112 |  | 
 | 113 | /* Device Command Register Bits (DEV_COMMAND_REG) */ | 
 | 114 | #define RESET_COMMAND		0x01 | 
 | 115 | #define REZERO_COMMAND		0x02 | 
 | 116 |  | 
 | 117 | /* Data Register 0 Bits (DATA_REG0) */ | 
 | 118 | #define GESTURE			3 | 
 | 119 |  | 
 | 120 | /* Device Query Registers Bits */ | 
 | 121 | /* DEV_QUERY_REG3 */ | 
 | 122 | #define HAS_PALM_DETECT		1 | 
 | 123 | #define HAS_MULTI_FING		2 | 
 | 124 | #define HAS_SCROLLER		4 | 
 | 125 | #define HAS_2D_SCROLL		5 | 
 | 126 |  | 
 | 127 | /* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ | 
 | 128 | #define NO_DECELERATION		1 | 
 | 129 | #define REDUCE_REPORTING	3 | 
 | 130 | #define NO_FILTER		5 | 
 | 131 |  | 
 | 132 | /* Function Masks */ | 
 | 133 | /* Device Control Register Masks (DEV_CONTROL_REG) */ | 
 | 134 | #define REPORT_RATE_MSK		0xc0 | 
 | 135 | #define SLEEP_MODE_MSK		0x07 | 
 | 136 |  | 
 | 137 | /* Device Sleep Modes */ | 
 | 138 | #define FULL_AWAKE		0x0 | 
 | 139 | #define NORMAL_OP		0x1 | 
 | 140 | #define LOW_PWR_OP		0x2 | 
 | 141 | #define VERY_LOW_PWR_OP		0x3 | 
 | 142 | #define SENS_SLEEP		0x4 | 
 | 143 | #define SLEEP_MOD		0x5 | 
 | 144 | #define DEEP_SLEEP		0x6 | 
 | 145 | #define HIBERNATE		0x7 | 
 | 146 |  | 
 | 147 | /* Interrupt Register Mask */ | 
 | 148 | /* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ | 
 | 149 | #define INT_ENA_REQ_MSK		0x07 | 
 | 150 | #define INT_ENA_ABS_MSK		0x01 | 
 | 151 | #define INT_ENA_REL_MSK		0x02 | 
 | 152 | #define INT_ENA_F20_MSK		0x04 | 
 | 153 |  | 
 | 154 | /* Device Status Register Masks (DEVICE_STATUS_REG) */ | 
 | 155 | #define CONFIGURED_MSK		0x40 | 
 | 156 | #define ERROR_MSK		0x80 | 
 | 157 |  | 
 | 158 | /* Data Register 0 Masks */ | 
 | 159 | #define FINGER_WIDTH_MSK	0xf0 | 
 | 160 | #define GESTURE_MSK		0x08 | 
 | 161 | #define SENSOR_STATUS_MSK	0x07 | 
 | 162 |  | 
 | 163 | /* | 
 | 164 |  * MSB Position Register Masks | 
 | 165 |  * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | | 
 | 166 |  * DEV_QUERY_REG3 | DEV_QUERY_REG5 | 
 | 167 |  */ | 
 | 168 | #define MSB_POSITION_MSK	0x1f | 
 | 169 |  | 
 | 170 | /* Device Query Registers Masks */ | 
 | 171 |  | 
 | 172 | /* DEV_QUERY_REG2 */ | 
 | 173 | #define NUM_EXTRA_POS_MSK	0x07 | 
 | 174 |  | 
 | 175 | /* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ | 
 | 176 | #define THREAD_IRQ_SLEEP_SECS	2 | 
 | 177 | #define THREAD_IRQ_SLEEP_MSECS	(THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) | 
 | 178 |  | 
 | 179 | /* | 
 | 180 |  * When in Polling mode and no data received for NO_DATA_THRES msecs | 
 | 181 |  * reduce the polling rate to NO_DATA_SLEEP_MSECS | 
 | 182 |  */ | 
 | 183 | #define NO_DATA_THRES		(MSEC_PER_SEC) | 
 | 184 | #define NO_DATA_SLEEP_MSECS	(MSEC_PER_SEC / 4) | 
 | 185 |  | 
 | 186 | /* Control touchpad's No Deceleration option */ | 
 | 187 | static int no_decel = 1; | 
 | 188 | module_param(no_decel, bool, 0644); | 
 | 189 | MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); | 
 | 190 |  | 
 | 191 | /* Control touchpad's Reduced Reporting option */ | 
 | 192 | static int reduce_report; | 
 | 193 | module_param(reduce_report, bool, 0644); | 
 | 194 | MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); | 
 | 195 |  | 
 | 196 | /* Control touchpad's No Filter option */ | 
 | 197 | static int no_filter; | 
 | 198 | module_param(no_filter, bool, 0644); | 
 | 199 | MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | 
 | 200 |  | 
 | 201 | /* | 
 | 202 |  * touchpad Attention line is Active Low and Open Drain, | 
 | 203 |  * therefore should be connected to pulled up line | 
 | 204 |  * and the irq configuration should be set to Falling Edge Trigger | 
 | 205 |  */ | 
 | 206 | /* Control IRQ / Polling option */ | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 207 | static bool polling_req; | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 208 | module_param(polling_req, bool, 0444); | 
 | 209 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); | 
 | 210 |  | 
 | 211 | /* Control Polling Rate */ | 
 | 212 | static int scan_rate = 80; | 
 | 213 | module_param(scan_rate, int, 0644); | 
 | 214 | MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80"); | 
 | 215 |  | 
 | 216 | /* The main device structure */ | 
 | 217 | struct synaptics_i2c { | 
 | 218 | 	struct i2c_client	*client; | 
 | 219 | 	struct input_dev	*input; | 
 | 220 | 	struct delayed_work	dwork; | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 221 | 	spinlock_t		lock; | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 222 | 	int			no_data_count; | 
 | 223 | 	int			no_decel_param; | 
 | 224 | 	int			reduce_report_param; | 
 | 225 | 	int			no_filter_param; | 
 | 226 | 	int			scan_rate_param; | 
 | 227 | 	int			scan_ms; | 
 | 228 | }; | 
 | 229 |  | 
 | 230 | static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate) | 
 | 231 | { | 
 | 232 | 	touch->scan_ms = MSEC_PER_SEC / scan_rate; | 
 | 233 | 	touch->scan_rate_param = scan_rate; | 
 | 234 | } | 
 | 235 |  | 
 | 236 | /* | 
 | 237 |  * Driver's initial design makes no race condition possible on i2c bus, | 
 | 238 |  * so there is no need in any locking. | 
 | 239 |  * Keep it in mind, while playing with the code. | 
 | 240 |  */ | 
 | 241 | static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) | 
 | 242 | { | 
 | 243 | 	int ret; | 
 | 244 |  | 
 | 245 | 	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | 
 | 246 | 	if (ret == 0) | 
 | 247 | 		ret = i2c_smbus_read_byte_data(client, reg & 0xff); | 
 | 248 |  | 
 | 249 | 	return ret; | 
 | 250 | } | 
 | 251 |  | 
 | 252 | static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) | 
 | 253 | { | 
 | 254 | 	int ret; | 
 | 255 |  | 
 | 256 | 	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | 
 | 257 | 	if (ret == 0) | 
 | 258 | 		ret = i2c_smbus_write_byte_data(client, reg & 0xff, val); | 
 | 259 |  | 
 | 260 | 	return ret; | 
 | 261 | } | 
 | 262 |  | 
 | 263 | static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) | 
 | 264 | { | 
 | 265 | 	int ret; | 
 | 266 |  | 
 | 267 | 	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | 
 | 268 | 	if (ret == 0) | 
 | 269 | 		ret = i2c_smbus_read_word_data(client, reg & 0xff); | 
 | 270 |  | 
 | 271 | 	return ret; | 
 | 272 | } | 
 | 273 |  | 
 | 274 | static int synaptics_i2c_config(struct i2c_client *client) | 
 | 275 | { | 
 | 276 | 	int ret, control; | 
 | 277 | 	u8 int_en; | 
 | 278 |  | 
 | 279 | 	/* set Report Rate to Device Highest (>=80) and Sleep to normal */ | 
 | 280 | 	ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); | 
 | 281 | 	if (ret) | 
 | 282 | 		return ret; | 
 | 283 |  | 
 | 284 | 	/* set Interrupt Disable to Func20 / Enable to Func10) */ | 
 | 285 | 	int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; | 
 | 286 | 	ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); | 
 | 287 | 	if (ret) | 
 | 288 | 		return ret; | 
 | 289 |  | 
 | 290 | 	control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); | 
 | 291 | 	/* No Deceleration */ | 
 | 292 | 	control |= no_decel ? 1 << NO_DECELERATION : 0; | 
 | 293 | 	/* Reduced Reporting */ | 
 | 294 | 	control |= reduce_report ? 1 << REDUCE_REPORTING : 0; | 
 | 295 | 	/* No Filter */ | 
 | 296 | 	control |= no_filter ? 1 << NO_FILTER : 0; | 
 | 297 | 	ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); | 
 | 298 | 	if (ret) | 
 | 299 | 		return ret; | 
 | 300 |  | 
 | 301 | 	return 0; | 
 | 302 | } | 
 | 303 |  | 
 | 304 | static int synaptics_i2c_reset_config(struct i2c_client *client) | 
 | 305 | { | 
 | 306 | 	int ret; | 
 | 307 |  | 
 | 308 | 	/* Reset the Touchpad */ | 
 | 309 | 	ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); | 
 | 310 | 	if (ret) { | 
 | 311 | 		dev_err(&client->dev, "Unable to reset device\n"); | 
 | 312 | 	} else { | 
 | 313 | 		msleep(SOFT_RESET_DELAY_MS); | 
 | 314 | 		ret = synaptics_i2c_config(client); | 
 | 315 | 		if (ret) | 
 | 316 | 			dev_err(&client->dev, "Unable to config device\n"); | 
 | 317 | 	} | 
 | 318 |  | 
 | 319 | 	return ret; | 
 | 320 | } | 
 | 321 |  | 
 | 322 | static int synaptics_i2c_check_error(struct i2c_client *client) | 
 | 323 | { | 
 | 324 | 	int status, ret = 0; | 
 | 325 |  | 
 | 326 | 	status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & | 
 | 327 | 		(CONFIGURED_MSK | ERROR_MSK); | 
 | 328 |  | 
 | 329 | 	if (status != CONFIGURED_MSK) | 
 | 330 | 		ret = synaptics_i2c_reset_config(client); | 
 | 331 |  | 
 | 332 | 	return ret; | 
 | 333 | } | 
 | 334 |  | 
 | 335 | static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) | 
 | 336 | { | 
 | 337 | 	struct input_dev *input = touch->input; | 
 | 338 | 	int xy_delta, gesture; | 
 | 339 | 	s32 data; | 
 | 340 | 	s8 x_delta, y_delta; | 
 | 341 |  | 
 | 342 | 	/* Deal with spontanious resets and errors */ | 
 | 343 | 	if (synaptics_i2c_check_error(touch->client)) | 
 | 344 | 		return 0; | 
 | 345 |  | 
 | 346 | 	/* Get Gesture Bit */ | 
 | 347 | 	data = synaptics_i2c_reg_get(touch->client, DATA_REG0); | 
 | 348 | 	gesture = (data >> GESTURE) & 0x1; | 
 | 349 |  | 
 | 350 | 	/* | 
 | 351 | 	 * Get Relative axes. we have to get them in one shot, | 
 | 352 | 	 * so we get 2 bytes starting from REL_X_REG. | 
 | 353 | 	 */ | 
 | 354 | 	xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; | 
 | 355 |  | 
 | 356 | 	/* Separate X from Y */ | 
 | 357 | 	x_delta = xy_delta & 0xff; | 
 | 358 | 	y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff; | 
 | 359 |  | 
 | 360 | 	/* Report the button event */ | 
 | 361 | 	input_report_key(input, BTN_LEFT, gesture); | 
 | 362 |  | 
 | 363 | 	/* Report the deltas */ | 
 | 364 | 	input_report_rel(input, REL_X, x_delta); | 
 | 365 | 	input_report_rel(input, REL_Y, -y_delta); | 
 | 366 | 	input_sync(input); | 
 | 367 |  | 
 | 368 | 	return xy_delta || gesture; | 
 | 369 | } | 
 | 370 |  | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 371 | static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, | 
 | 372 | 					  unsigned long delay) | 
 | 373 | { | 
 | 374 | 	unsigned long flags; | 
 | 375 |  | 
 | 376 | 	spin_lock_irqsave(&touch->lock, flags); | 
 | 377 |  | 
 | 378 | 	/* | 
 | 379 | 	 * If work is already scheduled then subsequent schedules will not | 
 | 380 | 	 * change the scheduled time that's why we have to cancel it first. | 
 | 381 | 	 */ | 
 | 382 | 	__cancel_delayed_work(&touch->dwork); | 
 | 383 | 	schedule_delayed_work(&touch->dwork, delay); | 
 | 384 |  | 
 | 385 | 	spin_unlock_irqrestore(&touch->lock, flags); | 
 | 386 | } | 
 | 387 |  | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 388 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | 
 | 389 | { | 
 | 390 | 	struct synaptics_i2c *touch = dev_id; | 
 | 391 |  | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 392 | 	synaptics_i2c_reschedule_work(touch, 0); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 393 |  | 
 | 394 | 	return IRQ_HANDLED; | 
 | 395 | } | 
 | 396 |  | 
 | 397 | static void synaptics_i2c_check_params(struct synaptics_i2c *touch) | 
 | 398 | { | 
 | 399 | 	bool reset = false; | 
 | 400 |  | 
 | 401 | 	if (scan_rate != touch->scan_rate_param) | 
 | 402 | 		set_scan_rate(touch, scan_rate); | 
 | 403 |  | 
 | 404 | 	if (no_decel != touch->no_decel_param) { | 
 | 405 | 		touch->no_decel_param = no_decel; | 
 | 406 | 		reset = true; | 
 | 407 | 	} | 
 | 408 |  | 
 | 409 | 	if (no_filter != touch->no_filter_param) { | 
 | 410 | 		touch->no_filter_param = no_filter; | 
 | 411 | 		reset = true; | 
 | 412 | 	} | 
 | 413 |  | 
 | 414 | 	if (reduce_report != touch->reduce_report_param) { | 
 | 415 | 		touch->reduce_report_param = reduce_report; | 
 | 416 | 		reset = true; | 
 | 417 | 	} | 
 | 418 |  | 
 | 419 | 	if (reset) | 
 | 420 | 		synaptics_i2c_reset_config(touch->client); | 
 | 421 | } | 
 | 422 |  | 
 | 423 | /* Control the Device polling rate / Work Handler sleep time */ | 
| Dmitry Torokhov | f5ba350 | 2009-11-02 21:57:40 -0800 | [diff] [blame] | 424 | static unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, | 
 | 425 | 						bool have_data) | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 426 | { | 
 | 427 | 	unsigned long delay, nodata_count_thres; | 
 | 428 |  | 
 | 429 | 	if (polling_req) { | 
 | 430 | 		delay = touch->scan_ms; | 
 | 431 | 		if (have_data) { | 
 | 432 | 			touch->no_data_count = 0; | 
 | 433 | 		} else { | 
 | 434 | 			nodata_count_thres = NO_DATA_THRES / touch->scan_ms; | 
 | 435 | 			if (touch->no_data_count < nodata_count_thres) | 
 | 436 | 				touch->no_data_count++; | 
 | 437 | 			else | 
 | 438 | 				delay = NO_DATA_SLEEP_MSECS; | 
 | 439 | 		} | 
 | 440 | 		return msecs_to_jiffies(delay); | 
 | 441 | 	} else { | 
 | 442 | 		delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); | 
 | 443 | 		return round_jiffies_relative(delay); | 
 | 444 | 	} | 
 | 445 | } | 
 | 446 |  | 
 | 447 | /* Work Handler */ | 
 | 448 | static void synaptics_i2c_work_handler(struct work_struct *work) | 
 | 449 | { | 
 | 450 | 	bool have_data; | 
 | 451 | 	struct synaptics_i2c *touch = | 
 | 452 | 			container_of(work, struct synaptics_i2c, dwork.work); | 
 | 453 | 	unsigned long delay; | 
 | 454 |  | 
 | 455 | 	synaptics_i2c_check_params(touch); | 
 | 456 |  | 
 | 457 | 	have_data = synaptics_i2c_get_input(touch); | 
 | 458 | 	delay = synaptics_i2c_adjust_delay(touch, have_data); | 
 | 459 |  | 
 | 460 | 	/* | 
 | 461 | 	 * While interrupt driven, there is no real need to poll the device. | 
 | 462 | 	 * But touchpads are very sensitive, so there could be errors | 
 | 463 | 	 * related to physical environment and the attention line isn't | 
 | 464 | 	 * neccesarily asserted. In such case we can lose the touchpad. | 
 | 465 | 	 * We poll the device once in THREAD_IRQ_SLEEP_SECS and | 
 | 466 | 	 * if error is detected, we try to reset and reconfigure the touchpad. | 
 | 467 | 	 */ | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 468 | 	synaptics_i2c_reschedule_work(touch, delay); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 469 | } | 
 | 470 |  | 
 | 471 | static int synaptics_i2c_open(struct input_dev *input) | 
 | 472 | { | 
 | 473 | 	struct synaptics_i2c *touch = input_get_drvdata(input); | 
 | 474 | 	int ret; | 
 | 475 |  | 
 | 476 | 	ret = synaptics_i2c_reset_config(touch->client); | 
 | 477 | 	if (ret) | 
 | 478 | 		return ret; | 
 | 479 |  | 
 | 480 | 	if (polling_req) | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 481 | 		synaptics_i2c_reschedule_work(touch, | 
 | 482 | 				msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 483 |  | 
 | 484 | 	return 0; | 
 | 485 | } | 
 | 486 |  | 
 | 487 | static void synaptics_i2c_close(struct input_dev *input) | 
 | 488 | { | 
 | 489 | 	struct synaptics_i2c *touch = input_get_drvdata(input); | 
 | 490 |  | 
 | 491 | 	if (!polling_req) | 
 | 492 | 		synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); | 
 | 493 |  | 
 | 494 | 	cancel_delayed_work_sync(&touch->dwork); | 
 | 495 |  | 
 | 496 | 	/* Save some power */ | 
 | 497 | 	synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | 
 | 498 | } | 
 | 499 |  | 
 | 500 | static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) | 
 | 501 | { | 
 | 502 | 	struct input_dev *input = touch->input; | 
 | 503 |  | 
 | 504 | 	input->name = touch->client->name; | 
 | 505 | 	input->phys = touch->client->adapter->name; | 
 | 506 | 	input->id.bustype = BUS_I2C; | 
 | 507 | 	input->id.version = synaptics_i2c_word_get(touch->client, | 
 | 508 | 						   INFO_QUERY_REG0); | 
 | 509 | 	input->dev.parent = &touch->client->dev; | 
 | 510 | 	input->open = synaptics_i2c_open; | 
 | 511 | 	input->close = synaptics_i2c_close; | 
 | 512 | 	input_set_drvdata(input, touch); | 
 | 513 |  | 
 | 514 | 	/* Register the device as mouse */ | 
 | 515 | 	__set_bit(EV_REL, input->evbit); | 
 | 516 | 	__set_bit(REL_X, input->relbit); | 
 | 517 | 	__set_bit(REL_Y, input->relbit); | 
 | 518 |  | 
 | 519 | 	/* Register device's buttons and keys */ | 
 | 520 | 	__set_bit(EV_KEY, input->evbit); | 
 | 521 | 	__set_bit(BTN_LEFT, input->keybit); | 
 | 522 | } | 
 | 523 |  | 
| Dmitry Torokhov | f5ba350 | 2009-11-02 21:57:40 -0800 | [diff] [blame] | 524 | static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 525 | { | 
 | 526 | 	struct synaptics_i2c *touch; | 
 | 527 |  | 
 | 528 | 	touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); | 
 | 529 | 	if (!touch) | 
 | 530 | 		return NULL; | 
 | 531 |  | 
 | 532 | 	touch->client = client; | 
 | 533 | 	touch->no_decel_param = no_decel; | 
 | 534 | 	touch->scan_rate_param = scan_rate; | 
 | 535 | 	set_scan_rate(touch, scan_rate); | 
 | 536 | 	INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 537 | 	spin_lock_init(&touch->lock); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 538 |  | 
 | 539 | 	return touch; | 
 | 540 | } | 
 | 541 |  | 
 | 542 | static int __devinit synaptics_i2c_probe(struct i2c_client *client, | 
 | 543 | 			       const struct i2c_device_id *dev_id) | 
 | 544 | { | 
 | 545 | 	int ret; | 
 | 546 | 	struct synaptics_i2c *touch; | 
 | 547 |  | 
 | 548 | 	touch = synaptics_i2c_touch_create(client); | 
 | 549 | 	if (!touch) | 
 | 550 | 		return -ENOMEM; | 
 | 551 |  | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 552 | 	ret = synaptics_i2c_reset_config(client); | 
 | 553 | 	if (ret) | 
 | 554 | 		goto err_mem_free; | 
 | 555 |  | 
 | 556 | 	if (client->irq < 1) | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 557 | 		polling_req = true; | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 558 |  | 
 | 559 | 	touch->input = input_allocate_device(); | 
 | 560 | 	if (!touch->input) { | 
 | 561 | 		ret = -ENOMEM; | 
 | 562 | 		goto err_mem_free; | 
 | 563 | 	} | 
 | 564 |  | 
 | 565 | 	synaptics_i2c_set_input_params(touch); | 
 | 566 |  | 
 | 567 | 	if (!polling_req) { | 
 | 568 | 		dev_dbg(&touch->client->dev, | 
 | 569 | 			 "Requesting IRQ: %d\n", touch->client->irq); | 
 | 570 |  | 
 | 571 | 		ret = request_irq(touch->client->irq, synaptics_i2c_irq, | 
 | 572 | 				  IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING, | 
 | 573 | 				  DRIVER_NAME, touch); | 
 | 574 | 		if (ret) { | 
 | 575 | 			dev_warn(&touch->client->dev, | 
 | 576 | 				  "IRQ request failed: %d, " | 
 | 577 | 				  "falling back to polling\n", ret); | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 578 | 			polling_req = true; | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 579 | 			synaptics_i2c_reg_set(touch->client, | 
 | 580 | 					      INTERRUPT_EN_REG, 0); | 
 | 581 | 		} | 
 | 582 | 	} | 
 | 583 |  | 
 | 584 | 	if (polling_req) | 
 | 585 | 		dev_dbg(&touch->client->dev, | 
 | 586 | 			 "Using polling at rate: %d times/sec\n", scan_rate); | 
 | 587 |  | 
 | 588 | 	/* Register the device in input subsystem */ | 
 | 589 | 	ret = input_register_device(touch->input); | 
 | 590 | 	if (ret) { | 
 | 591 | 		dev_err(&client->dev, | 
 | 592 | 			 "Input device register failed: %d\n", ret); | 
 | 593 | 		goto err_input_free; | 
 | 594 | 	} | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 595 |  | 
 | 596 | 	i2c_set_clientdata(client, touch); | 
 | 597 |  | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 598 | 	return 0; | 
 | 599 |  | 
 | 600 | err_input_free: | 
 | 601 | 	input_free_device(touch->input); | 
 | 602 | err_mem_free: | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 603 | 	kfree(touch); | 
 | 604 |  | 
 | 605 | 	return ret; | 
 | 606 | } | 
 | 607 |  | 
 | 608 | static int __devexit synaptics_i2c_remove(struct i2c_client *client) | 
 | 609 | { | 
 | 610 | 	struct synaptics_i2c *touch = i2c_get_clientdata(client); | 
 | 611 |  | 
 | 612 | 	if (!polling_req) | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 613 | 		free_irq(client->irq, touch); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 614 |  | 
 | 615 | 	input_unregister_device(touch->input); | 
 | 616 | 	i2c_set_clientdata(client, NULL); | 
 | 617 | 	kfree(touch); | 
 | 618 |  | 
 | 619 | 	return 0; | 
 | 620 | } | 
 | 621 |  | 
 | 622 | #ifdef CONFIG_PM | 
 | 623 | static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 
 | 624 | { | 
 | 625 | 	struct synaptics_i2c *touch = i2c_get_clientdata(client); | 
 | 626 |  | 
 | 627 | 	cancel_delayed_work_sync(&touch->dwork); | 
 | 628 |  | 
 | 629 | 	/* Save some power */ | 
 | 630 | 	synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | 
 | 631 |  | 
 | 632 | 	return 0; | 
 | 633 | } | 
 | 634 |  | 
 | 635 | static int synaptics_i2c_resume(struct i2c_client *client) | 
 | 636 | { | 
 | 637 | 	int ret; | 
 | 638 | 	struct synaptics_i2c *touch = i2c_get_clientdata(client); | 
 | 639 |  | 
 | 640 | 	ret = synaptics_i2c_reset_config(client); | 
 | 641 | 	if (ret) | 
 | 642 | 		return ret; | 
 | 643 |  | 
| Dmitry Torokhov | 30b3713 | 2009-09-16 01:06:42 -0700 | [diff] [blame] | 644 | 	synaptics_i2c_reschedule_work(touch, | 
 | 645 | 				msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 
| Mike Rapoport | eef3e4c | 2009-06-11 08:08:39 -0700 | [diff] [blame] | 646 |  | 
 | 647 | 	return 0; | 
 | 648 | } | 
 | 649 | #else | 
 | 650 | #define synaptics_i2c_suspend	NULL | 
 | 651 | #define synaptics_i2c_resume	NULL | 
 | 652 | #endif | 
 | 653 |  | 
 | 654 | static const struct i2c_device_id synaptics_i2c_id_table[] = { | 
 | 655 | 	{ "synaptics_i2c", 0 }, | 
 | 656 | 	{ }, | 
 | 657 | }; | 
 | 658 | MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); | 
 | 659 |  | 
 | 660 | static struct i2c_driver synaptics_i2c_driver = { | 
 | 661 | 	.driver = { | 
 | 662 | 		.name	= DRIVER_NAME, | 
 | 663 | 		.owner	= THIS_MODULE, | 
 | 664 | 	}, | 
 | 665 |  | 
 | 666 | 	.probe		= synaptics_i2c_probe, | 
 | 667 | 	.remove		= __devexit_p(synaptics_i2c_remove), | 
 | 668 |  | 
 | 669 | 	.suspend	= synaptics_i2c_suspend, | 
 | 670 | 	.resume		= synaptics_i2c_resume, | 
 | 671 | 	.id_table	= synaptics_i2c_id_table, | 
 | 672 | }; | 
 | 673 |  | 
 | 674 | static int __init synaptics_i2c_init(void) | 
 | 675 | { | 
 | 676 | 	return i2c_add_driver(&synaptics_i2c_driver); | 
 | 677 | } | 
 | 678 |  | 
 | 679 | static void __exit synaptics_i2c_exit(void) | 
 | 680 | { | 
 | 681 | 	i2c_del_driver(&synaptics_i2c_driver); | 
 | 682 | } | 
 | 683 |  | 
 | 684 | module_init(synaptics_i2c_init); | 
 | 685 | module_exit(synaptics_i2c_exit); | 
 | 686 |  | 
 | 687 | MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); | 
 | 688 | MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); | 
 | 689 | MODULE_LICENSE("GPL"); | 
 | 690 |  |