diff options
| -rw-r--r-- | Documentation/devicetree/bindings/input/atmel,maxtouch.txt | 27 | ||||
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 770 | ||||
| -rw-r--r-- | include/dt-bindings/input/atmel_mxt_ts.h | 22 | ||||
| -rw-r--r-- | include/linux/platform_data/atmel_mxt_ts.h (renamed from include/linux/i2c/atmel_mxt_ts.h) | 8 | 
4 files changed, 543 insertions, 284 deletions
diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index 6319f07bfbc..e879f6d1d2c 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -6,15 +6,34 @@ Required properties:  - reg: The I2C address of the device -- interrupts: The sink for the touch controller CHG/IRQ output +- interrupts: The sink for the touchpad's IRQ output      See ../interrupt-controller/interrupts.txt -Optional properties for maXTouch device: +Optional properties for main touchpad device: -- linux,gpio-keymap: An array of up to 4 entries indicating the Linux -    keycode generated by each GPIO. Linux keycodes are defined in +- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages +    on GPIO bit changes. An array of up to 8 entries can be provided +    indicating the Linux keycode mapped to each bit of the status byte, +    starting at the LSB. Linux keycodes are defined in      <dt-bindings/input/input.h>. +    Note: the numbering of the GPIOs and the bit they start at varies between +    maXTouch devices. You must either refer to the documentation, or +    experiment to determine which bit corresponds to which input. Use +    KEY_RESERVED for unused padding values. + +- atmel,suspend-mode: Select method used to suspend: +    MXT_SUSPEND_DEEP_SLEEP - use T7 to suspend the device into deep sleep +    MXT_SUSPEND_TOUCH_CTRL - use T9.CTRL to turn off touch processing +    Definitions are in <dt-bindings/input/atmel_mxt_ts.h>. + +- atmel,reset-gpio: Configure RESET GPIO. Required for regulator support. + +- atmel,cfg_name: Provide name of configuration file in OBP_RAW format. This +    will be downloaded from the firmware loader on probe to the device. + +- atmel,input_name: Override name of input device from the default. +  Example:  	touch@4b { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index c4249f8b5ba..7298926a75c 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -20,7 +20,7 @@  #include <linux/delay.h>  #include <linux/firmware.h>  #include <linux/i2c.h> -#include <linux/i2c/atmel_mxt_ts.h> +#include <linux/platform_data/atmel_mxt_ts.h>  #include <linux/input/mt.h>  #include <linux/interrupt.h>  #include <linux/irq.h> @@ -28,6 +28,7 @@  #include <linux/slab.h>  #include <linux/regulator/consumer.h>  #include <linux/gpio.h> +#include <linux/workqueue.h>  #ifdef CONFIG_OF  #include <linux/of_gpio.h> @@ -71,7 +72,9 @@  #define MXT_SPT_MESSAGECOUNT_T44	44  #define MXT_SPT_CTECONFIG_T46		46  #define MXT_PROCI_ACTIVE_STYLUS_T63	63 +#define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71  #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 +#define MXT_PROCI_ACTIVESTYLUS_T107	107  /* MXT_GEN_MESSAGE_T5 object */  #define MXT_RPTID_NOMSG		0xff @@ -101,6 +104,7 @@ struct t7_config {  #define MXT_POWER_CFG_DEEPSLEEP		1  /* MXT_TOUCH_MULTI_T9 field */ +#define MXT_TOUCH_CTRL		0  #define MXT_T9_ORIENT		9  #define MXT_T9_RANGE		18 @@ -135,9 +139,6 @@ struct t9_range {  /* Define for MXT_PROCI_TOUCHSUPPRESSION_T42 */  #define MXT_T42_MSG_TCHSUP	(1 << 0) -/* T47 Stylus */ -#define MXT_TOUCH_MAJOR_T47_STYLUS	1 -  /* T63 Stylus */  #define MXT_T63_STYLUS_PRESS	(1 << 0)  #define MXT_T63_STYLUS_RELEASE	(1 << 1) @@ -166,7 +167,28 @@ struct t9_range {  #define MXT_T100_DETECT		(1 << 7)  #define MXT_T100_TYPE_MASK	0x70 -#define MXT_T100_TYPE_STYLUS	0x20 + +enum t100_type { +	MXT_T100_TYPE_FINGER		= 1, +	MXT_T100_TYPE_PASSIVE_STYLUS	= 2, +	MXT_T100_TYPE_ACTIVE_STYLUS	= 3, +	MXT_T100_TYPE_HOVERING_FINGER	= 4, +	MXT_T100_TYPE_GLOVE		= 5, +	MXT_T100_TYPE_LARGE_TOUCH	= 6, +}; + +/* Gen2 Active Stylus */ +#define MXT_T107_STYLUS_STYAUX		42 +#define MXT_T107_STYLUS_STYAUX_PRESSURE	(1 << 0) +#define MXT_T107_STYLUS_STYAUX_PEAK	(1 << 4) + +#define MXT_T107_STYLUS_HOVER		(1 << 0) +#define MXT_T107_STYLUS_TIPSWITCH	(1 << 1) +#define MXT_T107_STYLUS_BUTTON0		(1 << 2) +#define MXT_T107_STYLUS_BUTTON1		(1 << 3) + +#define MXT_TOUCH_MAJOR_DEFAULT	1 +#define MXT_PRESSURE_DEFAULT	1  /* Delay times */  #define MXT_BACKUP_TIME		50	/* msec */ @@ -179,6 +201,7 @@ struct t9_range {  #define MXT_REGULATOR_DELAY	150	/* msec */  #define MXT_CHG_DELAY	        100	/* msec */  #define MXT_POWERON_DELAY	150	/* msec */ +#define MXT_BOOTLOADER_WAIT	36E5	/* 1 minute */  /* Command to unlock bootloader */  #define MXT_UNLOCK_CMD_MSB	0xaa @@ -220,6 +243,26 @@ struct mxt_object {  	u8 num_report_ids;  } __packed; +/* Firmware frame structure */ +struct mxt_fw_frame { +	__be16 size; +	u8 data[]; +}; + +/* Firmware update context */ +struct mxt_flash { +	struct mxt_data *data; +	const struct firmware *fw; +	struct mxt_fw_frame *frame; +	loff_t pos; +	size_t frame_size; +	unsigned int count; +	unsigned int retry; +	u8 previous; +	struct completion flash_completion; +	struct delayed_work work; +}; +  /* Each client has this additional data */  struct mxt_data {  	struct i2c_client *client; @@ -256,12 +299,14 @@ struct mxt_data {  	struct t7_config t7_cfg;  	u8 num_stylusids;  	unsigned long t15_keystatus; +	u8 stylus_aux_pressure; +	u8 stylus_aux_peak;  	bool use_retrigen_workaround; -	bool use_regulator;  	struct regulator *reg_vdd;  	struct regulator *reg_avdd;  	char *fw_name;  	char *cfg_name; +	struct mxt_flash *flash;  	/* Cached parameters from object table */  	u16 T5_address; @@ -269,6 +314,7 @@ struct mxt_data {  	u8 T6_reportid;  	u16 T6_address;  	u16 T7_address; +	u16 T71_address;  	u8 T9_reportid_min;  	u8 T9_reportid_max;  	u8 T15_reportid_min; @@ -283,9 +329,7 @@ struct mxt_data {  	u8 T63_reportid_max;  	u8 T100_reportid_min;  	u8 T100_reportid_max; - -	/* for fw update in bootloader */ -	struct completion bl_completion; +	u16 T107_address;  	/* for reset handling */  	struct completion reset_completion; @@ -293,6 +337,9 @@ struct mxt_data {  	/* for config update handling */  	struct completion crc_completion; +	/* for power up handling */ +	struct completion chg_completion; +  	/* Indicates whether device is in suspend */  	bool suspended; @@ -337,6 +384,7 @@ static bool mxt_object_readable(unsigned int type)  	case MXT_SPT_USERDATA_T38:  	case MXT_SPT_DIGITIZER_T43:  	case MXT_SPT_CTECONFIG_T46: +	case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:  		return true;  	default:  		return false; @@ -582,111 +630,142 @@ static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address)  {  	struct device *dev = &data->client->dev;  	int error; -	u8 val; -	bool crc_failure; +	u8 buf[3]; +	bool crc_failure, extended_id;  	error = mxt_lookup_bootloader_address(data, alt_address);  	if (error)  		return error; -	error = mxt_bootloader_read(data, &val, 1); +	/* Check bootloader status and version information */ +	error = mxt_bootloader_read(data, buf, sizeof(buf));  	if (error)  		return error; -	/* Check app crc fail mode */ -	crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; +	crc_failure = (buf[0] & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; +	extended_id = buf[0] & MXT_BOOT_EXTENDED_ID; -	dev_err(dev, "Detected bootloader, status:%02X%s\n", -			val, crc_failure ? ", APP_CRC_FAIL" : ""); +	dev_info(dev, "Found bootloader addr:%02x ID:%u%s%u%s\n", +		 data->bootloader_addr, +		 extended_id ? (buf[1] & MXT_BOOT_ID_MASK) : buf[0], +		 extended_id ? " version:" : "", +		 extended_id ? buf[2] : 0, +		 crc_failure ? ", APP_CRC_FAIL" : "");  	return 0;  } -static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val) -{ -	struct device *dev = &data->client->dev; -	u8 buf[3]; +static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock); -	if (val & MXT_BOOT_EXTENDED_ID) { -		if (mxt_bootloader_read(data, &buf[0], 3) != 0) { -			dev_err(dev, "%s: i2c failure\n", __func__); -			return val; -		} - -		dev_dbg(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]); +static int mxt_write_firmware_frame(struct mxt_data *data, struct mxt_flash *f) +{ +	f->frame = (struct mxt_fw_frame*)(f->fw->data + f->pos); -		return buf[0]; -	} else { -		dev_dbg(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK); +	/* Take account of CRC bytes */ +	f->frame_size = __be16_to_cpu(f->frame->size) + 2U; -		return val; -	} +	/* Write one frame to device */ +	return mxt_bootloader_write(data, f->fw->data + f->pos, +				   f->frame_size);  } -static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, -				bool wait) +static int mxt_check_bootloader(struct mxt_data *data)  {  	struct device *dev = &data->client->dev; -	u8 val; +	struct mxt_flash *f = data->flash; +	u8 state;  	int ret; -recheck: -	if (wait) { -		/* -		 * In application update mode, the interrupt -		 * line signals state transitions. We must wait for the -		 * CHG assertion before reading the status byte. -		 * Once the status byte has been read, the line is deasserted. -		 */ -		ret = mxt_wait_for_completion(data, &data->bl_completion, -					      MXT_FW_CHG_TIMEOUT); -		if (ret) { -			/* -			 * TODO: handle -ERESTARTSYS better by terminating -			 * fw update process before returning to userspace -			 * by writing length 0x000 to device (iff we are in -			 * WAITING_FRAME_DATA state). -			 */ -			dev_err(dev, "Update wait error %d\n", ret); -			return ret; -		} +	/* Handle interrupt after download/flash process */ +	if (f->pos >= f->fw->size) { +		complete(&f->flash_completion); +		return 0;  	} -	ret = mxt_bootloader_read(data, &val, 1); +	ret = mxt_bootloader_read(data, &state, 1);  	if (ret)  		return ret; -	if (state == MXT_WAITING_BOOTLOAD_CMD) -		val = mxt_get_bootloader_version(data, val); +	/* Remove don't care bits */ +	if (state & ~MXT_BOOT_STATUS_MASK) +		state &= ~MXT_BOOT_STATUS_MASK;  	switch (state) {  	case MXT_WAITING_BOOTLOAD_CMD: +		dev_info(dev, "Unlocking bootloader\n"); +		ret = mxt_send_bootloader_cmd(data, true); +		if (ret) +			return ret; + +		break; +  	case MXT_WAITING_FRAME_DATA: -	case MXT_APP_CRC_FAIL: -		val &= ~MXT_BOOT_STATUS_MASK; +		if ((f->previous != MXT_WAITING_BOOTLOAD_CMD) +		    && (f->previous != MXT_FRAME_CRC_PASS) +		    && (f->previous != MXT_FRAME_CRC_FAIL)) +			goto unexpected; + +		ret = mxt_write_firmware_frame(data, f); +		if (ret) +			return ret; +  		break; + +	case MXT_FRAME_CRC_CHECK: +		if (f->previous != MXT_WAITING_FRAME_DATA) +			goto unexpected; +		break; +  	case MXT_FRAME_CRC_PASS: -		if (val == MXT_FRAME_CRC_CHECK) { -			goto recheck; -		} else if (val == MXT_FRAME_CRC_FAIL) { -			dev_err(dev, "Bootloader CRC fail\n"); -			return -EINVAL; +		if (f->previous != MXT_FRAME_CRC_CHECK) +			goto unexpected; + +		/* Next frame */ +		f->retry = 0; +		f->pos += f->frame_size; +		f->count++; + +		if (f->pos >= f->fw->size) +			dev_info(dev, "Sent %u frames, %zu bytes\n", +				f->count, f->fw->size); +		else if (f->count % 50 == 0) +			dev_dbg(dev, "Sent %u frames, %lld/%zu bytes\n", +				f->count, f->pos, f->fw->size); + +		break; + +	case MXT_FRAME_CRC_FAIL: +		f->retry++; + +		if (f->retry > 20) { +			dev_err(dev, "Retry count exceeded\n"); +			return -EIO; +		} else { +			dev_dbg(dev, "Bootloader frame CRC failure\n");  		} + +		/* Back off by 20ms per retry */ +		msleep(f->retry * 20); +  		break; +  	default:  		return -EINVAL;  	} -	if (val != state) { -		dev_err(dev, "Invalid bootloader state %02X != %02X\n", -			val, state); -		return -EINVAL; -	} +	f->previous = state; + +	/* Poll after 0.1s if no interrupt received */ +	schedule_delayed_work(&f->work, HZ / 10);  	return 0; + +unexpected: +	dev_err(dev, "Unexpected state transition\n"); +	return -EINVAL;  } -static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock) +int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)  {  	int ret;  	u8 buf[2]; @@ -839,6 +918,20 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)  	data->t6_status = status;  } +static int mxt_write_object(struct mxt_data *data, +				 u8 type, u8 offset, u8 val) +{ +	struct mxt_object *object; +	u16 reg; + +	object = mxt_get_object(data, type); +	if (!object || offset >= mxt_obj_size(object)) +		return -EINVAL; + +	reg = object->start_address; +	return mxt_write_reg(data->client, reg + offset, val); +} +  static void mxt_input_button(struct mxt_data *data, u8 *message)  {  	struct input_dev *input = data->input_dev; @@ -922,7 +1015,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)  		/* A size of zero indicates touch is from a linked T47 Stylus */  		if (area == 0) { -			area = MXT_TOUCH_MAJOR_T47_STYLUS; +			area = MXT_TOUCH_MAJOR_DEFAULT;  			tool = MT_TOOL_PEN;  		} else {  			tool = MT_TOOL_FINGER; @@ -949,9 +1042,17 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)  	struct input_dev *input_dev = data->input_dev;  	int id;  	u8 status; +	u8 type;  	int x;  	int y;  	int tool; +	u8 major = 0; +	u8 pressure = 0; +	u8 orientation = 0; +	bool active = false; +	bool hover = false; +	bool eraser = false; +	bool barrel = false;  	id = message[0] - data->T100_reportid_min - 2; @@ -963,53 +1064,108 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)  	x = (message[3] << 8) | message[2];  	y = (message[5] << 8) | message[4]; -	dev_dbg(dev, -		"[%u] status:%02X x:%u y:%u area:%02X amp:%02X vec:%02X\n", -		id, -		status, -		x, y, -		data->t100_aux_area ? message[data->t100_aux_area] : 0, -		data->t100_aux_ampl ? message[data->t100_aux_ampl] : 0, -		data->t100_aux_vect ? message[data->t100_aux_vect] : 0); +	if (status & MXT_T100_DETECT) { +		type = (status & MXT_T100_TYPE_MASK) >> 4; -	input_mt_slot(input_dev, id); +		switch (type) { +		case MXT_T100_TYPE_HOVERING_FINGER: +			hover = true; +			/* fall through */ +		case MXT_T100_TYPE_FINGER: +		case MXT_T100_TYPE_GLOVE: +			active = true; +			tool = MT_TOOL_FINGER; -	if (status & MXT_T100_DETECT) { -		if ((status & MXT_T100_TYPE_MASK) == MXT_T100_TYPE_STYLUS) +			if (data->t100_aux_area) +				major = message[data->t100_aux_area]; +			if (data->t100_aux_ampl) +				pressure = message[data->t100_aux_ampl]; +			if (data->t100_aux_vect) +				orientation = message[data->t100_aux_vect]; + +			break; + +		case MXT_T100_TYPE_PASSIVE_STYLUS: +			active = true;  			tool = MT_TOOL_PEN; -		else -			tool = MT_TOOL_FINGER; -		/* Touch active */ -		input_mt_report_slot_state(input_dev, tool, 1); -		input_report_abs(input_dev, ABS_MT_POSITION_X, x); -		input_report_abs(input_dev, ABS_MT_POSITION_Y, y); +			/* Passive stylus is reported with size zero so +			 * hardcode */ +			major = MXT_TOUCH_MAJOR_DEFAULT; -		if (data->t100_aux_ampl) -			input_report_abs(input_dev, ABS_MT_PRESSURE, -					 message[data->t100_aux_ampl]); +			if (data->t100_aux_ampl) +				pressure = message[data->t100_aux_ampl]; -		if (data->t100_aux_area) { -			if (tool == MT_TOOL_PEN) -				input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, -						 MXT_TOUCH_MAJOR_T47_STYLUS); -			else -				input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, -						 message[data->t100_aux_area]); +			break; + +		case MXT_T100_TYPE_ACTIVE_STYLUS: +			/* stylus in range, but position unavailable */ +			if (!(message[6] & MXT_T107_STYLUS_HOVER)) +				break; + +			active = true; +			tool = MT_TOOL_PEN; +			major = MXT_TOUCH_MAJOR_DEFAULT; +			eraser = message[6] & MXT_T107_STYLUS_BUTTON0; +			barrel = message[6] & MXT_T107_STYLUS_BUTTON1; + +			if (!(message[6] & MXT_T107_STYLUS_TIPSWITCH)) +				hover = true; +			else if (data->stylus_aux_pressure) +				pressure = message[data->stylus_aux_pressure]; + +			break; + +		case MXT_T100_TYPE_LARGE_TOUCH: +			/* Ignore suppressed touch */ +			break; + +		default: +			dev_dbg(dev, "Unexpected T100 type\n"); +			return;  		} +	} + +	if (hover) { +		pressure = 0; +		major = 0; +	} else if (active) { +		/* +		 * Values reported should be non-zero if tool is touching the +		 * device +		 */ +		if (pressure == 0) +			pressure = MXT_PRESSURE_DEFAULT; + +		if (major == 0) +			major = MXT_TOUCH_MAJOR_DEFAULT; +	} + +	input_mt_slot(input_dev, id); -		if (data->t100_aux_vect) -			input_report_abs(input_dev, ABS_MT_ORIENTATION, -					 message[data->t100_aux_vect]); +	if (active) { +		dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n", +			id, type, x, y, major, pressure, orientation); + +		input_mt_report_slot_state(input_dev, tool, 1); +		input_report_abs(input_dev, ABS_MT_POSITION_X, x); +		input_report_abs(input_dev, ABS_MT_POSITION_Y, y); +		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major); +		input_report_abs(input_dev, ABS_MT_PRESSURE, pressure); +		input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation); + +		input_report_key(input_dev, BTN_STYLUS, eraser); +		input_report_key(input_dev, BTN_STYLUS2, barrel);  	} else { -		/* Touch no longer active, close out slot */ -		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0); +		dev_dbg(dev, "[%u] release\n", id); + +		/* close out slot */ +		input_mt_report_slot_state(input_dev, 0, 0);  	}  	data->update_input = true;  } -  static void mxt_proc_t15_messages(struct mxt_data *data, u8 *msg)  {  	struct input_dev *input_dev = data->input_dev; @@ -1327,10 +1483,13 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)  {  	struct mxt_data *data = dev_id; +	complete(&data->chg_completion); +  	if (data->in_bootloader) { -		/* bootloader state transition completion */ -		complete(&data->bl_completion); -		return IRQ_HANDLED; +		if (data->flash && &data->flash->work) +			cancel_delayed_work_sync(&data->flash->work); + +		return IRQ_RETVAL(mxt_check_bootloader(data));  	}  	if (!data->object_table) @@ -1380,7 +1539,9 @@ static int mxt_soft_reset(struct mxt_data *data)  	struct device *dev = &data->client->dev;  	int ret = 0; -	dev_info(dev, "Resetting chip\n"); +	dev_info(dev, "Resetting device\n"); + +	disable_irq(data->irq);  	INIT_COMPLETION(data->reset_completion); @@ -1388,6 +1549,11 @@ static int mxt_soft_reset(struct mxt_data *data)  	if (ret)  		return ret; +	/* Ignore CHG line for 100ms after reset */ +	msleep(100); + +	enable_irq(data->irq); +  	ret = mxt_wait_for_completion(data, &data->reset_completion,  				      MXT_RESET_TIMEOUT);  	if (ret) @@ -1644,6 +1810,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)  	u32 info_crc, config_crc, calculated_crc;  	u8 *config_mem;  	size_t config_mem_size; +	u16 crc_start = 0;  	mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); @@ -1721,10 +1888,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)  			MXT_INFO_CHECKSUM_SIZE;  	config_mem_size = data->mem_size - cfg_start_ofs;  	config_mem = kzalloc(config_mem_size, GFP_KERNEL); -	if (!config_mem) { -		dev_err(dev, "Failed to allocate memory\n"); +	if (!config_mem)  		return -ENOMEM; -	}  	ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,  				  config_mem, config_mem_size); @@ -1732,20 +1897,22 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)  		goto release_mem;  	/* Calculate crc of the received configs (not the raw config file) */ -	if (data->T7_address < cfg_start_ofs) { -		dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n", -			data->T7_address, cfg_start_ofs); -		ret = 0; -		goto release_mem; -	} +	if (data->T71_address) +		crc_start = data->T71_address; +	else if (data->T7_address) +		crc_start = data->T7_address; +	else +		dev_warn(dev, "Could not find CRC start\n"); -	calculated_crc = mxt_calculate_crc(config_mem, -					   data->T7_address - cfg_start_ofs, -					   config_mem_size); +	if (crc_start > cfg_start_ofs) { +		calculated_crc = mxt_calculate_crc(config_mem, +						   crc_start - cfg_start_ofs, +						   config_mem_size); -	if (config_crc > 0 && config_crc != calculated_crc) -		dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n", -			 calculated_crc, config_crc); +		if (config_crc > 0 && config_crc != calculated_crc) +			dev_warn(dev, "Config CRC in file inconsistent, calculated=%06X, file=%06X\n", +				 calculated_crc, config_crc); +	}  	ret = mxt_upload_cfg_mem(data, cfg_start_ofs,  				 config_mem, config_mem_size); @@ -1776,9 +1943,23 @@ static int mxt_acquire_irq(struct mxt_data *data)  {  	int error; -	enable_irq(data->irq); +	if (!data->irq) { +		error = request_threaded_irq(data->client->irq, NULL, +				mxt_interrupt, +				data->pdata->irqflags | IRQF_ONESHOT, +				data->client->name, data); +		if (error) { +			dev_err(&data->client->dev, "Error requesting irq\n"); +			return error; +		} + +		/* Presence of data->irq means IRQ initialised */ +		data->irq = data->client->irq; +	} else { +		enable_irq(data->irq); +	} -	if (data->use_retrigen_workaround) { +	if (data->object_table && data->use_retrigen_workaround) {  		error = mxt_process_messages_until_invalid(data);  		if (error)  			return error; @@ -1805,11 +1986,11 @@ static void mxt_free_object_table(struct mxt_data *data)  	data->raw_info_block = NULL;  	kfree(data->msg_buf);  	data->msg_buf = NULL; -  	data->T5_address = 0;  	data->T5_msg_size = 0;  	data->T6_reportid = 0;  	data->T7_address = 0; +	data->T71_address = 0;  	data->T9_reportid_min = 0;  	data->T9_reportid_max = 0;  	data->T15_reportid_min = 0; @@ -1883,6 +2064,9 @@ static int mxt_parse_object_table(struct mxt_data *data,  		case MXT_GEN_POWER_T7:  			data->T7_address = object->start_address;  			break; +		case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71: +			data->T71_address = object->start_address; +			break;  		case MXT_TOUCH_MULTI_T9:  			/* Only handle messages from first T9 instance */  			data->T9_reportid_min = min_id; @@ -1922,6 +2106,9 @@ static int mxt_parse_object_table(struct mxt_data *data,  			/* first two report IDs reserved */  			data->num_touchids = object->num_report_ids - 2;  			break; +		case MXT_PROCI_ACTIVESTYLUS_T107: +			data->T107_address = object->start_address; +			break;  		}  		end_address = object->start_address @@ -1942,10 +2129,8 @@ static int mxt_parse_object_table(struct mxt_data *data,  	data->msg_buf = kcalloc(data->max_reportid,  				data->T5_msg_size, GFP_KERNEL); -	if (!data->msg_buf) { -		dev_err(&client->dev, "Failed to allocate message buffer\n"); +	if (!data->msg_buf)  		return -ENOMEM; -	}  	return 0;  } @@ -1967,10 +2152,8 @@ static int mxt_read_info_block(struct mxt_data *data)  	/* Read 7-byte ID information block starting at address 0 */  	size = sizeof(struct mxt_info);  	id_buf = kzalloc(size, GFP_KERNEL); -	if (!id_buf) { -		dev_err(&client->dev, "Failed to allocate memory\n"); +	if (!id_buf)  		return -ENOMEM; -	}  	error = __mxt_read_reg(client, 0, size, id_buf);  	if (error) { @@ -1985,7 +2168,6 @@ static int mxt_read_info_block(struct mxt_data *data)  	buf = krealloc(id_buf, size, GFP_KERNEL);  	if (!buf) { -		dev_err(&client->dev, "Failed to allocate memory\n");  		error = -ENOMEM;  		goto err_free_mem;  	} @@ -2056,14 +2238,19 @@ static void mxt_regulator_enable(struct mxt_data *data)  	if (error)  		return; +	/* +	 * According to maXTouch power sequencing specification, RESET line +	 * must be kept low until some time after regulators come up to +	 * voltage +	 */  	msleep(MXT_REGULATOR_DELAY);  	gpio_set_value(data->pdata->gpio_reset, 1);  	msleep(MXT_CHG_DELAY);  retry_wait: -	INIT_COMPLETION(data->bl_completion); +	INIT_COMPLETION(data->chg_completion);  	data->in_bootloader = true; -	error = mxt_wait_for_completion(data, &data->bl_completion, +	error = mxt_wait_for_completion(data, &data->chg_completion,  					MXT_POWERON_DELAY);  	if (error == -EINTR)  		goto retry_wait; @@ -2077,18 +2264,14 @@ static void mxt_regulator_disable(struct mxt_data *data)  	regulator_disable(data->reg_avdd);  } -static void mxt_probe_regulators(struct mxt_data *data) +static int mxt_probe_regulators(struct mxt_data *data)  {  	struct device *dev = &data->client->dev;  	int error; -	/* -	 * According to maXTouch power sequencing specification, RESET line -	 * must be kept low until some time after regulators come up to -	 * voltage -	 */  	if (!gpio_is_valid(data->pdata->gpio_reset)) {  		dev_dbg(dev, "Must have reset GPIO to use regulator support\n"); +		error = -EINVAL;  		goto fail;  	} @@ -2106,18 +2289,17 @@ static void mxt_probe_regulators(struct mxt_data *data)  		goto fail_release;  	} -	data->use_regulator = true;  	mxt_regulator_enable(data);  	dev_dbg(dev, "Initialised regulators\n"); -	return; +	return 0;  fail_release:  	regulator_put(data->reg_vdd);  fail:  	data->reg_vdd = NULL;  	data->reg_avdd = NULL; -	data->use_regulator = false; +	return error;  }  static int mxt_read_t9_resolution(struct mxt_data *data) @@ -2168,8 +2350,6 @@ static int mxt_read_t9_resolution(struct mxt_data *data)  	return 0;  } -static void mxt_start(struct mxt_data *data); -static void mxt_stop(struct mxt_data *data);  static int mxt_input_open(struct input_dev *dev);  static void mxt_input_close(struct input_dev *dev); @@ -2188,10 +2368,8 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data)  		dev_warn(dev, "Failed to initialize T9 resolution\n");  	input_dev = input_allocate_device(); -	if (!input_dev) { -		dev_err(dev, "Failed to allocate memory\n"); +	if (!input_dev)  		return -ENOMEM; -	}  	input_dev->name = "Atmel maXTouch Touchscreen";  	input_dev->phys = data->phys; @@ -2287,6 +2465,40 @@ err_free_mem:  	return error;  } +static int mxt_read_t107_stylus_config(struct mxt_data *data) +{ +	struct i2c_client *client = data->client; +	int error; +	struct mxt_object *object; +	u8 styaux; +	int aux; + +	object = mxt_get_object(data, MXT_PROCI_ACTIVESTYLUS_T107); +	if (!object) +		return 0; + +	error = __mxt_read_reg(client, +			       object->start_address + MXT_T107_STYLUS_STYAUX, +			       1, &styaux); +	if (error) +		return error; + +	/* map aux bits */ +	aux = 7; + +	if (styaux & MXT_T107_STYLUS_STYAUX_PRESSURE) +		data->stylus_aux_pressure = aux++; + +	if (styaux & MXT_T107_STYLUS_STYAUX_PEAK) +		data->stylus_aux_peak = aux++; + +	dev_dbg(&client->dev, +		"Enabling T107 active stylus, aux map pressure:%u peak:%u\n", +		data->stylus_aux_pressure, data->stylus_aux_peak); + +	return 0; +} +  static int mxt_read_t100_config(struct mxt_data *data)  {  	struct i2c_client *client = data->client; @@ -2332,10 +2544,6 @@ static int mxt_read_t100_config(struct mxt_data *data)  	if (range_x == 0)  		range_x = 1023; -	/* Handle default values */ -	if (range_x == 0) -		range_x = 1023; -  	if (range_y == 0)  		range_y = 1023; @@ -2359,6 +2567,10 @@ static int mxt_read_t100_config(struct mxt_data *data)  	if (tchaux & MXT_T100_TCHAUX_AREA)  		data->t100_aux_area = aux++; +	dev_dbg(&client->dev, +		"T100 aux mappings vect:%u ampl:%u area:%u\n", +		data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area); +  	dev_info(&client->dev,  		 "T100 Touchscreen size X%uY%u\n", data->max_x, data->max_y); @@ -2372,14 +2584,16 @@ static int mxt_initialize_t100_input_device(struct mxt_data *data)  	int error;  	error = mxt_read_t100_config(data); -	if (error) -		dev_warn(dev, "Failed to initialize T9 resolution\n"); +	if (error) { +		dev_err(dev, "Failed to read T100 config\n"); +		return error; +	} + +	mxt_read_t107_stylus_config(data);  	input_dev = input_allocate_device(); -	if (!data || !input_dev) { -		dev_err(dev, "Failed to allocate memory\n"); +	if (!data || !input_dev)  		return -ENOMEM; -	}  	if (data->pdata->input_name)  		input_dev->name = data->pdata->input_name; @@ -2419,11 +2633,16 @@ static int mxt_initialize_t100_input_device(struct mxt_data *data)  	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,  			     0, data->max_y, 0, 0); +	if (data->T107_address) { +		input_set_capability(input_dev, EV_KEY, BTN_STYLUS); +		input_set_capability(input_dev, EV_KEY, BTN_STYLUS2); +	} +  	if (data->t100_aux_area)  		input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,  				     0, MXT_MAX_AREA, 0, 0); -	if (data->t100_aux_ampl) +	if (data->t100_aux_ampl | data->stylus_aux_pressure)  		input_set_abs_params(input_dev, ABS_MT_PRESSURE,  				     0, 255, 0, 0); @@ -2743,132 +2962,98 @@ static int mxt_check_firmware_format(struct device *dev,  	return -EINVAL;  } -static int mxt_load_fw(struct device *dev) +static int mxt_enter_bootloader(struct mxt_data *data)  { -	struct mxt_data *data = dev_get_drvdata(dev); -	const struct firmware *fw = NULL; -	unsigned int frame_size; -	unsigned int pos = 0; -	unsigned int retry = 0; -	unsigned int frame = 0;  	int ret; -	ret = request_firmware(&fw, data->fw_name, dev); -	if (ret) { -		dev_err(dev, "Unable to open firmware %s\n", data->fw_name); -		return ret; -	} - -	/* Check for incorrect enc file */ -	ret = mxt_check_firmware_format(dev, fw); -	if (ret) -		goto release_firmware; -  	if (data->suspended) { -		if (data->use_regulator) +		if (data->pdata->suspend_mode == MXT_SUSPEND_REGULATOR)  			mxt_regulator_enable(data); -		enable_irq(data->irq);  		data->suspended = false;  	}  	if (!data->in_bootloader) {  		/* Change to the bootloader mode */ -		data->in_bootloader = true; -  		ret = mxt_t6_command(data, MXT_COMMAND_RESET,  				     MXT_BOOT_VALUE, false);  		if (ret) -			goto release_firmware; +			return ret;  		msleep(MXT_RESET_TIME);  		/* Do not need to scan since we know family ID */ -		ret = mxt_lookup_bootloader_address(data, 0); +		ret = mxt_probe_bootloader(data, 0);  		if (ret) -			goto release_firmware; +			return ret; +		data->in_bootloader = true;  		mxt_free_input_device(data);  		mxt_free_object_table(data); -	} else { -		enable_irq(data->irq);  	} -	INIT_COMPLETION(data->bl_completion); +	dev_dbg(&data->client->dev, "Entered bootloader\n"); -	ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); -	if (ret) { -		/* Bootloader may still be unlocked from previous attempt */ -		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false); -		if (ret) -			goto disable_irq; -	} else { -		dev_info(dev, "Unlocking bootloader\n"); +	return 0; +} -		/* Unlock bootloader */ -		ret = mxt_send_bootloader_cmd(data, true); -		if (ret) -			goto disable_irq; -	} +static void mxt_fw_work(struct work_struct *work) +{ +	struct mxt_flash *f = +		container_of(work, struct mxt_flash, work.work); -	while (pos < fw->size) { -		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true); -		if (ret) -			goto disable_irq; +	mxt_check_bootloader(f->data); +} -		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1)); +static int mxt_load_fw(struct device *dev) +{ +	struct mxt_data *data = dev_get_drvdata(dev); +	int ret; -		/* Take account of CRC bytes */ -		frame_size += 2; +	data->flash = devm_kzalloc(dev, sizeof(struct mxt_flash), GFP_KERNEL); +	if (!data->flash) +		return -ENOMEM; -		/* Write one frame to device */ -		ret = mxt_bootloader_write(data, fw->data + pos, frame_size); -		if (ret) -			goto disable_irq; +	data->flash->data = data; -		ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true); -		if (ret) { -			retry++; +	ret = request_firmware(&data->flash->fw, data->fw_name, dev); +	if (ret) { +		dev_err(dev, "Unable to open firmware %s\n", data->fw_name); +		goto free; +	} -			/* Back off by 20ms per retry */ -			msleep(retry * 20); +	/* Check for incorrect enc file */ +	ret = mxt_check_firmware_format(dev, data->flash->fw); +	if (ret) +		goto release_firmware; -			if (retry > 20) { -				dev_err(dev, "Retry count exceeded\n"); -				goto disable_irq; -			} -		} else { -			retry = 0; -			pos += frame_size; -			frame++; -		} +	init_completion(&data->flash->flash_completion); +	INIT_DELAYED_WORK(&data->flash->work, mxt_fw_work); -		if (frame % 50 == 0) -			dev_dbg(dev, "Sent %d frames, %d/%zd bytes\n", -				frame, pos, fw->size); +	if (!data->in_bootloader) { +		ret = mxt_enter_bootloader(data); +		if (ret) +			goto release_firmware;  	} -	/* Wait for flash. */ -	ret = mxt_wait_for_completion(data, &data->bl_completion, -				      MXT_FW_RESET_TIME); +	ret = mxt_acquire_irq(data);  	if (ret) -		goto disable_irq; +		goto release_firmware; -	dev_dbg(dev, "Sent %d frames, %d bytes\n", frame, pos); +	/* Poll after 0.1s if no interrupt received */ +	schedule_delayed_work(&data->flash->work, HZ / 10); -	/* -	 * Wait for device to reset. Some bootloader versions do not assert -	 * the CHG line after bootloading has finished, so ignore potential -	 * errors. -	 */ -	mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME); - -	data->in_bootloader = false; +	/* Wait for flash. */ +	ret = mxt_wait_for_completion(data, &data->flash->flash_completion, +				      MXT_BOOTLOADER_WAIT); -disable_irq:  	disable_irq(data->irq); +	cancel_delayed_work_sync(&data->flash->work); +	data->in_bootloader = false;  release_firmware: -	release_firmware(fw); +	release_firmware(data->flash->fw); +free: +	devm_kfree(dev, data->flash);  	return ret;  } @@ -2884,10 +3069,8 @@ static int mxt_update_file_name(struct device *dev, char **file_name,  	}  	file_name_tmp = krealloc(*file_name, count + 1, GFP_KERNEL); -	if (!file_name_tmp) { -		dev_warn(dev, "no memory\n"); +	if (!file_name_tmp)  		return -ENOMEM; -	}  	*file_name = file_name_tmp;  	memcpy(*file_name, buf, count); @@ -2934,6 +3117,7 @@ static ssize_t mxt_update_cfg_store(struct device *dev,  		const char *buf, size_t count)  {  	struct mxt_data *data = dev_get_drvdata(dev); +	const struct mxt_platform_data *pdata = data->pdata;  	const struct firmware *cfg;  	int ret; @@ -2959,10 +3143,10 @@ static ssize_t mxt_update_cfg_store(struct device *dev,  	mxt_free_input_device(data);  	if (data->suspended) { -		if (data->use_regulator) { +		if (pdata->suspend_mode == MXT_SUSPEND_REGULATOR) {  			enable_irq(data->irq);  			mxt_regulator_enable(data); -		} else { +		} else if (pdata->suspend_mode == MXT_SUSPEND_DEEP_SLEEP) {  			mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);  			mxt_acquire_irq(data);  		} @@ -3044,6 +3228,9 @@ static ssize_t mxt_debug_enable_store(struct device *dev,  static int mxt_check_mem_access_params(struct mxt_data *data, loff_t off,  				       size_t *count)  { +	if (data->in_bootloader) +		return -EINVAL; +  	if (off >= data->mem_size)  		return -EIO; @@ -3144,13 +3331,24 @@ static void mxt_start(struct mxt_data *data)  	if (!data->suspended || data->in_bootloader)  		return; -	if (data->use_regulator) { -		enable_irq(data->irq); +	switch (data->pdata->suspend_mode) { +	case MXT_SUSPEND_TOUCH_CTRL: +		mxt_soft_reset(data); + +		/* Touch enable */ +		mxt_write_object(data, +				MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); +		break; +	case MXT_SUSPEND_REGULATOR: +		enable_irq(data->irq);  		mxt_regulator_enable(data); -	} else { +		break; + +	case MXT_SUSPEND_DEEP_SLEEP: +	default:  		/* -		 * Discard any messages still in message buffer +		 * Discard any touch messages still in message buffer  		 * from before chip went to sleep  		 */  		mxt_process_messages_until_invalid(data); @@ -3161,6 +3359,7 @@ static void mxt_start(struct mxt_data *data)  		mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);  		mxt_acquire_irq(data); +		break;  	}  	data->suspended = false; @@ -3171,14 +3370,29 @@ static void mxt_stop(struct mxt_data *data)  	if (data->suspended || data->in_bootloader || data->updating_config)  		return; -	disable_irq(data->irq); +	switch (data->pdata->suspend_mode) { +	case MXT_SUSPEND_TOUCH_CTRL: +		/* Touch disable */ +		mxt_write_object(data, +				MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); +		break; -	if (data->use_regulator) +	case MXT_SUSPEND_REGULATOR: +		disable_irq(data->irq);  		mxt_regulator_disable(data); -	else +		mxt_reset_slots(data); +		break; + +	case MXT_SUSPEND_DEEP_SLEEP: +	default: +		disable_irq(data->irq); +  		mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); -	mxt_reset_slots(data); +		mxt_reset_slots(data); +		break; +	} +  	data->suspended = true;  } @@ -3244,6 +3458,9 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)  		pdata->t19_keymap = keymap;  	} +	of_property_read_u32(client->dev.of_node, "atmel,suspend-mode", +			     &pdata->suspend_mode); +  	return pdata;  }  #else @@ -3276,17 +3493,14 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)  	}  	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); -	if (!data) { -		dev_err(&client->dev, "Failed to allocate memory\n"); +	if (!data)  		return -ENOMEM; -	}  	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",  		 client->adapter->nr, client->addr);  	data->client = client;  	data->pdata = pdata; -	data->irq = client->irq;  	i2c_set_clientdata(client, data);  	if (data->pdata->cfg_name) @@ -3295,22 +3509,22 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)  				     data->pdata->cfg_name,  				     strlen(data->pdata->cfg_name)); -	init_completion(&data->bl_completion);  	init_completion(&data->reset_completion);  	init_completion(&data->crc_completion); +	init_completion(&data->chg_completion);  	mutex_init(&data->debug_msg_lock); -	error = request_threaded_irq(client->irq, NULL, mxt_interrupt, -				     pdata->irqflags | IRQF_ONESHOT, -				     client->name, data); -	if (error) { -		dev_err(&client->dev, "Failed to register interrupt\n"); -		goto err_free_mem; -	} +	if (pdata->suspend_mode == MXT_SUSPEND_REGULATOR) { +		error = mxt_acquire_irq(data); +		if (error) +			goto err_free_mem; -	mxt_probe_regulators(data); +		error = mxt_probe_regulators(data); +		if (error) +			goto err_free_irq; -	disable_irq(data->irq); +		disable_irq(data->irq); +	}  	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);  	if (error) { @@ -3345,7 +3559,8 @@ err_remove_mem_access:  err_remove_sysfs_group:  	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);  err_free_irq: -	free_irq(client->irq, data); +	if (data->irq) +		free_irq(data->irq, data);  err_free_mem:  	kfree(data);  	return error; @@ -3360,7 +3575,10 @@ static int mxt_remove(struct i2c_client *client)  				      &data->mem_access_attr);  	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); -	free_irq(data->irq, data); + +	if (data->irq) +		free_irq(data->irq, data); +  	regulator_put(data->reg_avdd);  	regulator_put(data->reg_vdd);  	mxt_free_input_device(data); @@ -3370,8 +3588,7 @@ static int mxt_remove(struct i2c_client *client)  	return 0;  } -#ifdef CONFIG_PM_SLEEP -static int mxt_suspend(struct device *dev) +static int __maybe_unused mxt_suspend(struct device *dev)  {  	struct i2c_client *client = to_i2c_client(dev);  	struct mxt_data *data = i2c_get_clientdata(client); @@ -3387,7 +3604,7 @@ static int mxt_suspend(struct device *dev)  	return 0;  } -static int mxt_resume(struct device *dev) +static int __maybe_unused mxt_resume(struct device *dev)  {  	struct i2c_client *client = to_i2c_client(dev);  	struct mxt_data *data = i2c_get_clientdata(client); @@ -3402,7 +3619,6 @@ static int mxt_resume(struct device *dev)  	return 0;  } -#endif  static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); diff --git a/include/dt-bindings/input/atmel_mxt_ts.h b/include/dt-bindings/input/atmel_mxt_ts.h new file mode 100644 index 00000000000..c7637925da5 --- /dev/null +++ b/include/dt-bindings/input/atmel_mxt_ts.h @@ -0,0 +1,22 @@ +/* + * Atmel maXTouch Touchscreen driver + * + * Copyright (C) 2015 Atmel Corporation + * Author: Nick Dyer <nick.dyer@itdev.co.uk> + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + */ + +#ifndef __DT_BINDINGS_ATMEL_MXT_TS_H +#define __DT_BINDINGS_ATMEL_MXT_TS_H + +enum mxt_suspend_mode { +	MXT_SUSPEND_DEEP_SLEEP = 0, +	MXT_SUSPEND_TOUCH_CTRL = 1, +	MXT_SUSPEND_REGULATOR = 2, +}; + +#endif /* __DT_BINDINGS_ATMEL_MXT_TS_H */ diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/platform_data/atmel_mxt_ts.h index bc74c3f4c86..be6fa95a661 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/platform_data/atmel_mxt_ts.h @@ -10,16 +10,18 @@   * option) any later version.   */ -#ifndef __LINUX_ATMEL_MXT_TS_H -#define __LINUX_ATMEL_MXT_TS_H +#ifndef __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H +#define __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H  #include <linux/types.h> +#include <dt-bindings/input/atmel_mxt_ts.h>  /* The platform data for the Atmel maXTouch touchscreen driver */  struct mxt_platform_data {  	unsigned long irqflags;  	u8 t19_num_keys;  	const unsigned int *t19_keymap; +	enum mxt_suspend_mode suspend_mode;  	int t15_num_keys;  	const unsigned int *t15_keymap;  	unsigned long gpio_reset; @@ -27,4 +29,4 @@ struct mxt_platform_data {  	const char *input_name;  }; -#endif /* __LINUX_ATMEL_MXT_TS_H */ +#endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */  |