diff options
Diffstat (limited to 'drivers/input/touchscreen/mms114.c')
| -rw-r--r-- | drivers/input/touchscreen/mms114.c | 89 | 
1 files changed, 81 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index ac12494c7930..af233b6a16d9 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -7,7 +7,6 @@  #include <linux/module.h>  #include <linux/delay.h>  #include <linux/of.h> -#include <linux/of_device.h>  #include <linux/i2c.h>  #include <linux/input/mt.h>  #include <linux/input/touchscreen.h> @@ -43,6 +42,7 @@  /* Touchscreen absolute values */  #define MMS114_MAX_AREA			0xff +#define MMS114_MAX_TOUCHKEYS		15  #define MMS114_MAX_TOUCH		10  #define MMS114_EVENT_SIZE		8  #define MMS136_EVENT_SIZE		6 @@ -70,6 +70,9 @@ struct mms114_data {  	unsigned int		contact_threshold;  	unsigned int		moving_threshold; +	u32 keycodes[MMS114_MAX_TOUCHKEYS]; +	int num_keycodes; +  	/* Use cache data for mode control register(write only) */  	u8			cache_mode_control;  }; @@ -167,11 +170,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou  		return;  	} -	if (touch->type != MMS114_TYPE_TOUCHSCREEN) { -		dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type); -		return; -	} -  	id = touch->id - 1;  	x = touch->x_lo | touch->x_hi << 8;  	y = touch->y_lo | touch->y_hi << 8; @@ -191,9 +189,33 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou  	}  } +static void mms114_process_touchkey(struct mms114_data *data, +				    struct mms114_touch *touch) +{ +	struct i2c_client *client = data->client; +	struct input_dev *input_dev = data->input_dev; +	unsigned int keycode_id; + +	if (touch->id == 0) +		return; + +	if (touch->id > data->num_keycodes) { +		dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n", +			touch->id); +		return; +	} + +	keycode_id = touch->id - 1; +	dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n", keycode_id, +		touch->pressed); + +	input_report_key(input_dev, data->keycodes[keycode_id], touch->pressed); +} +  static irqreturn_t mms114_interrupt(int irq, void *dev_id)  {  	struct mms114_data *data = dev_id; +	struct i2c_client *client = data->client;  	struct input_dev *input_dev = data->input_dev;  	struct mms114_touch touch[MMS114_MAX_TOUCH];  	int packet_size; @@ -223,8 +245,22 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)  	if (error < 0)  		goto out; -	for (index = 0; index < touch_size; index++) -		mms114_process_mt(data, touch + index); +	for (index = 0; index < touch_size; index++) { +		switch (touch[index].type) { +		case MMS114_TYPE_TOUCHSCREEN: +			mms114_process_mt(data, touch + index); +			break; + +		case MMS114_TYPE_TOUCHKEY: +			mms114_process_touchkey(data, touch + index); +			break; + +		default: +			dev_err(&client->dev, "Wrong touch type (%d)\n", +				touch[index].type); +			break; +		} +	}  	input_mt_report_pointer_emulation(data->input_dev, true);  	input_sync(data->input_dev); @@ -446,6 +482,7 @@ static int mms114_probe(struct i2c_client *client)  	struct input_dev *input_dev;  	const void *match_data;  	int error; +	int i;  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {  		dev_err(&client->dev, "Not supported I2C adapter\n"); @@ -469,6 +506,42 @@ static int mms114_probe(struct i2c_client *client)  	data->type = (enum mms_type)match_data; +	data->num_keycodes = device_property_count_u32(&client->dev, +						       "linux,keycodes"); +	if (data->num_keycodes == -EINVAL) { +		data->num_keycodes = 0; +	} else if (data->num_keycodes < 0) { +		dev_err(&client->dev, +			"Unable to parse linux,keycodes property: %d\n", +			data->num_keycodes); +		return data->num_keycodes; +	} else if (data->num_keycodes > MMS114_MAX_TOUCHKEYS) { +		dev_warn(&client->dev, +			"Found %d linux,keycodes but max is %d, ignoring the rest\n", +			 data->num_keycodes, MMS114_MAX_TOUCHKEYS); +		data->num_keycodes = MMS114_MAX_TOUCHKEYS; +	} + +	if (data->num_keycodes > 0) { +		error = device_property_read_u32_array(&client->dev, +						       "linux,keycodes", +						       data->keycodes, +						       data->num_keycodes); +		if (error) { +			dev_err(&client->dev, +				"Unable to read linux,keycodes values: %d\n", +				error); +			return error; +		} + +		input_dev->keycode = data->keycodes; +		input_dev->keycodemax = data->num_keycodes; +		input_dev->keycodesize = sizeof(data->keycodes[0]); +		for (i = 0; i < data->num_keycodes; i++) +			input_set_capability(input_dev, +					     EV_KEY, data->keycodes[i]); +	} +  	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);  	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);  	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);  |