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