• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Driver for cypress touch screen controller
4  *
5  * Copyright (c) 2009 Aava Mobile
6  *
7  * Some cleanups by Alan Cox <alan@linux.intel.com>
8  */
9 
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/input.h>
13 #include <linux/slab.h>
14 #include <linux/interrupt.h>
15 #include <linux/io.h>
16 #include <linux/i2c.h>
17 #include <linux/gpio.h>
18 #include <linux/input/cy8ctmg110_pdata.h>
19 
20 #define CY8CTMG110_DRIVER_NAME      "cy8ctmg110"
21 
22 /* Touch coordinates */
23 #define CY8CTMG110_X_MIN		0
24 #define CY8CTMG110_Y_MIN		0
25 #define CY8CTMG110_X_MAX		759
26 #define CY8CTMG110_Y_MAX		465
27 
28 
29 /* cy8ctmg110 register definitions */
30 #define CY8CTMG110_TOUCH_WAKEUP_TIME	0
31 #define CY8CTMG110_TOUCH_SLEEP_TIME	2
32 #define CY8CTMG110_TOUCH_X1		3
33 #define CY8CTMG110_TOUCH_Y1		5
34 #define CY8CTMG110_TOUCH_X2		7
35 #define CY8CTMG110_TOUCH_Y2		9
36 #define CY8CTMG110_FINGERS		11
37 #define CY8CTMG110_GESTURE		12
38 #define CY8CTMG110_REG_MAX		13
39 
40 
41 /*
42  * The touch driver structure.
43  */
44 struct cy8ctmg110 {
45 	struct input_dev *input;
46 	char phys[32];
47 	struct i2c_client *client;
48 	int reset_pin;
49 	int irq_pin;
50 };
51 
52 /*
53  * cy8ctmg110_power is the routine that is called when touch hardware
54  * will powered off or on.
55  */
cy8ctmg110_power(struct cy8ctmg110 * ts,bool poweron)56 static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
57 {
58 	if (ts->reset_pin)
59 		gpio_direction_output(ts->reset_pin, 1 - poweron);
60 }
61 
cy8ctmg110_write_regs(struct cy8ctmg110 * tsc,unsigned char reg,unsigned char len,unsigned char * value)62 static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
63 		unsigned char len, unsigned char *value)
64 {
65 	struct i2c_client *client = tsc->client;
66 	int ret;
67 	unsigned char i2c_data[6];
68 
69 	BUG_ON(len > 5);
70 
71 	i2c_data[0] = reg;
72 	memcpy(i2c_data + 1, value, len);
73 
74 	ret = i2c_master_send(client, i2c_data, len + 1);
75 	if (ret != len + 1) {
76 		dev_err(&client->dev, "i2c write data cmd failed\n");
77 		return ret < 0 ? ret : -EIO;
78 	}
79 
80 	return 0;
81 }
82 
cy8ctmg110_read_regs(struct cy8ctmg110 * tsc,unsigned char * data,unsigned char len,unsigned char cmd)83 static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc,
84 		unsigned char *data, unsigned char len, unsigned char cmd)
85 {
86 	struct i2c_client *client = tsc->client;
87 	int ret;
88 	struct i2c_msg msg[2] = {
89 		/* first write slave position to i2c devices */
90 		{
91 			.addr = client->addr,
92 			.len = 1,
93 			.buf = &cmd
94 		},
95 		/* Second read data from position */
96 		{
97 			.addr = client->addr,
98 			.flags = I2C_M_RD,
99 			.len = len,
100 			.buf = data
101 		}
102 	};
103 
104 	ret = i2c_transfer(client->adapter, msg, 2);
105 	if (ret < 0)
106 		return ret;
107 
108 	return 0;
109 }
110 
cy8ctmg110_touch_pos(struct cy8ctmg110 * tsc)111 static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
112 {
113 	struct input_dev *input = tsc->input;
114 	unsigned char reg_p[CY8CTMG110_REG_MAX];
115 	int x, y;
116 
117 	memset(reg_p, 0, CY8CTMG110_REG_MAX);
118 
119 	/* Reading coordinates */
120 	if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
121 		return -EIO;
122 
123 	y = reg_p[2] << 8 | reg_p[3];
124 	x = reg_p[0] << 8 | reg_p[1];
125 
126 	/* Number of touch */
127 	if (reg_p[8] == 0) {
128 		input_report_key(input, BTN_TOUCH, 0);
129 	} else  {
130 		input_report_key(input, BTN_TOUCH, 1);
131 		input_report_abs(input, ABS_X, x);
132 		input_report_abs(input, ABS_Y, y);
133 	}
134 
135 	input_sync(input);
136 
137 	return 0;
138 }
139 
cy8ctmg110_set_sleepmode(struct cy8ctmg110 * ts,bool sleep)140 static int cy8ctmg110_set_sleepmode(struct cy8ctmg110 *ts, bool sleep)
141 {
142 	unsigned char reg_p[3];
143 
144 	if (sleep) {
145 		reg_p[0] = 0x00;
146 		reg_p[1] = 0xff;
147 		reg_p[2] = 5;
148 	} else {
149 		reg_p[0] = 0x10;
150 		reg_p[1] = 0xff;
151 		reg_p[2] = 0;
152 	}
153 
154 	return cy8ctmg110_write_regs(ts, CY8CTMG110_TOUCH_WAKEUP_TIME, 3, reg_p);
155 }
156 
cy8ctmg110_irq_thread(int irq,void * dev_id)157 static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
158 {
159 	struct cy8ctmg110 *tsc = dev_id;
160 
161 	cy8ctmg110_touch_pos(tsc);
162 
163 	return IRQ_HANDLED;
164 }
165 
cy8ctmg110_probe(struct i2c_client * client,const struct i2c_device_id * id)166 static int cy8ctmg110_probe(struct i2c_client *client,
167 					const struct i2c_device_id *id)
168 {
169 	const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
170 	struct cy8ctmg110 *ts;
171 	struct input_dev *input_dev;
172 	int err;
173 
174 	/* No pdata no way forward */
175 	if (pdata == NULL) {
176 		dev_err(&client->dev, "no pdata\n");
177 		return -ENODEV;
178 	}
179 
180 	if (!i2c_check_functionality(client->adapter,
181 					I2C_FUNC_SMBUS_READ_WORD_DATA))
182 		return -EIO;
183 
184 	ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
185 	input_dev = input_allocate_device();
186 	if (!ts || !input_dev) {
187 		err = -ENOMEM;
188 		goto err_free_mem;
189 	}
190 
191 	ts->client = client;
192 	ts->input = input_dev;
193 	ts->reset_pin = pdata->reset_pin;
194 	ts->irq_pin = pdata->irq_pin;
195 
196 	snprintf(ts->phys, sizeof(ts->phys),
197 		 "%s/input0", dev_name(&client->dev));
198 
199 	input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
200 	input_dev->phys = ts->phys;
201 	input_dev->id.bustype = BUS_I2C;
202 	input_dev->dev.parent = &client->dev;
203 
204 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
205 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
206 
207 	input_set_abs_params(input_dev, ABS_X,
208 			CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
209 	input_set_abs_params(input_dev, ABS_Y,
210 			CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
211 
212 	if (ts->reset_pin) {
213 		err = gpio_request(ts->reset_pin, NULL);
214 		if (err) {
215 			dev_err(&client->dev,
216 				"Unable to request GPIO pin %d.\n",
217 				ts->reset_pin);
218 			goto err_free_mem;
219 		}
220 	}
221 
222 	cy8ctmg110_power(ts, true);
223 	cy8ctmg110_set_sleepmode(ts, false);
224 
225 	err = gpio_request(ts->irq_pin, "touch_irq_key");
226 	if (err < 0) {
227 		dev_err(&client->dev,
228 			"Failed to request GPIO %d, error %d\n",
229 			ts->irq_pin, err);
230 		goto err_shutoff_device;
231 	}
232 
233 	err = gpio_direction_input(ts->irq_pin);
234 	if (err < 0) {
235 		dev_err(&client->dev,
236 			"Failed to configure input direction for GPIO %d, error %d\n",
237 			ts->irq_pin, err);
238 		goto err_free_irq_gpio;
239 	}
240 
241 	client->irq = gpio_to_irq(ts->irq_pin);
242 	if (client->irq < 0) {
243 		err = client->irq;
244 		dev_err(&client->dev,
245 			"Unable to get irq number for GPIO %d, error %d\n",
246 			ts->irq_pin, err);
247 		goto err_free_irq_gpio;
248 	}
249 
250 	err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread,
251 				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
252 				   "touch_reset_key", ts);
253 	if (err < 0) {
254 		dev_err(&client->dev,
255 			"irq %d busy? error %d\n", client->irq, err);
256 		goto err_free_irq_gpio;
257 	}
258 
259 	err = input_register_device(input_dev);
260 	if (err)
261 		goto err_free_irq;
262 
263 	i2c_set_clientdata(client, ts);
264 	device_init_wakeup(&client->dev, 1);
265 	return 0;
266 
267 err_free_irq:
268 	free_irq(client->irq, ts);
269 err_free_irq_gpio:
270 	gpio_free(ts->irq_pin);
271 err_shutoff_device:
272 	cy8ctmg110_set_sleepmode(ts, true);
273 	cy8ctmg110_power(ts, false);
274 	if (ts->reset_pin)
275 		gpio_free(ts->reset_pin);
276 err_free_mem:
277 	input_free_device(input_dev);
278 	kfree(ts);
279 	return err;
280 }
281 
cy8ctmg110_suspend(struct device * dev)282 static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
283 {
284 	struct i2c_client *client = to_i2c_client(dev);
285 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
286 
287 	if (device_may_wakeup(&client->dev))
288 		enable_irq_wake(client->irq);
289 	else {
290 		cy8ctmg110_set_sleepmode(ts, true);
291 		cy8ctmg110_power(ts, false);
292 	}
293 	return 0;
294 }
295 
cy8ctmg110_resume(struct device * dev)296 static int __maybe_unused cy8ctmg110_resume(struct device *dev)
297 {
298 	struct i2c_client *client = to_i2c_client(dev);
299 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
300 
301 	if (device_may_wakeup(&client->dev))
302 		disable_irq_wake(client->irq);
303 	else {
304 		cy8ctmg110_power(ts, true);
305 		cy8ctmg110_set_sleepmode(ts, false);
306 	}
307 	return 0;
308 }
309 
310 static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
311 
cy8ctmg110_remove(struct i2c_client * client)312 static int cy8ctmg110_remove(struct i2c_client *client)
313 {
314 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
315 
316 	cy8ctmg110_set_sleepmode(ts, true);
317 	cy8ctmg110_power(ts, false);
318 
319 	free_irq(client->irq, ts);
320 	input_unregister_device(ts->input);
321 	gpio_free(ts->irq_pin);
322 	if (ts->reset_pin)
323 		gpio_free(ts->reset_pin);
324 	kfree(ts);
325 
326 	return 0;
327 }
328 
329 static const struct i2c_device_id cy8ctmg110_idtable[] = {
330 	{ CY8CTMG110_DRIVER_NAME, 1 },
331 	{ }
332 };
333 
334 MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable);
335 
336 static struct i2c_driver cy8ctmg110_driver = {
337 	.driver		= {
338 		.name	= CY8CTMG110_DRIVER_NAME,
339 		.pm	= &cy8ctmg110_pm,
340 	},
341 	.id_table	= cy8ctmg110_idtable,
342 	.probe		= cy8ctmg110_probe,
343 	.remove		= cy8ctmg110_remove,
344 };
345 
346 module_i2c_driver(cy8ctmg110_driver);
347 
348 MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>");
349 MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver");
350 MODULE_LICENSE("GPL v2");
351