xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/cyttsp5/cyttsp5_btn.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * cyttsp5_btn.c
3  * Parade TrueTouch(TM) Standard Product V5 CapSense Reports Module.
4  * For use with Parade touchscreen controllers.
5  * Supported parts include:
6  * CYTMA5XX
7  * CYTMA448
8  * CYTMA445A
9  * CYTT21XXX
10  * CYTT31XXX
11  *
12  * Copyright (C) 2015 Parade Technologies
13  * Copyright (C) 2012-2015 Cypress Semiconductor
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2, and only version 2, as published by the
18  * Free Software Foundation.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
26  *
27  */
28 
29 #include "cyttsp5_regs.h"
30 
31 #define CYTTSP5_BTN_NAME "cyttsp5_btn"
32 
cyttsp5_btn_key_action(struct cyttsp5_btn_data * bd,int btn_no,int btn_state)33 static inline void cyttsp5_btn_key_action(struct cyttsp5_btn_data *bd,
34 	int btn_no, int btn_state)
35 {
36 	struct device *dev = bd->dev;
37 	struct cyttsp5_sysinfo *si = bd->si;
38 
39 	if (!si->btn[btn_no].enabled ||
40 			si->btn[btn_no].state == btn_state)
41 		return;
42 
43 	si->btn[btn_no].state = btn_state;
44 	input_report_key(bd->input, si->btn[btn_no].key_code, btn_state);
45 	input_sync(bd->input);
46 
47 	parade_debug(dev, DEBUG_LEVEL_1, "%s: btn=%d key_code=%d %s\n",
48 		__func__, btn_no, si->btn[btn_no].key_code,
49 		btn_state == CY_BTN_PRESSED ?
50 			"PRESSED" : "RELEASED");
51 }
52 
cyttsp5_get_btn_touches(struct cyttsp5_btn_data * bd)53 static void cyttsp5_get_btn_touches(struct cyttsp5_btn_data *bd)
54 {
55 	struct cyttsp5_sysinfo *si = bd->si;
56 	int num_btns = si->num_btns;
57 	int cur_btn;
58 	int cur_btn_state;
59 
60 	for (cur_btn = 0; cur_btn < num_btns; cur_btn++) {
61 		/* Get current button state */
62 		cur_btn_state = (si->xy_data[0] >> (cur_btn * CY_BITS_PER_BTN))
63 				& CY_NUM_BTN_EVENT_ID;
64 
65 		cyttsp5_btn_key_action(bd, cur_btn, cur_btn_state);
66 	}
67 }
68 
cyttsp5_btn_lift_all(struct cyttsp5_btn_data * bd)69 static void cyttsp5_btn_lift_all(struct cyttsp5_btn_data *bd)
70 {
71 	struct cyttsp5_sysinfo *si = bd->si;
72 	int i;
73 
74 	if (!si || si->num_btns == 0)
75 		return;
76 
77 	for (i = 0; i < si->num_btns; i++)
78 		cyttsp5_btn_key_action(bd, i, CY_BTN_RELEASED);
79 }
80 
81 #ifdef VERBOSE_DEBUG
cyttsp5_log_btn_data(struct cyttsp5_btn_data * bd)82 static void cyttsp5_log_btn_data(struct cyttsp5_btn_data *bd)
83 {
84 	struct device *dev = bd->dev;
85 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
86 	u8 *pr_buf = cd->pr_buf;
87 	struct cyttsp5_sysinfo *si = bd->si;
88 	int cur;
89 	int value;
90 
91 	for (cur = 0; cur < si->num_btns; cur++) {
92 		pr_buf[0] = 0;
93 		if (si->xy_data[0] & (1 << cur))
94 			value = 1;
95 		else
96 			value = 0;
97 		snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "btn_rec[%d]=0x", cur);
98 		snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "%s%X (%02X)",
99 			pr_buf, value,
100 			le16_to_cpu(si->xy_data[1 + cur * 2]));
101 
102 		parade_debug(dev, DEBUG_LEVEL_2, "%s: %s\n", __func__, pr_buf);
103 	}
104 }
105 #endif
106 
107 /* read xy_data for all current CapSense button touches */
cyttsp5_xy_worker(struct cyttsp5_btn_data * bd)108 static int cyttsp5_xy_worker(struct cyttsp5_btn_data *bd)
109 {
110 	struct cyttsp5_sysinfo *si = bd->si;
111 
112 	/* extract button press/release touch information */
113 	if (si->num_btns > 0) {
114 		cyttsp5_get_btn_touches(bd);
115 #ifdef VERBOSE_DEBUG
116 		/* log button press/release touch information */
117 		cyttsp5_log_btn_data(bd);
118 #endif
119 	}
120 
121 	return 0;
122 }
123 
cyttsp5_btn_attention(struct device * dev)124 static int cyttsp5_btn_attention(struct device *dev)
125 {
126 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
127 	struct cyttsp5_btn_data *bd = &cd->bd;
128 	int rc;
129 
130 	if (bd->si->xy_mode[2] != bd->si->desc.btn_report_id)
131 		return 0;
132 
133 	/* core handles handshake */
134 	mutex_lock(&bd->btn_lock);
135 	rc = cyttsp5_xy_worker(bd);
136 	mutex_unlock(&bd->btn_lock);
137 	if (rc < 0)
138 		dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
139 
140 	return rc;
141 }
142 
cyttsp5_startup_attention(struct device * dev)143 static int cyttsp5_startup_attention(struct device *dev)
144 {
145 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
146 	struct cyttsp5_btn_data *bd = &cd->bd;
147 
148 	mutex_lock(&bd->btn_lock);
149 	cyttsp5_btn_lift_all(bd);
150 	mutex_unlock(&bd->btn_lock);
151 
152 	return 0;
153 }
154 
cyttsp5_btn_suspend_attention(struct device * dev)155 static int cyttsp5_btn_suspend_attention(struct device *dev)
156 {
157 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
158 	struct cyttsp5_btn_data *bd = &cd->bd;
159 
160 	mutex_lock(&bd->btn_lock);
161 	cyttsp5_btn_lift_all(bd);
162 	bd->is_suspended = true;
163 	mutex_unlock(&bd->btn_lock);
164 
165 	pm_runtime_put(dev);
166 
167 	return 0;
168 }
169 
cyttsp5_btn_resume_attention(struct device * dev)170 static int cyttsp5_btn_resume_attention(struct device *dev)
171 {
172 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
173 	struct cyttsp5_btn_data *bd = &cd->bd;
174 
175 	pm_runtime_get(dev);
176 
177 	mutex_lock(&bd->btn_lock);
178 	bd->is_suspended = false;
179 	mutex_unlock(&bd->btn_lock);
180 
181 	return 0;
182 }
183 
cyttsp5_btn_open(struct input_dev * input)184 static int cyttsp5_btn_open(struct input_dev *input)
185 {
186 	struct device *dev = input->dev.parent;
187 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
188 	struct cyttsp5_btn_data *bd = &cd->bd;
189 
190 	pm_runtime_get_sync(dev);
191 
192 	mutex_lock(&bd->btn_lock);
193 	bd->is_suspended = false;
194 	mutex_unlock(&bd->btn_lock);
195 
196 	parade_debug(dev, DEBUG_LEVEL_2, "%s: setup subscriptions\n", __func__);
197 
198 	/* set up touch call back */
199 	_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
200 		cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
201 
202 	/* set up startup call back */
203 	_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
204 		cyttsp5_startup_attention, 0);
205 
206 	/* set up suspend call back */
207 	_cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
208 		cyttsp5_btn_suspend_attention, 0);
209 
210 	/* set up resume call back */
211 	_cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
212 		cyttsp5_btn_resume_attention, 0);
213 
214 	return 0;
215 }
216 
cyttsp5_btn_close(struct input_dev * input)217 static void cyttsp5_btn_close(struct input_dev *input)
218 {
219 	struct device *dev = input->dev.parent;
220 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
221 	struct cyttsp5_btn_data *bd = &cd->bd;
222 
223 	_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
224 		cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
225 
226 	_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
227 		cyttsp5_startup_attention, 0);
228 
229 	_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
230 		cyttsp5_btn_suspend_attention, 0);
231 
232 	_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
233 		cyttsp5_btn_resume_attention, 0);
234 
235 	mutex_lock(&bd->btn_lock);
236 	if (!bd->is_suspended) {
237 		pm_runtime_put(dev);
238 		bd->is_suspended = true;
239 	}
240 	mutex_unlock(&bd->btn_lock);
241 }
242 
cyttsp5_setup_input_device(struct device * dev)243 static int cyttsp5_setup_input_device(struct device *dev)
244 {
245 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
246 	struct cyttsp5_btn_data *bd = &cd->bd;
247 	int i;
248 	int rc;
249 
250 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Initialize event signals\n",
251 		__func__);
252 	__set_bit(EV_KEY, bd->input->evbit);
253 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Number of buttons %d\n",
254 		__func__, bd->si->num_btns);
255 	for (i = 0; i < bd->si->num_btns; i++) {
256 		parade_debug(dev, DEBUG_LEVEL_2, "%s: btn:%d keycode:%d\n",
257 			__func__, i, bd->si->btn[i].key_code);
258 		__set_bit(bd->si->btn[i].key_code, bd->input->keybit);
259 	}
260 
261 	rc = input_register_device(bd->input);
262 	if (rc < 0)
263 		dev_err(dev, "%s: Error, failed register input device r=%d\n",
264 			__func__, rc);
265 	else
266 		bd->input_device_registered = true;
267 
268 	return rc;
269 }
270 
cyttsp5_setup_input_attention(struct device * dev)271 static int cyttsp5_setup_input_attention(struct device *dev)
272 {
273 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
274 	struct cyttsp5_btn_data *bd = &cd->bd;
275 	int rc;
276 
277 	bd->si = _cyttsp5_request_sysinfo(dev);
278 	if (!bd->si)
279 		return -1;
280 
281 	rc = cyttsp5_setup_input_device(dev);
282 
283 	_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
284 		cyttsp5_setup_input_attention, 0);
285 
286 	return rc;
287 }
288 
cyttsp5_btn_probe(struct device * dev)289 int cyttsp5_btn_probe(struct device *dev)
290 {
291 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
292 	struct cyttsp5_btn_data *bd = &cd->bd;
293 	struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
294 	struct cyttsp5_btn_platform_data *btn_pdata;
295 	int rc = 0;
296 
297 	if (!pdata || !pdata->btn_pdata) {
298 		dev_err(dev, "%s: Missing platform data\n", __func__);
299 		rc = -ENODEV;
300 		goto error_no_pdata;
301 	}
302 	btn_pdata = pdata->btn_pdata;
303 
304 	mutex_init(&bd->btn_lock);
305 	bd->dev = dev;
306 	bd->pdata = btn_pdata;
307 
308 	/* Create the input device and register it. */
309 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Create the input device and register it\n",
310 		__func__);
311 	bd->input = input_allocate_device();
312 	if (!bd->input) {
313 		dev_err(dev, "%s: Error, failed to allocate input device\n",
314 			__func__);
315 		rc = -ENODEV;
316 		goto error_alloc_failed;
317 	}
318 
319 	if (bd->pdata->inp_dev_name)
320 		bd->input->name = bd->pdata->inp_dev_name;
321 	else
322 		bd->input->name = CYTTSP5_BTN_NAME;
323 	scnprintf(bd->phys, sizeof(bd->phys), "%s/input%d", dev_name(dev),
324 			cd->phys_num++);
325 	bd->input->phys = bd->phys;
326 	bd->input->dev.parent = bd->dev;
327 	bd->input->open = cyttsp5_btn_open;
328 	bd->input->close = cyttsp5_btn_close;
329 	input_set_drvdata(bd->input, bd);
330 
331 	/* get sysinfo */
332 	bd->si = _cyttsp5_request_sysinfo(dev);
333 
334 	if (bd->si) {
335 		rc = cyttsp5_setup_input_device(dev);
336 		if (rc)
337 			goto error_init_input;
338 	} else {
339 		dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
340 			__func__, bd->si);
341 		_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
342 			CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
343 	}
344 
345 	return 0;
346 
347 error_init_input:
348 	input_free_device(bd->input);
349 error_alloc_failed:
350 error_no_pdata:
351 	dev_err(dev, "%s failed.\n", __func__);
352 	return rc;
353 }
354 
cyttsp5_btn_release(struct device * dev)355 int cyttsp5_btn_release(struct device *dev)
356 {
357 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
358 	struct cyttsp5_btn_data *bd = &cd->bd;
359 
360 	if (bd->input_device_registered) {
361 		input_unregister_device(bd->input);
362 	} else {
363 		input_free_device(bd->input);
364 		_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
365 			CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
366 	}
367 
368 	return 0;
369 }
370