Input: atmel_mxt_ts - Support for touchpad variant
This same driver can be used by atmel based touchscreens and touchpads (buttonpads). Platform data may specify a device is a touchpad using the is_tp flag. This will cause the driver to perform some touchpad specific initializations, such as: * register input device name "Atmel maXTouch Touchpad" instead of Touchscreen. * register BTN_LEFT & BTN_TOOL_* event types. * register axis resolution (as a fixed constant, for now) * register BUTTONPAD property * process GPIO buttons using reportid T19 Input event GPIO mapping is done by the platform data key_map array. key_map[x] should contain the KEY or BTN code to send when processing GPIOx from T19. To specify a GPIO as not an input source, populate with KEY_RESERVED, or 0. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Benson Leung <bleung@chromium.org> Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Tested-by: Olof Johansson <olof@lixom.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
					parent
					
						
							
								67a865a40b
							
						
					
				
			
			
				commit
				
					
						22dfab7fd7
					
				
			
		
					 2 changed files with 67 additions and 2 deletions
				
			
		|  | @ -181,6 +181,12 @@ | ||||||
| 
 | 
 | ||||||
| #define MXT_FWRESET_TIME	175	/* msec */ | #define MXT_FWRESET_TIME	175	/* msec */ | ||||||
| 
 | 
 | ||||||
|  | /* MXT_SPT_GPIOPWM_T19 field */ | ||||||
|  | #define MXT_GPIO0_MASK		0x04 | ||||||
|  | #define MXT_GPIO1_MASK		0x08 | ||||||
|  | #define MXT_GPIO2_MASK		0x10 | ||||||
|  | #define MXT_GPIO3_MASK		0x20 | ||||||
|  | 
 | ||||||
| /* Command to unlock bootloader */ | /* Command to unlock bootloader */ | ||||||
| #define MXT_UNLOCK_CMD_MSB	0xaa | #define MXT_UNLOCK_CMD_MSB	0xaa | ||||||
| #define MXT_UNLOCK_CMD_LSB	0xdc | #define MXT_UNLOCK_CMD_LSB	0xdc | ||||||
|  | @ -212,6 +218,8 @@ | ||||||
| /* Touchscreen absolute values */ | /* Touchscreen absolute values */ | ||||||
| #define MXT_MAX_AREA		0xff | #define MXT_MAX_AREA		0xff | ||||||
| 
 | 
 | ||||||
|  | #define MXT_PIXELS_PER_MM	20 | ||||||
|  | 
 | ||||||
