14feacbc2SBenjamin Tissoires /*
24feacbc2SBenjamin Tissoires  *  Driver for Ntrig/Microsoft Touchscreens over SPI
34feacbc2SBenjamin Tissoires  *
44feacbc2SBenjamin Tissoires  *  Copyright (c) 2016 Red Hat Inc.
54feacbc2SBenjamin Tissoires  */
64feacbc2SBenjamin Tissoires 
74feacbc2SBenjamin Tissoires /*
84feacbc2SBenjamin Tissoires  * This program is free software; you can redistribute it and/or modify it
94feacbc2SBenjamin Tissoires  * under the terms of the GNU General Public License as published by the Free
104feacbc2SBenjamin Tissoires  * Software Foundation; version 2 of the License.
114feacbc2SBenjamin Tissoires  */
124feacbc2SBenjamin Tissoires 
134feacbc2SBenjamin Tissoires #include <linux/kernel.h>
144feacbc2SBenjamin Tissoires 
154feacbc2SBenjamin Tissoires #include <linux/delay.h>
164feacbc2SBenjamin Tissoires #include <linux/gpio/consumer.h>
174feacbc2SBenjamin Tissoires #include <linux/input.h>
184feacbc2SBenjamin Tissoires #include <linux/input/mt.h>
194feacbc2SBenjamin Tissoires #include <linux/interrupt.h>
204feacbc2SBenjamin Tissoires #include <linux/module.h>
214feacbc2SBenjamin Tissoires #include <linux/slab.h>
224feacbc2SBenjamin Tissoires #include <linux/spi/spi.h>
234feacbc2SBenjamin Tissoires #include <linux/acpi.h>
244feacbc2SBenjamin Tissoires 
254feacbc2SBenjamin Tissoires #include <asm/unaligned.h>
264feacbc2SBenjamin Tissoires 
274feacbc2SBenjamin Tissoires #define SURFACE3_PACKET_SIZE	264
284feacbc2SBenjamin Tissoires 
29427ee206SStephen Just #define SURFACE3_REPORT_TOUCH	0xd2
30*72fb4765SStephen Just #define SURFACE3_REPORT_PEN	0x16
31427ee206SStephen Just 
324feacbc2SBenjamin Tissoires struct surface3_ts_data {
334feacbc2SBenjamin Tissoires 	struct spi_device *spi;
344feacbc2SBenjamin Tissoires 	struct gpio_desc *gpiod_rst[2];
354feacbc2SBenjamin Tissoires 	struct input_dev *input_dev;
36*72fb4765SStephen Just 	struct input_dev *pen_input_dev;
37*72fb4765SStephen Just 	int pen_tool;
384feacbc2SBenjamin Tissoires 
394feacbc2SBenjamin Tissoires 	u8 rd_buf[SURFACE3_PACKET_SIZE]		____cacheline_aligned;
404feacbc2SBenjamin Tissoires };
414feacbc2SBenjamin Tissoires 
424feacbc2SBenjamin Tissoires struct surface3_ts_data_finger {
434feacbc2SBenjamin Tissoires 	u8 status;
444feacbc2SBenjamin Tissoires 	__le16 tracking_id;
454feacbc2SBenjamin Tissoires 	__le16 x;
464feacbc2SBenjamin Tissoires 	__le16 cx;
474feacbc2SBenjamin Tissoires 	__le16 y;
484feacbc2SBenjamin Tissoires 	__le16 cy;
494feacbc2SBenjamin Tissoires 	__le16 width;
504feacbc2SBenjamin Tissoires 	__le16 height;
514feacbc2SBenjamin Tissoires 	u32 padding;
524feacbc2SBenjamin Tissoires } __packed;
534feacbc2SBenjamin Tissoires 
54*72fb4765SStephen Just struct surface3_ts_data_pen {
55*72fb4765SStephen Just 	u8 status;
56*72fb4765SStephen Just 	__le16 x;
57*72fb4765SStephen Just 	__le16 y;
58*72fb4765SStephen Just 	__le16 pressure;
59*72fb4765SStephen Just 	u8 padding;
60*72fb4765SStephen Just } __packed;
61*72fb4765SStephen Just 
624feacbc2SBenjamin Tissoires static int surface3_spi_read(struct surface3_ts_data *ts_data)
634feacbc2SBenjamin Tissoires {
644feacbc2SBenjamin Tissoires 	struct spi_device *spi = ts_data->spi;
654feacbc2SBenjamin Tissoires 
664feacbc2SBenjamin Tissoires 	memset(ts_data->rd_buf, 0, sizeof(ts_data->rd_buf));
674feacbc2SBenjamin Tissoires 	return spi_read(spi, ts_data->rd_buf, sizeof(ts_data->rd_buf));
684feacbc2SBenjamin Tissoires }
694feacbc2SBenjamin Tissoires 
704feacbc2SBenjamin Tissoires static void surface3_spi_report_touch(struct surface3_ts_data *ts_data,
714feacbc2SBenjamin Tissoires 				   struct surface3_ts_data_finger *finger)
724feacbc2SBenjamin Tissoires {
734feacbc2SBenjamin Tissoires 	int st = finger->status & 0x01;
744feacbc2SBenjamin Tissoires 	int slot;
754feacbc2SBenjamin Tissoires 
764feacbc2SBenjamin Tissoires 	slot = input_mt_get_slot_by_key(ts_data->input_dev,
774feacbc2SBenjamin Tissoires 				get_unaligned_le16(&finger->tracking_id));
784feacbc2SBenjamin Tissoires 	if (slot < 0)
794feacbc2SBenjamin Tissoires 		return;
804feacbc2SBenjamin Tissoires 
814feacbc2SBenjamin Tissoires 	input_mt_slot(ts_data->input_dev, slot);
824feacbc2SBenjamin Tissoires 	input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, st);
834feacbc2SBenjamin Tissoires 	if (st) {
844feacbc2SBenjamin Tissoires 		input_report_abs(ts_data->input_dev,
854feacbc2SBenjamin Tissoires 				 ABS_MT_POSITION_X,
864feacbc2SBenjamin Tissoires 				 get_unaligned_le16(&finger->x));
874feacbc2SBenjamin Tissoires 		input_report_abs(ts_data->input_dev,
884feacbc2SBenjamin Tissoires 				 ABS_MT_POSITION_Y,
894feacbc2SBenjamin Tissoires 				 get_unaligned_le16(&finger->y));
904feacbc2SBenjamin Tissoires 		input_report_abs(ts_data->input_dev,
914feacbc2SBenjamin Tissoires 				 ABS_MT_WIDTH_MAJOR,
924feacbc2SBenjamin Tissoires 				 get_unaligned_le16(&finger->width));
934feacbc2SBenjamin Tissoires 		input_report_abs(ts_data->input_dev,
944feacbc2SBenjamin Tissoires 				 ABS_MT_WIDTH_MINOR,
954feacbc2SBenjamin Tissoires 				 get_unaligned_le16(&finger->height));
964feacbc2SBenjamin Tissoires 	}
974feacbc2SBenjamin Tissoires }
984feacbc2SBenjamin Tissoires 
99427ee206SStephen Just static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data)
1004feacbc2SBenjamin Tissoires {
1014feacbc2SBenjamin Tissoires 	u16 timestamp;
1024feacbc2SBenjamin Tissoires 	unsigned int i;
1034feacbc2SBenjamin Tissoires 	timestamp = get_unaligned_le16(&data[15]);
1044feacbc2SBenjamin Tissoires 
1054feacbc2SBenjamin Tissoires 	for (i = 0; i < 13; i++) {
1064feacbc2SBenjamin Tissoires 		struct surface3_ts_data_finger *finger;
1074feacbc2SBenjamin Tissoires 
1084feacbc2SBenjamin Tissoires 		finger = (struct surface3_ts_data_finger *)&data[17 +
1094feacbc2SBenjamin Tissoires 				i * sizeof(struct surface3_ts_data_finger)];
1104feacbc2SBenjamin Tissoires 
1114feacbc2SBenjamin Tissoires 		/*
1124feacbc2SBenjamin Tissoires 		 * When bit 5 of status is 1, it marks the end of the report:
1134feacbc2SBenjamin Tissoires 		 * - touch present: 0xe7
1144feacbc2SBenjamin Tissoires 		 * - touch released: 0xe4
1154feacbc2SBenjamin Tissoires 		 * - nothing valuable: 0xff
1164feacbc2SBenjamin Tissoires 		 */
1174feacbc2SBenjamin Tissoires 		if (finger->status & 0x10)
1184feacbc2SBenjamin Tissoires 			break;
1194feacbc2SBenjamin Tissoires 
1204feacbc2SBenjamin Tissoires 		surface3_spi_report_touch(ts_data, finger);
1214feacbc2SBenjamin Tissoires 	}
1224feacbc2SBenjamin Tissoires 
1234feacbc2SBenjamin Tissoires 	input_mt_sync_frame(ts_data->input_dev);
1244feacbc2SBenjamin Tissoires 	input_sync(ts_data->input_dev);
1254feacbc2SBenjamin Tissoires }
1264feacbc2SBenjamin Tissoires 
127*72fb4765SStephen Just static void surface3_spi_report_pen(struct surface3_ts_data *ts_data,
128*72fb4765SStephen Just 				    struct surface3_ts_data_pen *pen)
129*72fb4765SStephen Just {
130*72fb4765SStephen Just 	struct input_dev *dev = ts_data->pen_input_dev;
131*72fb4765SStephen Just 	int st = pen->status;
132*72fb4765SStephen Just 	int prox = st & 0x01;
133*72fb4765SStephen Just 	int rubber = st & 0x18;
134*72fb4765SStephen Just 	int tool = (prox && rubber) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
135*72fb4765SStephen Just 
136*72fb4765SStephen Just 	/* fake proximity out to switch tools */
137*72fb4765SStephen Just 	if (ts_data->pen_tool != tool) {
138*72fb4765SStephen Just 		input_report_key(dev, ts_data->pen_tool, 0);
139*72fb4765SStephen Just 		input_sync(dev);
140*72fb4765SStephen Just 		ts_data->pen_tool = tool;
141*72fb4765SStephen Just 	}
142*72fb4765SStephen Just 
143*72fb4765SStephen Just 	input_report_key(dev, BTN_TOUCH, st & 0x12);
144*72fb4765SStephen Just 
145*72fb4765SStephen Just 	input_report_key(dev, ts_data->pen_tool, prox);
146*72fb4765SStephen Just 
147*72fb4765SStephen Just 	if (st) {
148*72fb4765SStephen Just 		input_report_key(dev,
149*72fb4765SStephen Just 				 BTN_STYLUS,
150*72fb4765SStephen Just 				 st & 0x04);
151*72fb4765SStephen Just 
152*72fb4765SStephen Just 		input_report_abs(dev,
153*72fb4765SStephen Just 				 ABS_X,
154*72fb4765SStephen Just 				 get_unaligned_le16(&pen->x));
155*72fb4765SStephen Just 		input_report_abs(dev,
156*72fb4765SStephen Just 				 ABS_Y,
157*72fb4765SStephen Just 				 get_unaligned_le16(&pen->y));
158*72fb4765SStephen Just 		input_report_abs(dev,
159*72fb4765SStephen Just 				 ABS_PRESSURE,
160*72fb4765SStephen Just 				 get_unaligned_le16(&pen->pressure));
161*72fb4765SStephen Just 	}
162*72fb4765SStephen Just }
163*72fb4765SStephen Just 
164*72fb4765SStephen Just static void surface3_spi_process_pen(struct surface3_ts_data *ts_data, u8 *data)
165*72fb4765SStephen Just {
166*72fb4765SStephen Just 	struct surface3_ts_data_pen *pen;
167*72fb4765SStephen Just 
168*72fb4765SStephen Just 	pen = (struct surface3_ts_data_pen *)&data[15];
169*72fb4765SStephen Just 
170*72fb4765SStephen Just 	surface3_spi_report_pen(ts_data, pen);
171*72fb4765SStephen Just 	input_sync(ts_data->pen_input_dev);
172*72fb4765SStephen Just }
173*72fb4765SStephen Just 
174427ee206SStephen Just static void surface3_spi_process(struct surface3_ts_data *ts_data)
175427ee206SStephen Just {
176427ee206SStephen Just 	const char header[] = {
177427ee206SStephen Just 		0xff, 0xff, 0xff, 0xff, 0xa5, 0x5a, 0xe7, 0x7e, 0x01
178427ee206SStephen Just 	};
179427ee206SStephen Just 	u8 *data = ts_data->rd_buf;
180427ee206SStephen Just 
181427ee206SStephen Just 	if (memcmp(header, data, sizeof(header)))
182427ee206SStephen Just 		dev_err(&ts_data->spi->dev,
183427ee206SStephen Just 			"%s header error: %*ph, ignoring...\n",
184427ee206SStephen Just 			__func__, (int)sizeof(header), data);
185427ee206SStephen Just 
186*72fb4765SStephen Just 	switch (data[9]) {
187*72fb4765SStephen Just 	case SURFACE3_REPORT_TOUCH:
188427ee206SStephen Just 		surface3_spi_process_touch(ts_data, data);
189*72fb4765SStephen Just 		break;
190*72fb4765SStephen Just 	case SURFACE3_REPORT_PEN:
191*72fb4765SStephen Just 		surface3_spi_process_pen(ts_data, data);
192*72fb4765SStephen Just 		break;
193*72fb4765SStephen Just 	default:
194427ee206SStephen Just 		dev_err(&ts_data->spi->dev,
195427ee206SStephen Just 			"%s unknown packet type: %x, ignoring...\n",
196427ee206SStephen Just 			__func__, data[9]);
197*72fb4765SStephen Just 		break;
198*72fb4765SStephen Just 	}
199427ee206SStephen Just }
200427ee206SStephen Just 
2014feacbc2SBenjamin Tissoires static irqreturn_t surface3_spi_irq_handler(int irq, void *dev_id)
2024feacbc2SBenjamin Tissoires {
2034feacbc2SBenjamin Tissoires 	struct surface3_ts_data *data = dev_id;
2044feacbc2SBenjamin Tissoires 
2054feacbc2SBenjamin Tissoires 	if (surface3_spi_read(data))
2064feacbc2SBenjamin Tissoires 		return IRQ_HANDLED;
2074feacbc2SBenjamin Tissoires 
2084feacbc2SBenjamin Tissoires 	dev_dbg(&data->spi->dev, "%s received -> %*ph\n",
2094feacbc2SBenjamin Tissoires 		__func__, SURFACE3_PACKET_SIZE, data->rd_buf);
2104feacbc2SBenjamin Tissoires 	surface3_spi_process(data);
2114feacbc2SBenjamin Tissoires 
2124feacbc2SBenjamin Tissoires 	return IRQ_HANDLED;
2134feacbc2SBenjamin Tissoires }
2144feacbc2SBenjamin Tissoires 
2154feacbc2SBenjamin Tissoires static void surface3_spi_power(struct surface3_ts_data *data, bool on)
2164feacbc2SBenjamin Tissoires {
2174feacbc2SBenjamin Tissoires 	gpiod_set_value(data->gpiod_rst[0], on);
2184feacbc2SBenjamin Tissoires 	gpiod_set_value(data->gpiod_rst[1], on);
2194feacbc2SBenjamin Tissoires 	/* let the device settle a little */
2204feacbc2SBenjamin Tissoires 	msleep(20);
2214feacbc2SBenjamin Tissoires }
2224feacbc2SBenjamin Tissoires 
2234feacbc2SBenjamin Tissoires /**
2244feacbc2SBenjamin Tissoires  * surface3_spi_get_gpio_config - Get GPIO config from ACPI/DT
2254feacbc2SBenjamin Tissoires  *
2264feacbc2SBenjamin Tissoires  * @ts: surface3_spi_ts_data pointer
2274feacbc2SBenjamin Tissoires  */
2284feacbc2SBenjamin Tissoires static int surface3_spi_get_gpio_config(struct surface3_ts_data *data)
2294feacbc2SBenjamin Tissoires {
2304feacbc2SBenjamin Tissoires 	int error;
2314feacbc2SBenjamin Tissoires 	struct device *dev;
2324feacbc2SBenjamin Tissoires 	struct gpio_desc *gpiod;
2334feacbc2SBenjamin Tissoires 	int i;
2344feacbc2SBenjamin Tissoires 
2354feacbc2SBenjamin Tissoires 	dev = &data->spi->dev;
2364feacbc2SBenjamin Tissoires 
2374feacbc2SBenjamin Tissoires 	/* Get the reset lines GPIO pin number */
2384feacbc2SBenjamin Tissoires 	for (i = 0; i < 2; i++) {
2394feacbc2SBenjamin Tissoires 		gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_OUT_LOW);
2404feacbc2SBenjamin Tissoires 		if (IS_ERR(gpiod)) {
2414feacbc2SBenjamin Tissoires 			error = PTR_ERR(gpiod);
2424feacbc2SBenjamin Tissoires 			if (error != -EPROBE_DEFER)
2434feacbc2SBenjamin Tissoires 				dev_err(dev,
2444feacbc2SBenjamin Tissoires 					"Failed to get power GPIO %d: %d\n",
2454feacbc2SBenjamin Tissoires 					i,
2464feacbc2SBenjamin Tissoires 					error);
2474feacbc2SBenjamin Tissoires 			return error;
2484feacbc2SBenjamin Tissoires 		}
2494feacbc2SBenjamin Tissoires 
2504feacbc2SBenjamin Tissoires 		data->gpiod_rst[i] = gpiod;
2514feacbc2SBenjamin Tissoires 	}
2524feacbc2SBenjamin Tissoires 
2534feacbc2SBenjamin Tissoires 	return 0;
2544feacbc2SBenjamin Tissoires }
2554feacbc2SBenjamin Tissoires 
256427ee206SStephen Just static int surface3_spi_create_touch_input(struct surface3_ts_data *data)
2574feacbc2SBenjamin Tissoires {
2584feacbc2SBenjamin Tissoires 	struct input_dev *input;
2594feacbc2SBenjamin Tissoires 	int error;
2604feacbc2SBenjamin Tissoires 
2614feacbc2SBenjamin Tissoires 	input = devm_input_allocate_device(&data->spi->dev);
2624feacbc2SBenjamin Tissoires 	if (!input)
2634feacbc2SBenjamin Tissoires 		return -ENOMEM;
2644feacbc2SBenjamin Tissoires 
2654feacbc2SBenjamin Tissoires 	data->input_dev = input;
2664feacbc2SBenjamin Tissoires 
2674feacbc2SBenjamin Tissoires 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, 9600, 0, 0);
2684feacbc2SBenjamin Tissoires 	input_abs_set_res(input, ABS_MT_POSITION_X, 40);
2694feacbc2SBenjamin Tissoires 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 7200, 0, 0);
2704feacbc2SBenjamin Tissoires 	input_abs_set_res(input, ABS_MT_POSITION_Y, 48);
2714feacbc2SBenjamin Tissoires 	input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 1024, 0, 0);
2724feacbc2SBenjamin Tissoires 	input_set_abs_params(input, ABS_MT_WIDTH_MINOR, 0, 1024, 0, 0);
2734feacbc2SBenjamin Tissoires 	input_mt_init_slots(input, 10, INPUT_MT_DIRECT);
2744feacbc2SBenjamin Tissoires 
2754feacbc2SBenjamin Tissoires 	input->name = "Surface3 SPI Capacitive TouchScreen";
2764feacbc2SBenjamin Tissoires 	input->phys = "input/ts";
2774feacbc2SBenjamin Tissoires 	input->id.bustype = BUS_SPI;
2784feacbc2SBenjamin Tissoires 	input->id.vendor = 0x045e;	/* Microsoft */
279427ee206SStephen Just 	input->id.product = 0x0001;
2804feacbc2SBenjamin Tissoires 	input->id.version = 0x0000;
2814feacbc2SBenjamin Tissoires 
2824feacbc2SBenjamin Tissoires 	error = input_register_device(input);
2834feacbc2SBenjamin Tissoires 	if (error) {
2844feacbc2SBenjamin Tissoires 		dev_err(&data->spi->dev,
2854feacbc2SBenjamin Tissoires 			"Failed to register input device: %d", error);
2864feacbc2SBenjamin Tissoires 		return error;
2874feacbc2SBenjamin Tissoires 	}
2884feacbc2SBenjamin Tissoires 
2894feacbc2SBenjamin Tissoires 	return 0;
2904feacbc2SBenjamin Tissoires }
2914feacbc2SBenjamin Tissoires 
292*72fb4765SStephen Just static int surface3_spi_create_pen_input(struct surface3_ts_data *data)
293*72fb4765SStephen Just {
294*72fb4765SStephen Just 	struct input_dev *input;
295*72fb4765SStephen Just 	int error;
296*72fb4765SStephen Just 
297*72fb4765SStephen Just 	input = devm_input_allocate_device(&data->spi->dev);
298*72fb4765SStephen Just 	if (!input)
299*72fb4765SStephen Just 		return -ENOMEM;
300*72fb4765SStephen Just 
301*72fb4765SStephen Just 	data->pen_input_dev = input;
302*72fb4765SStephen Just 	data->pen_tool = BTN_TOOL_PEN;
303*72fb4765SStephen Just 
304*72fb4765SStephen Just 	__set_bit(INPUT_PROP_DIRECT, input->propbit);
305*72fb4765SStephen Just 	__set_bit(INPUT_PROP_POINTER, input->propbit);
306*72fb4765SStephen Just 	input_set_abs_params(input, ABS_X, 0, 9600, 0, 0);
307*72fb4765SStephen Just 	input_abs_set_res(input, ABS_X, 40);
308*72fb4765SStephen Just 	input_set_abs_params(input, ABS_Y, 0, 7200, 0, 0);
309*72fb4765SStephen Just 	input_abs_set_res(input, ABS_Y, 48);
310*72fb4765SStephen Just 	input_set_abs_params(input, ABS_PRESSURE, 0, 1024, 0, 0);
311*72fb4765SStephen Just 	input_set_capability(input, EV_KEY, BTN_TOUCH);
312*72fb4765SStephen Just 	input_set_capability(input, EV_KEY, BTN_STYLUS);
313*72fb4765SStephen Just 	input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
314*72fb4765SStephen Just 	input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
315*72fb4765SStephen Just 
316*72fb4765SStephen Just 	input->name = "Surface3 SPI Pen Input";
317*72fb4765SStephen Just 	input->phys = "input/ts";
318*72fb4765SStephen Just 	input->id.bustype = BUS_SPI;
319*72fb4765SStephen Just 	input->id.vendor = 0x045e;     /* Microsoft */
320*72fb4765SStephen Just 	input->id.product = 0x0002;
321*72fb4765SStephen Just 	input->id.version = 0x0000;
322*72fb4765SStephen Just 
323*72fb4765SStephen Just 	error = input_register_device(input);
324*72fb4765SStephen Just 	if (error) {
325*72fb4765SStephen Just 		dev_err(&data->spi->dev,
326*72fb4765SStephen Just 			"Failed to register input device: %d", error);
327*72fb4765SStephen Just 		return error;
328*72fb4765SStephen Just 	}
329*72fb4765SStephen Just 
330*72fb4765SStephen Just 	return 0;
331*72fb4765SStephen Just }
332*72fb4765SStephen Just 
3334feacbc2SBenjamin Tissoires static int surface3_spi_probe(struct spi_device *spi)
3344feacbc2SBenjamin Tissoires {
3354feacbc2SBenjamin Tissoires 	struct surface3_ts_data *data;
3364feacbc2SBenjamin Tissoires 	int error;
3374feacbc2SBenjamin Tissoires 
3384feacbc2SBenjamin Tissoires 	/* Set up SPI*/
3394feacbc2SBenjamin Tissoires 	spi->bits_per_word = 8;
3404feacbc2SBenjamin Tissoires 	spi->mode = SPI_MODE_0;
3414feacbc2SBenjamin Tissoires 	error = spi_setup(spi);
3424feacbc2SBenjamin Tissoires 	if (error)
3434feacbc2SBenjamin Tissoires 		return error;
3444feacbc2SBenjamin Tissoires 
3454feacbc2SBenjamin Tissoires 	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
3464feacbc2SBenjamin Tissoires 	if (!data)
3474feacbc2SBenjamin Tissoires 		return -ENOMEM;
3484feacbc2SBenjamin Tissoires 
3494feacbc2SBenjamin Tissoires 	data->spi = spi;
3504feacbc2SBenjamin Tissoires 	spi_set_drvdata(spi, data);
3514feacbc2SBenjamin Tissoires 
3524feacbc2SBenjamin Tissoires 	error = surface3_spi_get_gpio_config(data);
3534feacbc2SBenjamin Tissoires 	if (error)
3544feacbc2SBenjamin Tissoires 		return error;
3554feacbc2SBenjamin Tissoires 
3564feacbc2SBenjamin Tissoires 	surface3_spi_power(data, true);
3574feacbc2SBenjamin Tissoires 	surface3_spi_power(data, false);
3584feacbc2SBenjamin Tissoires 	surface3_spi_power(data, true);
3594feacbc2SBenjamin Tissoires 
360427ee206SStephen Just 	error = surface3_spi_create_touch_input(data);
3614feacbc2SBenjamin Tissoires 	if (error)
3624feacbc2SBenjamin Tissoires 		return error;
3634feacbc2SBenjamin Tissoires 
364*72fb4765SStephen Just 	error = surface3_spi_create_pen_input(data);
365*72fb4765SStephen Just 	if (error)
366*72fb4765SStephen Just 		return error;
367*72fb4765SStephen Just 
3684feacbc2SBenjamin Tissoires 	error = devm_request_threaded_irq(&spi->dev, spi->irq,
3694feacbc2SBenjamin Tissoires 					  NULL, surface3_spi_irq_handler,
3704feacbc2SBenjamin Tissoires 					  IRQF_ONESHOT,
3714feacbc2SBenjamin Tissoires 					  "Surface3-irq", data);
3724feacbc2SBenjamin Tissoires 	if (error)
3734feacbc2SBenjamin Tissoires 		return error;
3744feacbc2SBenjamin Tissoires 
3754feacbc2SBenjamin Tissoires 	return 0;
3764feacbc2SBenjamin Tissoires }
3774feacbc2SBenjamin Tissoires 
3784feacbc2SBenjamin Tissoires static int __maybe_unused surface3_spi_suspend(struct device *dev)
3794feacbc2SBenjamin Tissoires {
3804feacbc2SBenjamin Tissoires 	struct spi_device *spi = to_spi_device(dev);
3814feacbc2SBenjamin Tissoires 	struct surface3_ts_data *data = spi_get_drvdata(spi);
3824feacbc2SBenjamin Tissoires 
3834feacbc2SBenjamin Tissoires 	disable_irq(data->spi->irq);
3844feacbc2SBenjamin Tissoires 
3854feacbc2SBenjamin Tissoires 	surface3_spi_power(data, false);
3864feacbc2SBenjamin Tissoires 
3874feacbc2SBenjamin Tissoires 	return 0;
3884feacbc2SBenjamin Tissoires }
3894feacbc2SBenjamin Tissoires 
3904feacbc2SBenjamin Tissoires static int __maybe_unused surface3_spi_resume(struct device *dev)
3914feacbc2SBenjamin Tissoires {
3924feacbc2SBenjamin Tissoires 	struct spi_device *spi = to_spi_device(dev);
3934feacbc2SBenjamin Tissoires 	struct surface3_ts_data *data = spi_get_drvdata(spi);
3944feacbc2SBenjamin Tissoires 
3954feacbc2SBenjamin Tissoires 	surface3_spi_power(data, true);
3964feacbc2SBenjamin Tissoires 
3974feacbc2SBenjamin Tissoires 	enable_irq(data->spi->irq);
3984feacbc2SBenjamin Tissoires 
3994feacbc2SBenjamin Tissoires 	return 0;
4004feacbc2SBenjamin Tissoires }
4014feacbc2SBenjamin Tissoires 
4024feacbc2SBenjamin Tissoires static SIMPLE_DEV_PM_OPS(surface3_spi_pm_ops,
4034feacbc2SBenjamin Tissoires 			 surface3_spi_suspend,
4044feacbc2SBenjamin Tissoires 			 surface3_spi_resume);
4054feacbc2SBenjamin Tissoires 
4064feacbc2SBenjamin Tissoires #ifdef CONFIG_ACPI
4074feacbc2SBenjamin Tissoires static const struct acpi_device_id surface3_spi_acpi_match[] = {
4084feacbc2SBenjamin Tissoires 	{ "MSHW0037", 0 },
4094feacbc2SBenjamin Tissoires 	{ }
4104feacbc2SBenjamin Tissoires };
4114feacbc2SBenjamin Tissoires MODULE_DEVICE_TABLE(acpi, surface3_spi_acpi_match);
4124feacbc2SBenjamin Tissoires #endif
4134feacbc2SBenjamin Tissoires 
4144feacbc2SBenjamin Tissoires static struct spi_driver surface3_spi_driver = {
4154feacbc2SBenjamin Tissoires 	.driver = {
4164feacbc2SBenjamin Tissoires 		.name	= "Surface3-spi",
4174feacbc2SBenjamin Tissoires 		.acpi_match_table = ACPI_PTR(surface3_spi_acpi_match),
4184feacbc2SBenjamin Tissoires 		.pm = &surface3_spi_pm_ops,
4194feacbc2SBenjamin Tissoires 	},
4204feacbc2SBenjamin Tissoires 	.probe = surface3_spi_probe,
4214feacbc2SBenjamin Tissoires };
4224feacbc2SBenjamin Tissoires 
4234feacbc2SBenjamin Tissoires module_spi_driver(surface3_spi_driver);
4244feacbc2SBenjamin Tissoires 
4254feacbc2SBenjamin Tissoires MODULE_AUTHOR("Benjamin Tissoires <[email protected]>");
4264feacbc2SBenjamin Tissoires MODULE_DESCRIPTION("Surface 3 SPI touchscreen driver");
4274feacbc2SBenjamin Tissoires MODULE_LICENSE("GPL v2");
428