History

Input: add Cypress TTSP capacitive multi-touch screen support

Cypress TrueTouch(tm) Standard Product controllers are found in a wide range of embedded devices. This driver add support for a variety of TTSP controllers. Since the hardware is capable of tracking identifiable contacts, multi-touch protocol type B (stateful) is used to report contact information. The driver is composed of a core driver that process the data sent by the contacts and a set of bus specific interface modules. This patch adds the base core TTSP driver.

Javier Martinez Canillas committed 14 years ago

Commit 4065d1e1 parent 31175a87 files · +1223 −2Browse files

Unified · Split

7 files
  1. drivers/input/touchscreen/Kconfig +31 −1
  2. drivers/input/touchscreen/Makefile +4 −1
  3. drivers/input/touchscreen/cyttsp_core.c +625 −0
  4. drivers/input/touchscreen/cyttsp_core.h +149 −0
  5. drivers/input/touchscreen/cyttsp_i2c.c +146 −0
  6. drivers/input/touchscreen/cyttsp_spi.c +210 −0
  7. include/linux/input/cyttsp.h +58 −0
drivers/input/touchscreen/Kconfig+31−1
@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110 · 138 unmodified lines
139139 tristate "cy8ctmg110 touchscreen"
140140 depends on I2C
141141 depends on GPIOLIB
142−
143142 help
144143 Say Y here if you have a cy8ctmg110 capacitive touchscreen on
145144 an AAVA device.
@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110 · 3 unmodified lines
149148 To compile this driver as a module, choose M here: the
150149 module will be called cy8ctmg110_ts.
151150
151+config TOUCHSCREEN_CYTTSP_CORE
152+ tristate "Cypress TTSP touchscreen"
153+ help
154+ Say Y here if you have a touchscreen using controller from
155+ the Cypress TrueTouch(tm) Standard Product family connected
156+ to your system. You will also need to select appropriate
157+ bus connection below.
158+
159+ If unsure, say N.
160+
161+ To compile this driver as a module, choose M here: the
162+ module will be called cyttsp_core.
163+
164+config TOUCHSCREEN_CYTTSP_I2C
165+ tristate "support I2C bus connection"
166+ depends on TOUCHSCREEN_CYTTSP_CORE && I2C
167+ help
168+ Say Y here if the touchscreen is connected via I2C bus.
169+
170+ To compile this driver as a module, choose M here: the
171+ module will be called cyttsp_i2c.
172+
173+config TOUCHSCREEN_CYTTSP_SPI
174+ tristate "support SPI bus connection"
175+ depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER
176+ help
177+ Say Y here if the touchscreen is connected via SPI bus.
178+
179+ To compile this driver as a module, choose M here: the
180+ module will be called cyttsp_spi.
181+
152182 config TOUCHSCREEN_DA9034
153183 tristate "Touchscreen support for Dialog Semiconductor DA9034"
154184 depends on PMIC_DA903X
drivers/input/touchscreen/Makefile+4−1
@@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o · 15 unmodified lines
1616 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
1717 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
1818 obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
19−obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
19+obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
2020 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
21+obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
22+obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o
23+obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
2124 obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
2225 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
2326 obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
drivers/input/touchscreen/cyttsp_core.c+625−0
@@ -0,0 +1,625 @@
1+/*
2+ * Core Source for:
3+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4+ * For use with Cypress Txx3xx parts.
5+ * Supported parts include:
6+ * CY8CTST341
7+ * CY8CTMA340
8+ *
9+ * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10+ * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11+ *
12+ * This program is free software; you can redistribute it and/or
13+ * modify it under the terms of the GNU General Public License
14+ * version 2, and only version 2, as published by the
15+ * Free Software Foundation.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License along
23+ * with this program; if not, write to the Free Software Foundation, Inc.,
24+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+ *
26+ * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27+ *
28+ */
29+
30+#include <linux/delay.h>
31+#include <linux/input.h>
32+#include <linux/input/mt.h>
33+#include <linux/gpio.h>
34+#include <linux/interrupt.h>
35+#include <linux/slab.h>
36+
37+#include "cyttsp_core.h"
38+
39+/* Bootloader number of command keys */
40+#define CY_NUM_BL_KEYS 8
41+
42+/* helpers */
43+#define GET_NUM_TOUCHES(x) ((x) & 0x0F)
44+#define IS_LARGE_AREA(x) (((x) & 0x10) >> 4)
45+#define IS_BAD_PKT(x) ((x) & 0x20)
46+#define IS_VALID_APP(x) ((x) & 0x01)
47+#define IS_OPERATIONAL_ERR(x) ((x) & 0x3F)
48+#define GET_HSTMODE(reg) (((reg) & 0x70) >> 4)
49+#define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4)
50+
51+#define CY_REG_BASE 0x00
52+#define CY_REG_ACT_DIST 0x1E
53+#define CY_REG_ACT_INTRVL 0x1D
54+#define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1)
55+#define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1)
56+#define CY_MAXZ 255
57+#define CY_DELAY_DFLT 20 /* ms */
58+#define CY_DELAY_MAX 500
59+#define CY_ACT_DIST_DFLT 0xF8
60+#define CY_HNDSHK_BIT 0x80
61+/* device mode bits */
62+#define CY_OPERATE_MODE 0x00
63+#define CY_SYSINFO_MODE 0x10
64+/* power mode select bits */
65+#define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */
66+#define CY_DEEP_SLEEP_MODE 0x02
67+#define CY_LOW_POWER_MODE 0x04
68+
69+/* Slots management */
70+#define CY_MAX_FINGER 4
71+#define CY_MAX_ID 16
72+
73+static const u8 bl_command[] = {
74+ 0x00, /* file offset */
75+ 0xFF, /* command */
76+ 0xA5, /* exit bootloader command */
77+ 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */
78+};
79+
80+static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
81+ u8 length, void *buf)
82+{
83+ int error;
84+ int tries;
85+
86+ for (tries = 0; tries < CY_NUM_RETRY; tries++) {
87+ error = ts->bus_ops->read(ts, command, length, buf);
88+ if (!error)
89+ return 0;
90+
91+ msleep(CY_DELAY_DFLT);
92+ }
93+
94+ return -EIO;
95+}
96+
97+static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
98+ u8 length, void *buf)
99+{
100+ int error;
101+ int tries;
102+
103+ for (tries = 0; tries < CY_NUM_RETRY; tries++) {
104+ error = ts->bus_ops->write(ts, command, length, buf);
105+ if (!error)
106+ return 0;
107+
108+ msleep(CY_DELAY_DFLT);
109+ }
110+
111+ return -EIO;
112+}
113+
114+static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
115+{
116+ return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
117+}
118+
119+static int cyttsp_load_bl_regs(struct cyttsp *ts)
120+{
121+ memset(&ts->bl_data, 0, sizeof(ts->bl_data));
122+ ts->bl_data.bl_status = 0x10;
123+
124+ return ttsp_read_block_data(ts, CY_REG_BASE,
125+ sizeof(ts->bl_data), &ts->bl_data);
126+}
127+
128+static int cyttsp_exit_bl_mode(struct cyttsp *ts)
129+{
130+ int error;
131+ u8 bl_cmd[sizeof(bl_command)];
132+
133+ memcpy(bl_cmd, bl_command, sizeof(bl_command));
134+ if (ts->pdata->bl_keys)
135+ memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
136+ ts->pdata->bl_keys, sizeof(bl_command));
137+
138+ error = ttsp_write_block_data(ts, CY_REG_BASE,
139+ sizeof(bl_cmd), bl_cmd);
140+ if (error)
141+ return error;
142+
143+ /* wait for TTSP Device to complete the operation */
144+ msleep(CY_DELAY_DFLT);
145+
146+ error = cyttsp_load_bl_regs(ts);
147+ if (error)
148+ return error;
149+
150+ if (GET_BOOTLOADERMODE(ts->bl_data.bl_status))
151+ return -EIO;
152+
153+ return 0;
154+}
155+
156+static int cyttsp_set_operational_mode(struct cyttsp *ts)
157+{
158+ int error;
159+
160+ error = ttsp_send_command(ts, CY_OPERATE_MODE);
161+ if (error)
162+ return error;
163+
164+ /* wait for TTSP Device to complete switch to Operational mode */
165+ error = ttsp_read_block_data(ts, CY_REG_BASE,
166+ sizeof(ts->xy_data), &ts->xy_data);
167+ if (error)
168+ return error;
169+
170+ return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
171+}
172+
173+static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
174+{
175+ int error;
176+
177+ memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data));
178+
179+ /* switch to sysinfo mode */
180+ error = ttsp_send_command(ts, CY_SYSINFO_MODE);
181+ if (error)
182+ return error;
183+
184+ /* read sysinfo registers */
185+ msleep(CY_DELAY_DFLT);
186+ error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
187+ &ts->sysinfo_data);
188+ if (error)
189+ return error;
190+
191+ if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
192+ return -EIO;
193+
194+ return 0;
195+}
196+
197+static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
198+{
199+ int retval = 0;
200+
201+ if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
202+ ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
203+ ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
204+
205+ u8 intrvl_ray[] = {
206+ ts->pdata->act_intrvl,
207+ ts->pdata->tch_tmout,
208+ ts->pdata->lp_intrvl
209+ };
210+
211+ /* set intrvl registers */
212+ retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL,
213+ sizeof(intrvl_ray), intrvl_ray);
214+ msleep(CY_DELAY_DFLT);
215+ }
216+
217+ return retval;
218+}
219+
220+static int cyttsp_soft_reset(struct cyttsp *ts)
221+{
222+ unsigned long timeout;
223+ int retval;
224+
225+ /* wait for interrupt to set ready completion */
226+ INIT_COMPLETION(ts->bl_ready);
227+ ts->state = CY_BL_STATE;
228+
229+ enable_irq(ts->irq);
230+
231+ retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
232+ if (retval)
233+ goto out;
234+
235+ timeout = wait_for_completion_timeout(&ts->bl_ready,
236+ msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));
237+ retval = timeout ? 0 : -EIO;
238+
239+out:
240+ ts->state = CY_IDLE_STATE;
241+ disable_irq(ts->irq);
242+ return retval;
243+}
244+
245+static int cyttsp_act_dist_setup(struct cyttsp *ts)
246+{
247+ u8 act_dist_setup = ts->pdata->act_dist;
248+
249+ /* Init gesture; active distance setup */
250+ return ttsp_write_block_data(ts, CY_REG_ACT_DIST,
251+ sizeof(act_dist_setup), &act_dist_setup);
252+}
253+
254+static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
255+{
256+ ids[0] = xy_data->touch12_id >> 4;
257+ ids[1] = xy_data->touch12_id & 0xF;
258+ ids[2] = xy_data->touch34_id >> 4;
259+ ids[3] = xy_data->touch34_id & 0xF;
260+}
261+
262+static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
263+ int idx)
264+{
265+ switch (idx) {
266+ case 0:
267+ return &xy_data->tch1;
268+ case 1:
269+ return &xy_data->tch2;
270+ case 2:
271+ return &xy_data->tch3;
272+ case 3:
273+ return &xy_data->tch4;
274+ default:
275+ return NULL;
276+ }
277+}
278+
279+static void cyttsp_report_tchdata(struct cyttsp *ts)
280+{
281+ struct cyttsp_xydata *xy_data = &ts->xy_data;
282+ struct input_dev *input = ts->input;
283+ int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat);
284+ const struct cyttsp_tch *tch;
285+ int ids[CY_MAX_ID];
286+ int i;
287+ DECLARE_BITMAP(used, CY_MAX_ID);
288+
289+ if (IS_LARGE_AREA(xy_data->tt_stat) == 1) {
290+ /* terminate all active tracks */
291+ num_tch = 0;
292+ dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
293+ } else if (num_tch > CY_MAX_FINGER) {
294+ /* terminate all active tracks */
295+ num_tch = 0;
296+ dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
297+ } else if (IS_BAD_PKT(xy_data->tt_mode)) {
298+ /* terminate all active tracks */
299+ num_tch = 0;
300+ dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
301+ }
302+
303+ cyttsp_extract_track_ids(xy_data, ids);
304+
305+ bitmap_zero(used, CY_MAX_ID);
306+
307+ for (i = 0; i < num_tch; i++) {
308+ tch = cyttsp_get_tch(xy_data, i);
309+
310+ input_mt_slot(input, ids[i]);
311+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
312+ input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x));
313+ input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y));
314+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z);
315+
316+ __set_bit(ids[i], used);
317+ }
318+
319+ for (i = 0; i < CY_MAX_ID; i++) {
320+ if (test_bit(i, used))
321+ continue;
322+
323+ input_mt_slot(input, i);
324+ input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
325+ }
326+
327+ input_sync(input);
328+}
329+
330+static irqreturn_t cyttsp_irq(int irq, void *handle)
331+{
332+ struct cyttsp *ts = handle;
333+ int error;
334+
335+ if (unlikely(ts->state == CY_BL_STATE)) {
336+ complete(&ts->bl_ready);
337+ goto out;
338+ }
339+
340+ /* Get touch data from CYTTSP device */
341+ error = ttsp_read_block_data(ts, CY_REG_BASE,
342+ sizeof(struct cyttsp_xydata), &ts->xy_data);
343+ if (error)
344+ goto out;
345+
346+ /* provide flow control handshake */
347+ if (ts->pdata->use_hndshk) {
348+ error = ttsp_send_command(ts,
349+ ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
350+ if (error)
351+ goto out;
352+ }
353+
354+ if (unlikely(ts->state == CY_IDLE_STATE))
355+ goto out;
356+
357+ if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
358+ /*
359+ * TTSP device has reset back to bootloader mode.
360+ * Restore to operational mode.
361+ */
362+ error = cyttsp_exit_bl_mode(ts);
363+ if (error) {
364+ dev_err(ts->dev,
365+ "Could not return to operational mode, err: %d\n",
366+ error);
367+ ts->state = CY_IDLE_STATE;
368+ }
369+ } else {
370+ cyttsp_report_tchdata(ts);
371+ }
372+
373+out:
374+ return IRQ_HANDLED;
375+}
376+
377+static int cyttsp_power_on(struct cyttsp *ts)
378+{
379+ int error;
380+
381+ error = cyttsp_soft_reset(ts);
382+ if (error)
383+ return error;
384+
385+ error = cyttsp_load_bl_regs(ts);
386+ if (error)
387+ return error;
388+
389+ if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
390+ IS_VALID_APP(ts->bl_data.bl_status)) {
391+ error = cyttsp_exit_bl_mode(ts);
392+ if (error)
393+ return error;
394+ }
395+
396+ if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
397+ IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
398+ return -ENODEV;
399+ }
400+
401+ error = cyttsp_set_sysinfo_mode(ts);
402+ if (error)
403+ return error;
404+
405+ error = cyttsp_set_sysinfo_regs(ts);
406+ if (error)
407+ return error;
408+
409+ error = cyttsp_set_operational_mode(ts);
410+ if (error)
411+ return error;
412+
413+ /* init active distance */
414+ error = cyttsp_act_dist_setup(ts);
415+ if (error)
416+ return error;
417+
418+ ts->state = CY_ACTIVE_STATE;
419+
420+ return 0;
421+}
422+
423+static int cyttsp_enable(struct cyttsp *ts)
424+{
425+ int error;
426+
427+ /*
428+ * The device firmware can wake on an I2C or SPI memory slave
429+ * address match. So just reading a register is sufficient to
430+ * wake up the device. The first read attempt will fail but it
431+ * will wake it up making the second read attempt successful.
432+ */
433+ error = ttsp_read_block_data(ts, CY_REG_BASE,
434+ sizeof(ts->xy_data), &ts->xy_data);
435+ if (error)
436+ return error;
437+
438+ if (GET_HSTMODE(ts->xy_data.hst_mode))
439+ return -EIO;
440+
441+ enable_irq(ts->irq);
442+
443+ return 0;
444+}
445+
446+static int cyttsp_disable(struct cyttsp *ts)
447+{
448+ int error;
449+
450+ error = ttsp_send_command(ts, CY_LOW_POWER_MODE);
451+ if (error)
452+ return error;
453+
454+ disable_irq(ts->irq);
455+
456+ return 0;
457+}
458+
459+#ifdef CONFIG_PM_SLEEP
460+static int cyttsp_suspend(struct device *dev)
461+{
462+ struct cyttsp *ts = dev_get_drvdata(dev);
463+ int retval = 0;
464+
465+ mutex_lock(&ts->input->mutex);
466+
467+ if (ts->input->users) {
468+ retval = cyttsp_disable(ts);
469+ if (retval == 0)
470+ ts->suspended = true;
471+ }
472+
473+ mutex_unlock(&ts->input->mutex);
474+
475+ return retval;
476+}
477+
478+static int cyttsp_resume(struct device *dev)
479+{
480+ struct cyttsp *ts = dev_get_drvdata(dev);
481+
482+ mutex_lock(&ts->input->mutex);
483+
484+ if (ts->input->users)
485+ cyttsp_enable(ts);
486+
487+ ts->suspended = false;
488+
489+ mutex_unlock(&ts->input->mutex);
490+
491+ return 0;
492+}
493+
494+#endif
495+
496+SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
497+EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
498+
499+static int cyttsp_open(struct input_dev *dev)
500+{
501+ struct cyttsp *ts = input_get_drvdata(dev);
502+ int retval = 0;
503+
504+ if (!ts->suspended)
505+ retval = cyttsp_enable(ts);
506+
507+ return retval;
508+}
509+
510+static void cyttsp_close(struct input_dev *dev)
511+{
512+ struct cyttsp *ts = input_get_drvdata(dev);
513+
514+ if (!ts->suspended)
515+ cyttsp_disable(ts);
516+}
517+
518+struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
519+ struct device *dev, int irq, size_t xfer_buf_size)
520+{
521+ const struct cyttsp_platform_data *pdata = dev->platform_data;
522+ struct cyttsp *ts;
523+ struct input_dev *input_dev;
524+ int error;
525+
526+ if (!dev || !bus_ops || !pdata || !pdata->name || irq <= 0) {
527+ error = -EINVAL;
528+ goto err_out;
529+ }
530+
531+ ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
532+ input_dev = input_allocate_device();
533+ if (!ts || !input_dev) {
534+ error = -ENOMEM;
535+ goto err_free_mem;
536+ }
537+
538+ ts->dev = dev;
539+ ts->input = input_dev;
540+ ts->pdata = dev->platform_data;
541+ ts->bus_ops = bus_ops;
542+ ts->irq = irq;
543+
544+ init_completion(&ts->bl_ready);
545+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
546+
547+ if (pdata->init) {
548+ error = pdata->init();
549+ if (error) {
550+ dev_err(ts->dev, "platform init failed, err: %d\n",
551+ error);
552+ goto err_free_mem;
553+ }
554+ }
555+
556+ input_dev->name = pdata->name;
557+ input_dev->phys = ts->phys;
558+ input_dev->id.bustype = bus_ops->bustype;
559+ input_dev->dev.parent = ts->dev;
560+
561+ input_dev->open = cyttsp_open;
562+ input_dev->close = cyttsp_close;
563+
564+ input_set_drvdata(input_dev, ts);
565+
566+ __set_bit(EV_ABS, input_dev->evbit);
567+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
568+ 0, pdata->maxx, 0, 0);
569+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
570+ 0, pdata->maxy, 0, 0);
571+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
572+ 0, CY_MAXZ, 0, 0);
573+
574+ input_mt_init_slots(input_dev, CY_MAX_ID);
575+
576+ error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
577+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
578+ pdata->name, ts);
579+ if (error) {
580+ dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
581+ ts->irq, error);
582+ goto err_platform_exit;
583+ }
584+
585+ disable_irq(ts->irq);
586+
587+ error = cyttsp_power_on(ts);
588+ if (error)
589+ goto err_free_irq;
590+
591+ error = input_register_device(input_dev);
592+ if (error) {
593+ dev_err(ts->dev, "failed to register input device: %d\n",
594+ error);
595+ goto err_free_irq;
596+ }
597+
598+ return ts;
599+
600+err_free_irq:
601+ free_irq(ts->irq, ts);
602+err_platform_exit:
603+ if (pdata->exit)
604+ pdata->exit();
605+err_free_mem:
606+ input_free_device(input_dev);
607+ kfree(ts);
608+err_out:
609+ return ERR_PTR(error);
610+}
611+EXPORT_SYMBOL_GPL(cyttsp_probe);
612+
613+void cyttsp_remove(struct cyttsp *ts)
614+{
615+ free_irq(ts->irq, ts);
616+ input_unregister_device(ts->input);
617+ if (ts->pdata->exit)
618+ ts->pdata->exit();
619+ kfree(ts);
620+}
621+EXPORT_SYMBOL_GPL(cyttsp_remove);
622+
623+MODULE_LICENSE("GPL");
624+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
625+MODULE_AUTHOR("Cypress");
drivers/input/touchscreen/cyttsp_core.h+149−0
@@ -0,0 +1,149 @@
1+/*
2+ * Header file for:
3+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4+ * For use with Cypress Txx3xx parts.
5+ * Supported parts include:
6+ * CY8CTST341
7+ * CY8CTMA340
8+ *
9+ * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10+ * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11+ *
12+ * This program is free software; you can redistribute it and/or
13+ * modify it under the terms of the GNU General Public License
14+ * version 2, and only version 2, as published by the
15+ * Free Software Foundation.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License along
23+ * with this program; if not, write to the Free Software Foundation, Inc.,
24+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+ *
26+ * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27+ *
28+ */
29+
30+
31+#ifndef __CYTTSP_CORE_H__
32+#define __CYTTSP_CORE_H__
33+
34+#include <linux/kernel.h>
35+#include <linux/err.h>
36+#include <linux/module.h>
37+#include <linux/types.h>
38+#include <linux/device.h>
39+#include <linux/input/cyttsp.h>
40+
41+#define CY_NUM_RETRY 16 /* max number of retries for read ops */
42+
43+struct cyttsp_tch {
44+ __be16 x, y;
45+ u8 z;
46+} __packed;
47+
48+/* TrueTouch Standard Product Gen3 interface definition */
49+struct cyttsp_xydata {
50+ u8 hst_mode;
51+ u8 tt_mode;
52+ u8 tt_stat;
53+ struct cyttsp_tch tch1;
54+ u8 touch12_id;
55+ struct cyttsp_tch tch2;
56+ u8 gest_cnt;
57+ u8 gest_id;
58+ struct cyttsp_tch tch3;
59+ u8 touch34_id;
60+ struct cyttsp_tch tch4;
61+ u8 tt_undef[3];
62+ u8 act_dist;
63+ u8 tt_reserved;
64+} __packed;
65+
66+
67+/* TTSP System Information interface definition */
68+struct cyttsp_sysinfo_data {
69+ u8 hst_mode;
70+ u8 mfg_cmd;
71+ u8 mfg_stat;
72+ u8 cid[3];
73+ u8 tt_undef1;
74+ u8 uid[8];
75+ u8 bl_verh;
76+ u8 bl_verl;
77+ u8 tts_verh;
78+ u8 tts_verl;
79+ u8 app_idh;
80+ u8 app_idl;
81+ u8 app_verh;
82+ u8 app_verl;
83+ u8 tt_undef[5];
84+ u8 scn_typ;
85+ u8 act_intrvl;
86+ u8 tch_tmout;
87+ u8 lp_intrvl;
88+};
89+
90+/* TTSP Bootloader Register Map interface definition */
91+#define CY_BL_CHKSUM_OK 0x01
92+struct cyttsp_bootloader_data {
93+ u8 bl_file;
94+ u8 bl_status;
95+ u8 bl_error;
96+ u8 blver_hi;
97+ u8 blver_lo;
98+ u8 bld_blver_hi;
99+ u8 bld_blver_lo;
100+ u8 ttspver_hi;
101+ u8 ttspver_lo;
102+ u8 appid_hi;
103+ u8 appid_lo;
104+ u8 appver_hi;
105+ u8 appver_lo;
106+ u8 cid_0;
107+ u8 cid_1;
108+ u8 cid_2;
109+};
110+
111+struct cyttsp;
112+
113+struct cyttsp_bus_ops {
114+ u16 bustype;
115+ int (*write)(struct cyttsp *ts,
116+ u8 addr, u8 length, const void *values);
117+ int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values);
118+};
119+
120+enum cyttsp_state {
121+ CY_IDLE_STATE,
122+ CY_ACTIVE_STATE,
123+ CY_BL_STATE,
124+};
125+
126+struct cyttsp {
127+ struct device *dev;
128+ int irq;
129+ struct input_dev *input;
130+ char phys[32];
131+ const struct cyttsp_platform_data *pdata;
132+ const struct cyttsp_bus_ops *bus_ops;
133+ struct cyttsp_bootloader_data bl_data;
134+ struct cyttsp_sysinfo_data sysinfo_data;
135+ struct cyttsp_xydata xy_data;
136+ struct completion bl_ready;
137+ enum cyttsp_state state;
138+ bool suspended;
139+
140+ u8 xfer_buf[] ____cacheline_aligned;
141+};
142+
143+struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
144+ struct device *dev, int irq, size_t xfer_buf_size);
145+void cyttsp_remove(struct cyttsp *ts);
146+
147+extern const struct dev_pm_ops cyttsp_pm_ops;
148+
149+#endif /* __CYTTSP_CORE_H__ */
drivers/input/touchscreen/cyttsp_i2c.c+146−0
@@ -0,0 +1,146 @@
1+/*
2+ * Source for:
3+ * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
4+ * For use with Cypress Txx3xx parts.
5+ * Supported parts include:
6+ * CY8CTST341
7+ * CY8CTMA340
8+ *
9+ * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10+ * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11+ *
12+ * This program is free software; you can redistribute it and/or
13+ * modify it under the terms of the GNU General Public License
14+ * version 2, and only version 2, as published by the
15+ * Free Software Foundation.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License along
23+ * with this program; if not, write to the Free Software Foundation, Inc.,
24+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+ *
26+ * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27+ *
28+ */
29+
30+#include "cyttsp_core.h"
31+
32+#include <linux/i2c.h>
33+#include <linux/input.h>
34+
35+#define CY_I2C_DATA_SIZE 128
36+
37+static int cyttsp_i2c_read_block_data(struct cyttsp *ts,
38+ u8 addr, u8 length, void *values)
39+{
40+ struct i2c_client *client = to_i2c_client(ts->dev);
41+ struct i2c_msg msgs[] = {
42+ {
43+ .addr = client->addr,
44+ .flags = 0,
45+ .len = 1,
46+ .buf = &addr,
47+ },
48+ {
49+ .addr = client->addr,
50+ .flags = I2C_M_RD,
51+ .len = length,
52+ .buf = values,
53+ },
54+ };
55+ int retval;
56+
57+ retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
58+ if (retval < 0)
59+ return retval;
60+
61+ return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
62+}
63+
64+static int cyttsp_i2c_write_block_data(struct cyttsp *ts,
65+ u8 addr, u8 length, const void *values)
66+{
67+ struct i2c_client *client = to_i2c_client(ts->dev);
68+ int retval;
69+
70+ ts->xfer_buf[0] = addr;
71+ memcpy(&ts->xfer_buf[1], values, length);
72+
73+ retval = i2c_master_send(client, ts->xfer_buf, length + 1);
74+
75+ return retval < 0 ? retval : 0;
76+}
77+
78+static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
79+ .bustype = BUS_I2C,
80+ .write = cyttsp_i2c_write_block_data,
81+ .read = cyttsp_i2c_read_block_data,
82+};
83+
84+static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
85+ const struct i2c_device_id *id)
86+{
87+ struct cyttsp *ts;
88+
89+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
90+ dev_err(&client->dev, "I2C functionality not Supported\n");
91+ return -EIO;
92+ }
93+
94+ ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
95+ CY_I2C_DATA_SIZE);
96+
97+ if (IS_ERR(ts))
98+ return PTR_ERR(ts);
99+
100+ i2c_set_clientdata(client, ts);
101+
102+ return 0;
103+}
104+
105+static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
106+{
107+ struct cyttsp *ts = i2c_get_clientdata(client);
108+
109+ cyttsp_remove(ts);
110+
111+ return 0;
112+}
113+
114+static const struct i2c_device_id cyttsp_i2c_id[] = {
115+ { CY_I2C_NAME, 0 },
116+ { }
117+};
118+MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
119+
120+static struct i2c_driver cyttsp_i2c_driver = {
121+ .driver = {
122+ .name = CY_I2C_NAME,
123+ .owner = THIS_MODULE,
124+ .pm = &cyttsp_pm_ops,
125+ },
126+ .probe = cyttsp_i2c_probe,
127+ .remove = __devexit_p(cyttsp_i2c_remove),
128+ .id_table = cyttsp_i2c_id,
129+};
130+
131+static int __init cyttsp_i2c_init(void)
132+{
133+ return i2c_add_driver(&cyttsp_i2c_driver);
134+}
135+module_init(cyttsp_i2c_init);
136+
137+static void __exit cyttsp_i2c_exit(void)
138+{
139+ return i2c_del_driver(&cyttsp_i2c_driver);
140+}
141+module_exit(cyttsp_i2c_exit);
142+
143+MODULE_LICENSE("GPL");
144+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
145+MODULE_AUTHOR("Cypress");
146+MODULE_ALIAS("i2c:cyttsp");
drivers/input/touchscreen/cyttsp_spi.c+210−0
@@ -0,0 +1,210 @@
1+/*
2+ * Source for:
3+ * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
4+ * For use with Cypress Txx3xx parts.
5+ * Supported parts include:
6+ * CY8CTST341
7+ * CY8CTMA340
8+ *
9+ * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10+ * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11+ *
12+ * This program is free software; you can redistribute it and/or
13+ * modify it under the terms of the GNU General Public License
14+ * version 2, and only version 2, as published by the
15+ * Free Software Foundation.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License along
23+ * with this program; if not, write to the Free Software Foundation, Inc.,
24+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+ *
26+ * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27+ *
28+ */
29+
30+#include "cyttsp_core.h"
31+
32+#include <linux/delay.h>
33+#include <linux/input.h>
34+#include <linux/spi/spi.h>
35+
36+#define CY_SPI_WR_OP 0x00 /* r/~w */
37+#define CY_SPI_RD_OP 0x01
38+#define CY_SPI_CMD_BYTES 4
39+#define CY_SPI_SYNC_BYTE 2
40+#define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */
41+#define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */
42+#define CY_SPI_DATA_SIZE 128
43+#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
44+#define CY_SPI_BITS_PER_WORD 8
45+
46+static int cyttsp_spi_xfer(struct cyttsp *ts,
47+ u8 op, u8 reg, u8 *buf, int length)
48+{
49+ struct spi_device *spi = to_spi_device(ts->dev);
50+ struct spi_message msg;
51+ struct spi_transfer xfer[2];
52+ u8 *wr_buf = &ts->xfer_buf[0];
53+ u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE];
54+ int retval;
55+ int i;
56+
57+ if (length > CY_SPI_DATA_SIZE) {
58+ dev_err(ts->dev, "%s: length %d is too big.\n",
59+ __func__, length);
60+ return -EINVAL;
61+ }
62+
63+ memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
64+ memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE);
65+
66+ wr_buf[0] = 0x00; /* header byte 0 */
67+ wr_buf[1] = 0xFF; /* header byte 1 */
68+ wr_buf[2] = reg; /* reg index */
69+ wr_buf[3] = op; /* r/~w */
70+ if (op == CY_SPI_WR_OP)
71+ memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
72+
73+ memset(xfer, 0, sizeof(xfer));
74+ spi_message_init(&msg);
75+
76+ /*
77+ We set both TX and RX buffers because Cypress TTSP
78+ requires full duplex operation.
79+ */
80+ xfer[0].tx_buf = wr_buf;
81+ xfer[0].rx_buf = rd_buf;
82+ switch (op) {
83+ case CY_SPI_WR_OP:
84+ xfer[0].len = length + CY_SPI_CMD_BYTES;
85+ spi_message_add_tail(&xfer[0], &msg);
86+ break;
87+
88+ case CY_SPI_RD_OP:
89+ xfer[0].len = CY_SPI_CMD_BYTES;
90+ spi_message_add_tail(&xfer[0], &msg);
91+
92+ xfer[1].rx_buf = buf;
93+ xfer[1].len = length;
94+ spi_message_add_tail(&xfer[1], &msg);
95+ break;
96+
97+ default:
98+ dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op);
99+ return -EINVAL;
100+ }
101+
102+ retval = spi_sync(spi, &msg);
103+ if (retval < 0) {
104+ dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
105+ __func__, retval, xfer[1].len, op);
106+
107+ /*
108+ * do not return here since was a bad ACK sequence
109+ * let the following ACK check handle any errors and
110+ * allow silent retries
111+ */
112+ }
113+
114+ if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 ||
115+ rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
116+
117+ dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op);
118+
119+ for (i = 0; i < CY_SPI_CMD_BYTES; i++)
120+ dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n",
121+ __func__, i, rd_buf[i]);
122+ for (i = 0; i < length; i++)
123+ dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n",
124+ __func__, i, buf[i]);
125+
126+ return -EIO;
127+ }
128+
129+ return 0;
130+}
131+
132+static int cyttsp_spi_read_block_data(struct cyttsp *ts,
133+ u8 addr, u8 length, void *data)
134+{
135+ return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length);
136+}
137+
138+static int cyttsp_spi_write_block_data(struct cyttsp *ts,
139+ u8 addr, u8 length, const void *data)
140+{
141+ return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length);
142+}
143+
144+static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
145+ .bustype = BUS_SPI,
146+ .write = cyttsp_spi_write_block_data,
147+ .read = cyttsp_spi_read_block_data,
148+};
149+
150+static int __devinit cyttsp_spi_probe(struct spi_device *spi)
151+{
152+ struct cyttsp *ts;
153+ int error;
154+
155+ /* Set up SPI*/
156+ spi->bits_per_word = CY_SPI_BITS_PER_WORD;
157+ spi->mode = SPI_MODE_0;
158+ error = spi_setup(spi);
159+ if (error < 0) {
160+ dev_err(&spi->dev, "%s: SPI setup error %d\n",
161+ __func__, error);
162+ return error;
163+ }
164+
165+ ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
166+ CY_SPI_DATA_BUF_SIZE * 2);
167+ if (IS_ERR(ts))
168+ return PTR_ERR(ts);
169+
170+ spi_set_drvdata(spi, ts);
171+
172+ return 0;
173+}
174+
175+static int __devexit cyttsp_spi_remove(struct spi_device *spi)
176+{
177+ struct cyttsp *ts = spi_get_drvdata(spi);
178+
179+ cyttsp_remove(ts);
180+
181+ return 0;
182+}
183+
184+static struct spi_driver cyttsp_spi_driver = {
185+ .driver = {
186+ .name = CY_SPI_NAME,
187+ .owner = THIS_MODULE,
188+ .pm = &cyttsp_pm_ops,
189+ },
190+ .probe = cyttsp_spi_probe,
191+ .remove = __devexit_p(cyttsp_spi_remove),
192+};
193+
194+static int __init cyttsp_spi_init(void)
195+{
196+ return spi_register_driver(&cyttsp_spi_driver);
197+}
198+module_init(cyttsp_spi_init);
199+
200+static void __exit cyttsp_spi_exit(void)
201+{
202+ spi_unregister_driver(&cyttsp_spi_driver);
203+}
204+module_exit(cyttsp_spi_exit);
205+
206+MODULE_ALIAS("spi:cyttsp");
207+MODULE_LICENSE("GPL");
208+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
209+MODULE_AUTHOR("Cypress");
210+MODULE_ALIAS("spi:cyttsp");
include/linux/input/cyttsp.h+58−0
@@ -0,0 +1,58 @@
1+/*
2+ * Header file for:
3+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4+ * For use with Cypress Txx3xx parts.
5+ * Supported parts include:
6+ * CY8CTST341
7+ * CY8CTMA340
8+ *
9+ * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10+ * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11+ *
12+ * This program is free software; you can redistribute it and/or
13+ * modify it under the terms of the GNU General Public License
14+ * version 2, and only version 2, as published by the
15+ * Free Software Foundation.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License along
23+ * with this program; if not, write to the Free Software Foundation, Inc.,
24+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+ *
26+ * Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com)
27+ *
28+ */
29+#ifndef _CYTTSP_H_
30+#define _CYTTSP_H_
31+
32+#define CY_SPI_NAME "cyttsp-spi"
33+#define CY_I2C_NAME "cyttsp-i2c"
34+/* Active Power state scanning/processing refresh interval */
35+#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
36+/* touch timeout for the Active power */
37+#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
38+/* Low Power state scanning/processing refresh interval */
39+#define CY_LP_INTRVL_DFLT 0x0A /* ms */
40+/* Active distance in pixels for a gesture to be reported */
41+#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
42+
43+struct cyttsp_platform_data {
44+ u32 maxx;
45+ u32 maxy;
46+ bool use_hndshk;
47+ u8 act_dist; /* Active distance */
48+ u8 act_intrvl; /* Active refresh interval; ms */
49+ u8 tch_tmout; /* Active touch timeout; ms */
50+ u8 lp_intrvl; /* Low power refresh interval; ms */
51+ int (*init)(void);
52+ void (*exit)(void);
53+ char *name;
54+ s16 irq_gpio;
55+ u8 *bl_keys;
56+};
57+
58+#endif /* _CYTTSP_H_ */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t