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