diff options
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
| -rw-r--r-- | drivers/input/mouse/synaptics.c | 96 | 
1 files changed, 94 insertions, 2 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 26386f9d256..ef9e0b8a9aa 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -117,6 +117,82 @@ void synaptics_reset(struct psmouse *psmouse)  }  #ifdef CONFIG_MOUSE_PS2_SYNAPTICS +struct min_max_quirk { +	const char * const *pnp_ids; +	int x_min, x_max, y_min, y_max; +}; + +static const struct min_max_quirk min_max_pnpid_table[] = { +	{ +		(const char * const []){"LEN0033", NULL}, +		1024, 5052, 2258, 4832 +	}, +	{ +		(const char * const []){"LEN0035", "LEN0042", NULL}, +		1232, 5710, 1156, 4696 +	}, +	{ +		(const char * const []){"LEN0034", "LEN0036", "LEN2002", +					"LEN2004", NULL}, +		1024, 5112, 2024, 4832 +	}, +	{ +		(const char * const []){"LEN2001", NULL}, +		1024, 5022, 2508, 4832 +	}, +	{ } +}; + +/* This list has been kindly provided by Synaptics. */ +static const char * const topbuttonpad_pnp_ids[] = { +	"LEN0017", +	"LEN0018", +	"LEN0019", +	"LEN0023", +	"LEN002A", +	"LEN002B", +	"LEN002C", +	"LEN002D", +	"LEN002E", +	"LEN0033", /* Helix */ +	"LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ +	"LEN0035", /* X240 */ +	"LEN0036", /* T440 */ +	"LEN0037", +	"LEN0038", +	"LEN0041", +	"LEN0042", /* Yoga */ +	"LEN0045", +	"LEN0046", +	"LEN0047", +	"LEN0048", +	"LEN0049", +	"LEN2000", +	"LEN2001", /* Edge E431 */ +	"LEN2002", /* Edge E531 */ +	"LEN2003", +	"LEN2004", /* L440 */ +	"LEN2005", +	"LEN2006", +	"LEN2007", +	"LEN2008", +	"LEN2009", +	"LEN200A", +	"LEN200B", +	NULL +}; + +static bool matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) +{ +	int i; + +	if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) +		for (i = 0; ids[i]; i++) +			if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) +				return true; + +	return false; +}  /*****************************************************************************   *	Synaptics communications functions @@ -265,10 +341,12 @@ static int synaptics_identify(struct psmouse *psmouse)   * Read touchpad resolution and maximum reported coordinates   * Resolution is left zero if touchpad does not support the query   */ +  static int synaptics_resolution(struct psmouse *psmouse)  {  	struct synaptics_data *priv = psmouse->private;  	unsigned char resp[3]; +	int i;  	if (SYN_ID_MAJOR(priv->identity) < 4)  		return 0; @@ -280,6 +358,16 @@ static int synaptics_resolution(struct psmouse *psmouse)  		}  	} +	for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { +		if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) { +			priv->x_min = min_max_pnpid_table[i].x_min; +			priv->x_max = min_max_pnpid_table[i].x_max; +			priv->y_min = min_max_pnpid_table[i].y_min; +			priv->y_max = min_max_pnpid_table[i].y_max; +			return 0; +		} +	} +  	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&  	    SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {  		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { @@ -1244,8 +1332,10 @@ static void set_abs_position_params(struct input_dev *dev,  	input_abs_set_res(dev, y_code, priv->y_res);  } -static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) +static void set_input_params(struct psmouse *psmouse, +			     struct synaptics_data *priv)  { +	struct input_dev *dev = psmouse->dev;  	int i;  	/* Things that apply to both modes */ @@ -1314,6 +1404,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)  	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {  		__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); +		if (matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) +			__set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);  		/* Clickpads report only left button */  		__clear_bit(BTN_RIGHT, dev->keybit);  		__clear_bit(BTN_MIDDLE, dev->keybit); @@ -1538,7 +1630,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)  		     priv->capabilities, priv->ext_cap, priv->ext_cap_0c,  		     priv->board_id, priv->firmware_id); -	set_input_params(psmouse->dev, priv); +	set_input_params(psmouse, priv);  	/*  	 * Encode touchpad model so that it can be used to set  | 