| struct mxt_info { | struct mxt_info { | ||||||
| 	u8 family_id; | 	u8 family_id; | ||||||
| 	u8 variant_id; | 	u8 variant_id; | ||||||
|  | @ -243,6 +251,8 @@ struct mxt_data { | ||||||
| 	const struct mxt_platform_data *pdata; | 	const struct mxt_platform_data *pdata; | ||||||
| 	struct mxt_object *object_table; | 	struct mxt_object *object_table; | ||||||
| 	struct mxt_info info; | 	struct mxt_info info; | ||||||
|  | 	bool is_tp; | ||||||
|  | 
 | ||||||
| 	unsigned int irq; | 	unsigned int irq; | ||||||
| 	unsigned int max_x; | 	unsigned int max_x; | ||||||
| 	unsigned int max_y; | 	unsigned int max_y; | ||||||
|  | @ -251,6 +261,7 @@ struct mxt_data { | ||||||
| 	u8 T6_reportid; | 	u8 T6_reportid; | ||||||
| 	u8 T9_reportid_min; | 	u8 T9_reportid_min; | ||||||
| 	u8 T9_reportid_max; | 	u8 T9_reportid_max; | ||||||
|  | 	u8 T19_reportid; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static bool mxt_object_readable(unsigned int type) | static bool mxt_object_readable(unsigned int type) | ||||||
|  | @ -502,6 +513,21 @@ static int mxt_write_object(struct mxt_data *data, | ||||||
| 	return mxt_write_reg(data->client, reg + offset, val); | 	return mxt_write_reg(data->client, reg + offset, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void mxt_input_button(struct mxt_data *data, struct mxt_message *message) | ||||||
|  | { | ||||||
|  | 	struct input_dev *input = data->input_dev; | ||||||
|  | 	bool button; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	/* Active-low switch */ | ||||||
|  | 	for (i = 0; i < MXT_NUM_GPIO; i++) { | ||||||
|  | 		if (data->pdata->key_map[i] == KEY_RESERVED) | ||||||
|  | 			continue; | ||||||
|  | 		button = !(message->message[0] & MXT_GPIO0_MASK << i); | ||||||
|  | 		input_report_key(input, data->pdata->key_map[i], button); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void mxt_input_touchevent(struct mxt_data *data, | static void mxt_input_touchevent(struct mxt_data *data, | ||||||
| 				      struct mxt_message *message, int id) | 				      struct mxt_message *message, int id) | ||||||
| { | { | ||||||
|  | @ -585,6 +611,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | ||||||
| 			int id = reportid - data->T9_reportid_min; | 			int id = reportid - data->T9_reportid_min; | ||||||
| 			mxt_input_touchevent(data, &message, id); | 			mxt_input_touchevent(data, &message, id); | ||||||
| 			update_input = true; | 			update_input = true; | ||||||
|  | 		} else if (message.reportid == data->T19_reportid) { | ||||||
|  | 			mxt_input_button(data, &message); | ||||||
|  | 			update_input = true; | ||||||
| 		} else { | 		} else { | ||||||
| 			mxt_dump_message(dev, &message); | 			mxt_dump_message(dev, &message); | ||||||
| 		} | 		} | ||||||
|  | @ -764,6 +793,9 @@ static int mxt_get_object_table(struct mxt_data *data) | ||||||
| 			data->T9_reportid_min = min_id; | 			data->T9_reportid_min = min_id; | ||||||
| 			data->T9_reportid_max = max_id; | 			data->T9_reportid_max = max_id; | ||||||
| 			break; | 			break; | ||||||
|  | 		case MXT_SPT_GPIOPWM_T19: | ||||||
|  | 			data->T19_reportid = min_id; | ||||||
|  | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -777,7 +809,7 @@ static void mxt_free_object_table(struct mxt_data *data) | ||||||
| 	data->T6_reportid = 0; | 	data->T6_reportid = 0; | ||||||
| 	data->T9_reportid_min = 0; | 	data->T9_reportid_min = 0; | ||||||
| 	data->T9_reportid_max = 0; | 	data->T9_reportid_max = 0; | ||||||
| 
 | 	data->T19_reportid = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int mxt_initialize(struct mxt_data *data) | static int mxt_initialize(struct mxt_data *data) | ||||||
|  | @ -1115,9 +1147,13 @@ static int mxt_probe(struct i2c_client *client, | ||||||
| 		goto err_free_mem; | 		goto err_free_mem; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	input_dev->name = "Atmel maXTouch Touchscreen"; | 	data->is_tp = pdata && pdata->is_tp; | ||||||
|  | 
 | ||||||
|  | 	input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" : | ||||||
|  | 					  "Atmel maXTouch Touchscreen"; | ||||||
| 	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | 	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | ||||||
| 		 client->adapter->nr, client->addr); | 		 client->adapter->nr, client->addr); | ||||||
|  | 
 | ||||||
| 	input_dev->phys = data->phys; | 	input_dev->phys = data->phys; | ||||||
| 
 | 
 | ||||||
| 	input_dev->id.bustype = BUS_I2C; | 	input_dev->id.bustype = BUS_I2C; | ||||||
|  | @ -1140,6 +1176,29 @@ static int mxt_probe(struct i2c_client *client, | ||||||
| 	__set_bit(EV_KEY, input_dev->evbit); | 	__set_bit(EV_KEY, input_dev->evbit); | ||||||
| 	__set_bit(BTN_TOUCH, input_dev->keybit); | 	__set_bit(BTN_TOUCH, input_dev->keybit); | ||||||
| 
 | 
 | ||||||
|  | 	if (data->is_tp) { | ||||||
|  | 		int i; | ||||||
|  | 		__set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||||||
|  | 		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < MXT_NUM_GPIO; i++) | ||||||
|  | 			if (pdata->key_map[i] != KEY_RESERVED) | ||||||
|  | 				__set_bit(pdata->key_map[i], input_dev->keybit); | ||||||
|  | 
 | ||||||
|  | 		__set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||||||
|  | 		__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||||||
|  | 		__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||||||
|  | 		__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||||||
|  | 		__set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit); | ||||||
|  | 
 | ||||||
|  | 		input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||||||
|  | 		input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||||||
|  | 		input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||||||
|  | 				  MXT_PIXELS_PER_MM); | ||||||
|  | 		input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||||||
|  | 				  MXT_PIXELS_PER_MM); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* For single touch */ | 	/* For single touch */ | ||||||
| 	input_set_abs_params(input_dev, ABS_X, | 	input_set_abs_params(input_dev, ABS_X, | ||||||
| 			     0, data->max_x, 0, 0); | 			     0, data->max_x, 0, 0); | ||||||
|  | @ -1258,6 +1317,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | ||||||
| static const struct i2c_device_id mxt_id[] = { | static const struct i2c_device_id mxt_id[] = { | ||||||
| 	{ "qt602240_ts", 0 }, | 	{ "qt602240_ts", 0 }, | ||||||
| 	{ "atmel_mxt_ts", 0 }, | 	{ "atmel_mxt_ts", 0 }, | ||||||
|  | 	{ "atmel_mxt_tp", 0 }, | ||||||
| 	{ "mXT224", 0 }, | 	{ "mXT224", 0 }, | ||||||
| 	{ } | 	{ } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -15,6 +15,9 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/types.h> | #include <linux/types.h> | ||||||
| 
 | 
 | ||||||
|  | /* For key_map array */ | ||||||
|  | #define MXT_NUM_GPIO		4 | ||||||
|  | 
 | ||||||
| /* Orient */ | /* Orient */ | ||||||
| #define MXT_NORMAL		0x0 | #define MXT_NORMAL		0x0 | ||||||
| #define MXT_DIAGONAL		0x1 | #define MXT_DIAGONAL		0x1 | ||||||
|  | @ -39,6 +42,8 @@ struct mxt_platform_data { | ||||||
| 	unsigned int voltage; | 	unsigned int voltage; | ||||||
| 	unsigned char orient; | 	unsigned char orient; | ||||||
| 	unsigned long irqflags; | 	unsigned long irqflags; | ||||||
|  | 	bool is_tp; | ||||||
|  | 	const unsigned int key_map[MXT_NUM_GPIO]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif /* __LINUX_ATMEL_MXT_TS_H */ | #endif /* __LINUX_ATMEL_MXT_TS_H */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Daniel Kurtz
				Daniel Kurtz