diff options
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 30 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 5 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_core.c | 2174 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_core.h | 448 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_i2c.c | 72 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_spi.c | 187 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp_core.h | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp_i2c.c | 55 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp_i2c_common.c | 86 |
9 files changed, 56 insertions, 3005 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0df90c3d743b..1ac26fc2e3eb 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -254,36 +254,6 @@ config TOUCHSCREEN_CYTTSP_SPI To compile this driver as a module, choose M here: the module will be called cyttsp_spi. -config TOUCHSCREEN_CYTTSP4_CORE - tristate "Cypress TrueTouch Gen4 Touchscreen Driver" - help - Core driver for Cypress TrueTouch(tm) Standard Product - Generation4 touchscreen controllers. - - Say Y here if you have a Cypress Gen4 touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here. - -config TOUCHSCREEN_CYTTSP4_I2C - tristate "support I2C bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && I2C - help - Say Y here if the touchscreen is connected via I2C bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_i2c. - -config TOUCHSCREEN_CYTTSP4_SPI - tristate "support SPI bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER - help - Say Y here if the touchscreen is connected via SPI bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_spi. - config TOUCHSCREEN_CYTTSP5 tristate "Cypress TrueTouch Gen5 Touchscreen Driver" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 04dc8039341b..82bc837ca01e 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -25,11 +25,8 @@ obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o +obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c deleted file mode 100644 index 7cb26929dc73..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ /dev/null @@ -1,2174 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp4_core.c - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/input/mt.h> -#include <linux/interrupt.h> -#include <linux/pm_runtime.h> -#include <linux/sched.h> -#include <linux/slab.h> - -/* Timeout in ms. */ -#define CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT 500 -#define CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT 5000 -#define CY_CORE_MODE_CHANGE_TIMEOUT 1000 -#define CY_CORE_RESET_AND_WAIT_TIMEOUT 500 -#define CY_CORE_WAKEUP_TIMEOUT 500 - -#define CY_CORE_STARTUP_RETRY_COUNT 3 - -static const char * const cyttsp4_tch_abs_string[] = { - [CY_TCH_X] = "X", - [CY_TCH_Y] = "Y", - [CY_TCH_P] = "P", - [CY_TCH_T] = "T", - [CY_TCH_E] = "E", - [CY_TCH_O] = "O", - [CY_TCH_W] = "W", - [CY_TCH_MAJ] = "MAJ", - [CY_TCH_MIN] = "MIN", - [CY_TCH_OR] = "OR", - [CY_TCH_NUM_ABS] = "INVALID" -}; - -static const u8 ldr_exit[] = { - 0xFF, 0x01, 0x3B, 0x00, 0x00, 0x4F, 0x6D, 0x17 -}; - -static const u8 ldr_err_app[] = { - 0x01, 0x02, 0x00, 0x00, 0x55, 0xDD, 0x17 -}; - -static inline size_t merge_bytes(u8 high, u8 low) -{ - return (high << 8) + low; -} - -#ifdef VERBOSE_DEBUG -static void cyttsp4_pr_buf(struct device *dev, u8 *pr_buf, u8 *dptr, int size, - const char *data_name) -{ - int i, k; - const char fmt[] = "%02X "; - int max; - - if (!size) - return; - - max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED); - - pr_buf[0] = 0; - for (i = k = 0; i < size && k < max; i++, k += 3) - scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, dptr[i]); - - dev_vdbg(dev, "%s: %s[0..%d]=%s%s\n", __func__, data_name, size - 1, - pr_buf, size <= max ? "" : CY_PR_TRUNCATED); -} -#else -#define cyttsp4_pr_buf(dev, pr_buf, dptr, size, data_name) do { } while (0) -#endif - -static int cyttsp4_load_status_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct device *dev = cd->dev; - int rc; - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, si->si_ofs.mode_size, - si->xy_mode); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_mode, - si->si_ofs.mode_size, "xy_mode"); - - return rc; -} - -static int cyttsp4_handshake(struct cyttsp4 *cd, u8 mode) -{ - u8 cmd = mode ^ CY_HST_TOGGLE; - int rc; - - /* - * Mode change issued, handshaking now will cause endless mode change - * requests, for sync mode modechange will do same with handshake - * */ - if (mode & CY_HST_MODE_CHANGE) - return 0; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) - dev_err(cd->dev, "%s: bus write fail on handshake (ret=%d)\n", - __func__, rc); - - return rc; -} - -static int cyttsp4_hw_soft_reset(struct cyttsp4 *cd) -{ - u8 cmd = CY_HST_RESET; - int rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) { - dev_err(cd->dev, "%s: FAILED to execute SOFT reset\n", - __func__); - return rc; - } - return 0; -} - -static int cyttsp4_hw_hard_reset(struct cyttsp4 *cd) -{ - if (cd->cpdata->xres) { - cd->cpdata->xres(cd->cpdata, cd->dev); - dev_dbg(cd->dev, "%s: execute HARD reset\n", __func__); - return 0; - } - dev_err(cd->dev, "%s: FAILED to execute HARD reset\n", __func__); - return -ENOSYS; -} - -static int cyttsp4_hw_reset(struct cyttsp4 *cd) -{ - int rc = cyttsp4_hw_hard_reset(cd); - if (rc == -ENOSYS) - rc = cyttsp4_hw_soft_reset(cd); - return rc; -} - -/* - * Gets number of bits for a touch filed as parameter, - * sets maximum value for field which is used as bit mask - * and returns number of bytes required for that field - */ -static int cyttsp4_bits_2_bytes(unsigned int nbits, size_t *max) -{ - *max = 1UL << nbits; - return (nbits + 7) / 8; -} - -static int cyttsp4_si_data_offsets(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(si->si_data), - &si->si_data); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read sysinfo data offsets r=%d\n", - __func__, rc); - return rc; - } - - /* Print sysinfo data offsets */ - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)&si->si_data, - sizeof(si->si_data), "sysinfo_data_offsets"); - - /* convert sysinfo data offset bytes into integers */ - - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.cydata_ofs = merge_bytes(si->si_data.cydata_ofsh, - si->si_data.cydata_ofsl); - si->si_ofs.test_ofs = merge_bytes(si->si_data.test_ofsh, - si->si_data.test_ofsl); - si->si_ofs.pcfg_ofs = merge_bytes(si->si_data.pcfg_ofsh, - si->si_data.pcfg_ofsl); - si->si_ofs.opcfg_ofs = merge_bytes(si->si_data.opcfg_ofsh, - si->si_data.opcfg_ofsl); - si->si_ofs.ddata_ofs = merge_bytes(si->si_data.ddata_ofsh, - si->si_data.ddata_ofsl); - si->si_ofs.mdata_ofs = merge_bytes(si->si_data.mdata_ofsh, - si->si_data.mdata_ofsl); - return rc; -} - -static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int read_offset; - int mfgid_sz, calc_mfgid_sz; - void *p; - int rc; - - if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) { - dev_err(cd->dev, - "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n", - __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs); - return -EINVAL; - } - - si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; - dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, - si->si_ofs.cydata_size); - - p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate cydata memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.cydata = p; - - read_offset = si->si_ofs.cydata_ofs; - - /* Read the CYDA registers up to MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, - offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz), - si->si_ptrs.cydata); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - /* Check MFGID size */ - mfgid_sz = si->si_ptrs.cydata->mfgid_sz; - calc_mfgid_sz = si->si_ofs.cydata_size - sizeof(struct cyttsp4_cydata); - if (mfgid_sz != calc_mfgid_sz) { - dev_err(cd->dev, "%s: mismatch in MFGID size, reported:%d calculated:%d\n", - __func__, mfgid_sz, calc_mfgid_sz); - return -EINVAL; - } - - read_offset += offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz); - - /* Read the CYDA registers for MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, si->si_ptrs.cydata->mfgid_sz, - si->si_ptrs.cydata->mfg_id); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - read_offset += si->si_ptrs.cydata->mfgid_sz; - - /* Read the rest of the CYDA registers */ - rc = cyttsp4_adap_read(cd, read_offset, - sizeof(struct cyttsp4_cydata) - - offsetof(struct cyttsp4_cydata, cyito_idh), - &si->si_ptrs.cydata->cyito_idh); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.cydata, - si->si_ofs.cydata_size, "sysinfo_cydata"); - return rc; -} - -static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) { - dev_err(cd->dev, - "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n", - __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs); - return -EINVAL; - } - - si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; - - p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate test memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.test = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.test_ofs, si->si_ofs.test_size, - si->si_ptrs.test); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read test data r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.test, si->si_ofs.test_size, - "sysinfo_test_data"); - if (si->si_ptrs.test->post_codel & - CY_POST_CODEL_WDG_RST) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "Reset was a WATCHDOG RESET", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_CFG_DATA_CRC_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", __func__, - "Config Data CRC FAIL", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_PANEL_TEST_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "PANEL TEST FAIL", - si->si_ptrs.test->post_codel); - - dev_info(cd->dev, "%s: SCANNING is %s codel=%02X\n", - __func__, si->si_ptrs.test->post_codel & 0x08 ? - "ENABLED" : "DISABLED", - si->si_ptrs.test->post_codel); - return rc; -} - -static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n", - __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs); - return -EINVAL; - } - - si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; - - p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate pcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.pcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size, - si->si_ptrs.pcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read pcfg data r=%d\n", - __func__, rc); - return rc; - } - - si->si_ofs.max_x = merge_bytes((si->si_ptrs.pcfg->res_xh - & CY_PCFG_RESOLUTION_X_MASK), si->si_ptrs.pcfg->res_xl); - si->si_ofs.x_origin = !!(si->si_ptrs.pcfg->res_xh - & CY_PCFG_ORIGIN_X_MASK); - si->si_ofs.max_y = merge_bytes((si->si_ptrs.pcfg->res_yh - & CY_PCFG_RESOLUTION_Y_MASK), si->si_ptrs.pcfg->res_yl); - si->si_ofs.y_origin = !!(si->si_ptrs.pcfg->res_yh - & CY_PCFG_ORIGIN_Y_MASK); - si->si_ofs.max_p = merge_bytes(si->si_ptrs.pcfg->max_zh, - si->si_ptrs.pcfg->max_zl); - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.pcfg, - si->si_ofs.pcfg_size, "sysinfo_pcfg_data"); - return rc; -} - -static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct cyttsp4_tch_abs_params *tch; - struct cyttsp4_tch_rec_params *tch_old, *tch_new; - enum cyttsp4_tch_abs abs; - int i; - void *p; - int rc; - - if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n", - __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs); - return -EINVAL; - } - - si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; - - p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate opcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.opcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size, - si->si_ptrs.opcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", - __func__, rc); - return rc; - } - si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; - si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; - si->si_ofs.rep_sz = (si->si_ptrs.opcfg->rep_szh * 256) + - si->si_ptrs.opcfg->rep_szl; - si->si_ofs.num_btns = si->si_ptrs.opcfg->num_btns; - si->si_ofs.num_btn_regs = (si->si_ofs.num_btns + - CY_NUM_BTN_PER_REG - 1) / CY_NUM_BTN_PER_REG; - si->si_ofs.tt_stat_ofs = si->si_ptrs.opcfg->tt_stat_ofs; - si->si_ofs.obj_cfg0 = si->si_ptrs.opcfg->obj_cfg0; - si->si_ofs.max_tchs = si->si_ptrs.opcfg->max_tchs & - CY_BYTE_OFS_MASK; - si->si_ofs.tch_rec_size = si->si_ptrs.opcfg->tch_rec_size & - CY_BYTE_OFS_MASK; - - /* Get the old touch fields */ - for (abs = CY_TCH_X; abs < CY_NUM_TCH_FIELDS; abs++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_old = &si->si_ptrs.opcfg->tch_rec_old[abs]; - - tch->ofs = tch_old->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_old->size, - &tch->max); - tch->bofs = (tch_old->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - - /* button fields */ - si->si_ofs.btn_rec_size = si->si_ptrs.opcfg->btn_rec_size; - si->si_ofs.btn_diff_ofs = si->si_ptrs.opcfg->btn_diff_ofs; - si->si_ofs.btn_diff_size = si->si_ptrs.opcfg->btn_diff_size; - - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* Get the extended touch fields */ - for (i = 0; i < CY_NUM_EXT_TCH_FIELDS; abs++, i++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_new = &si->si_ptrs.opcfg->tch_rec_new[i]; - - tch->ofs = tch_new->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_new->size, - &tch->max); - tch->bofs = (tch_new->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - } - - for (abs = 0; abs < CY_TCH_NUM_ABS; abs++) { - dev_dbg(cd->dev, "%s: tch_rec_%s\n", __func__, - cyttsp4_tch_abs_string[abs]); - dev_dbg(cd->dev, "%s: ofs =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].ofs); - dev_dbg(cd->dev, "%s: siz =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].size); - dev_dbg(cd->dev, "%s: max =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].max); - dev_dbg(cd->dev, "%s: bofs=%2zd\n", __func__, - si->si_ofs.tch_abs[abs].bofs); - } - - si->si_ofs.mode_size = si->si_ofs.tt_stat_ofs + 1; - si->si_ofs.data_size = si->si_ofs.max_tchs * - si->si_ptrs.opcfg->tch_rec_size; - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, - si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); - - return 0; -} - -static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.ddata_size = si->si_ofs.mdata_ofs - si->si_ofs.ddata_ofs; - - p = krealloc(si->si_ptrs.ddata, si->si_ofs.ddata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc ddata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.ddata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.ddata_ofs, si->si_ofs.ddata_size, - si->si_ptrs.ddata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read ddata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.ddata, - si->si_ofs.ddata_size, "sysinfo_ddata"); - return rc; -} - -static int cyttsp4_si_get_mdata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.mdata_size = si->si_ofs.map_sz - si->si_ofs.mdata_ofs; - - p = krealloc(si->si_ptrs.mdata, si->si_ofs.mdata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc mdata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.mdata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.mdata_ofs, si->si_ofs.mdata_size, - si->si_ptrs.mdata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read mdata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.mdata, - si->si_ofs.mdata_size, "sysinfo_mdata"); - return rc; -} - -static int cyttsp4_si_get_btn_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int btn; - int num_defined_keys; - u16 *key_table; - void *p; - int rc = 0; - - if (si->si_ofs.num_btns) { - si->si_ofs.btn_keys_size = si->si_ofs.num_btns * - sizeof(struct cyttsp4_btn); - - p = krealloc(si->btn, si->si_ofs.btn_keys_size, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) { - dev_err(cd->dev, "%s: %s\n", __func__, - "fail alloc btn_keys memory"); - return -ENOMEM; - } - si->btn = p; - - if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS] == NULL) - num_defined_keys = 0; - else if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS]->data == NULL) - num_defined_keys = 0; - else - num_defined_keys = cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->size; - - for (btn = 0; btn < si->si_ofs.num_btns && - btn < num_defined_keys; btn++) { - key_table = (u16 *)cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->data; - si->btn[btn].key_code = key_table[btn]; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - for (; btn < si->si_ofs.num_btns; btn++) { - si->btn[btn].key_code = KEY_RESERVED; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - - return rc; - } - - si->si_ofs.btn_keys_size = 0; - kfree(si->btn); - si->btn = NULL; - return rc; -} - -static int cyttsp4_si_get_op_data_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - - p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_mode = p; - - p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_data = p; - - p = krealloc(si->btn_rec_data, - si->si_ofs.btn_rec_size * si->si_ofs.num_btns, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->btn_rec_data = p; - - return 0; -} - -static void cyttsp4_si_put_log_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - dev_dbg(cd->dev, "%s: cydata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.cydata_ofs, si->si_ofs.cydata_size); - dev_dbg(cd->dev, "%s: test_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.test_ofs, si->si_ofs.test_size); - dev_dbg(cd->dev, "%s: pcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size); - dev_dbg(cd->dev, "%s: opcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size); - dev_dbg(cd->dev, "%s: ddata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.ddata_ofs, si->si_ofs.ddata_size); - dev_dbg(cd->dev, "%s: mdata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.mdata_ofs, si->si_ofs.mdata_size); - - dev_dbg(cd->dev, "%s: cmd_ofs =%4zd\n", __func__, - si->si_ofs.cmd_ofs); - dev_dbg(cd->dev, "%s: rep_ofs =%4zd\n", __func__, - si->si_ofs.rep_ofs); - dev_dbg(cd->dev, "%s: rep_sz =%4zd\n", __func__, - si->si_ofs.rep_sz); - dev_dbg(cd->dev, "%s: num_btns =%4zd\n", __func__, - si->si_ofs.num_btns); - dev_dbg(cd->dev, "%s: num_btn_regs =%4zd\n", __func__, - si->si_ofs.num_btn_regs); - dev_dbg(cd->dev, "%s: tt_stat_ofs =%4zd\n", __func__, - si->si_ofs.tt_stat_ofs); - dev_dbg(cd->dev, "%s: tch_rec_size =%4zd\n", __func__, - si->si_ofs.tch_rec_size); - dev_dbg(cd->dev, "%s: max_tchs =%4zd\n", __func__, - si->si_ofs.max_tchs); - dev_dbg(cd->dev, "%s: mode_size =%4zd\n", __func__, - si->si_ofs.mode_size); - dev_dbg(cd->dev, "%s: data_size =%4zd\n", __func__, - si->si_ofs.data_size); - dev_dbg(cd->dev, "%s: map_sz =%4zd\n", __func__, - si->si_ofs.map_sz); - - dev_dbg(cd->dev, "%s: btn_rec_size =%2zd\n", __func__, - si->si_ofs.btn_rec_size); - dev_dbg(cd->dev, "%s: btn_diff_ofs =%2zd\n", __func__, - si->si_ofs.btn_diff_ofs); - dev_dbg(cd->dev, "%s: btn_diff_size =%2zd\n", __func__, - si->si_ofs.btn_diff_size); - - dev_dbg(cd->dev, "%s: max_x = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_x, si->si_ofs.max_x); - dev_dbg(cd->dev, "%s: x_origin = %zd (%s)\n", __func__, - si->si_ofs.x_origin, - si->si_ofs.x_origin == CY_NORMAL_ORIGIN ? - "left corner" : "right corner"); - dev_dbg(cd->dev, "%s: max_y = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_y, si->si_ofs.max_y); - dev_dbg(cd->dev, "%s: y_origin = %zd (%s)\n", __func__, - si->si_ofs.y_origin, - si->si_ofs.y_origin == CY_NORMAL_ORIGIN ? - "upper corner" : "lower corner"); - dev_dbg(cd->dev, "%s: max_p = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_p, si->si_ofs.max_p); - - dev_dbg(cd->dev, "%s: xy_mode=%p xy_data=%p\n", __func__, - si->xy_mode, si->xy_data); -} - -static int cyttsp4_get_sysinfo_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc; - - rc = cyttsp4_si_data_offsets(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_cydata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_test_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_pcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_opcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_ddata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_mdata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_btn_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_op_data_ptrs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get_op_data\n", - __func__); - return rc; - } - - cyttsp4_si_put_log_data(cd); - - /* provide flow control handshake */ - rc = cyttsp4_handshake(cd, si->si_data.hst_mode); - if (rc < 0) - dev_err(cd->dev, "%s: handshake fail on sysinfo reg\n", - __func__); - - si->ready = true; - return rc; -} - -static void cyttsp4_queue_startup_(struct cyttsp4 *cd) -{ - if (cd->startup_state == STARTUP_NONE) { - cd->startup_state = STARTUP_QUEUED; - schedule_work(&cd->startup_work); - dev_dbg(cd->dev, "%s: cyttsp4_startup queued\n", __func__); - } else { - dev_dbg(cd->dev, "%s: startup_state = %d\n", __func__, - cd->startup_state); - } -} - -static void cyttsp4_report_slot_liftoff(struct cyttsp4_mt_data *md, - int max_slots) -{ - int t; - - if (md->num_prv_tch == 0) - return; - - for (t = 0; t < max_slots; t++) { - input_mt_slot(md->input, t); - input_mt_report_slot_inactive(md->input); - } -} - -static void cyttsp4_lift_all(struct cyttsp4_mt_data *md) -{ - if (!md->si) - return; - - if (md->num_prv_tch != 0) { - cyttsp4_report_slot_liftoff(md, - md->si->si_ofs.tch_abs[CY_TCH_T].max); - input_sync(md->input); - md->num_prv_tch = 0; - } -} - -static void cyttsp4_get_touch_axis(struct cyttsp4_mt_data *md, - int *axis, int size, int max, u8 *xy_data, int bofs) -{ - int nbyte; - int next; - - for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) { - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d) bofs=%d\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next], bofs); - *axis = (*axis * 256) + (xy_data[next] >> bofs); - next++; - } - - *axis &= max - 1; - - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d)\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next]); -} - -static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, - struct cyttsp4_touch *touch, u8 *xy_data) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - enum cyttsp4_tch_abs abs; - bool flipped; - - for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { - cyttsp4_get_touch_axis(md, &touch->abs[abs], - si->si_ofs.tch_abs[abs].size, - si->si_ofs.tch_abs[abs].max, - xy_data + si->si_ofs.tch_abs[abs].ofs, - si->si_ofs.tch_abs[abs].bofs); - dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__, - cyttsp4_tch_abs_string[abs], - touch->abs[abs], touch->abs[abs]); - } - - if (md->pdata->flags & CY_FLAG_FLIP) { - swap(touch->abs[CY_TCH_X], touch->abs[CY_TCH_Y]); - flipped = true; - } else - flipped = false; - - if (md->pdata->flags & CY_FLAG_INV_X) { - if (flipped) - touch->abs[CY_TCH_X] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_X]; - else - touch->abs[CY_TCH_X] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_X]; - } - if (md->pdata->flags & CY_FLAG_INV_Y) { - if (flipped) - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_Y]; - else - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_Y]; - } - - dev_vdbg(dev, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n", - __func__, flipped ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_X ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_Y ? "true" : "false", - touch->abs[CY_TCH_X], touch->abs[CY_TCH_X], - touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]); -} - -static void cyttsp4_final_sync(struct input_dev *input, int max_slots, int *ids) -{ - int t; - - for (t = 0; t < max_slots; t++) { - if (ids[t]) - continue; - input_mt_slot(input, t); - input_mt_report_slot_inactive(input); - } - - input_sync(input); -} - -static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - struct cyttsp4_touch tch; - int sig; - int i, j, t = 0; - int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; - - memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int)); - for (i = 0; i < num_cur_tch; i++) { - cyttsp4_get_touch(md, &tch, si->xy_data + - (i * si->si_ofs.tch_rec_size)); - if ((tch.abs[CY_TCH_T] < md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || - (tch.abs[CY_TCH_T] > md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { - dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n", - __func__, i, tch.abs[CY_TCH_T], - md->pdata->frmwrk->abs[(CY_ABS_ID_OST * - CY_NUM_ABS_SET) + CY_MAX_OST]); - continue; - } - - /* use 0 based track id's */ - sig = md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) { - t = tch.abs[CY_TCH_T] - md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]; - if (tch.abs[CY_TCH_E] == CY_EV_LIFTOFF) { - dev_dbg(dev, "%s: t=%d e=%d lift-off\n", - __func__, t, tch.abs[CY_TCH_E]); - goto cyttsp4_get_mt_touches_pr_tch; - } - input_mt_slot(md->input, t); - input_mt_report_slot_state(md->input, MT_TOOL_FINGER, - true); - ids[t] = true; - } - - /* all devices: position and pressure fields */ - for (j = 0; j <= CY_ABS_W_OST; j++) { - sig = md->pdata->frmwrk->abs[((CY_ABS_X_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_X + j]); - } - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* - * TMA400 size and orientation fields: - * if pressure is non-zero and major touch - * signal is zero, then set major and minor touch - * signals to minimum non-zero value - */ - if (tch.abs[CY_TCH_P] > 0 && tch.abs[CY_TCH_MAJ] == 0) - tch.abs[CY_TCH_MAJ] = tch.abs[CY_TCH_MIN] = 1; - - /* Get the extended touch fields */ - for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) { - sig = md->pdata->frmwrk->abs - [((CY_ABS_MAJ_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_MAJ + j]); - } - } - -cyttsp4_get_mt_touches_pr_tch: - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d\n", - __func__, t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_MAJ], - tch.abs[CY_TCH_MIN], - tch.abs[CY_TCH_OR], - tch.abs[CY_TCH_E]); - else - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d e=%d\n", __func__, - t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_E]); - } - - cyttsp4_final_sync(md->input, si->si_ofs.tch_abs[CY_TCH_T].max, ids); - - md->num_prv_tch = num_cur_tch; - - return; -} - -/* read xy_data for all current touches */ -static int cyttsp4_xy_worker(struct cyttsp4 *cd) -{ - struct cyttsp4_mt_data *md = &cd->md; - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - u8 num_cur_tch; - u8 hst_mode; - u8 rep_len; - u8 rep_stat; - u8 tt_stat; - int rc = 0; - - /* - * Get event data from cyttsp4 device. - * The event data includes all data - * for all active touches. - * Event data also includes button data - */ - /* - * Use 2 reads: - * 1st read to get mode + button bytes + touch count (core) - * 2nd read (optional) to get touch 1 - touch n data - */ - hst_mode = si->xy_mode[CY_REG_BASE]; - rep_len = si->xy_mode[si->si_ofs.rep_ofs]; - rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1]; - tt_stat = si->xy_mode[si->si_ofs.tt_stat_ofs]; - dev_vdbg(dev, "%s: %s%02X %s%d %s%02X %s%02X\n", __func__, - "hst_mode=", hst_mode, "rep_len=", rep_len, - "rep_stat=", rep_stat, "tt_stat=", tt_stat); - - num_cur_tch = GET_NUM_TOUCHES(tt_stat); - dev_vdbg(dev, "%s: num_cur_tch=%d\n", __func__, num_cur_tch); - - if (rep_len == 0 && num_cur_tch > 0) { - dev_err(dev, "%s: report length error rep_len=%d num_tch=%d\n", - __func__, rep_len, num_cur_tch); - goto cyttsp4_xy_worker_exit; - } - - /* read touches */ - if (num_cur_tch > 0) { - rc = cyttsp4_adap_read(cd, si->si_ofs.tt_stat_ofs + 1, - num_cur_tch * si->si_ofs.tch_rec_size, - si->xy_data); - if (rc < 0) { - dev_err(dev, "%s: read fail on touch regs r=%d\n", - __func__, rc); - goto cyttsp4_xy_worker_exit; - } - } - - /* print xy data */ - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_data, num_cur_tch * - si->si_ofs.tch_rec_size, "xy_data"); - - /* check any error conditions */ - if (IS_BAD_PKT(rep_stat)) { - dev_dbg(dev, "%s: Invalid buffer detected\n", __func__); - rc = 0; - goto cyttsp4_xy_worker_exit; - } - - if (IS_LARGE_AREA(tt_stat)) - dev_dbg(dev, "%s: Large area detected\n", __func__); - - if (num_cur_tch > si->si_ofs.max_tchs) { - dev_err(dev, "%s: too many tch; set to max tch (n=%d c=%zd)\n", - __func__, num_cur_tch, si->si_ofs.max_tchs); - num_cur_tch = si->si_ofs.max_tchs; - } - - /* extract xy_data for all currently reported touches */ - dev_vdbg(dev, "%s: extract data num_cur_tch=%d\n", __func__, - num_cur_tch); - if (num_cur_tch) - cyttsp4_get_mt_touches(md, num_cur_tch); - else - cyttsp4_lift_all(md); - - rc = 0; - -cyttsp4_xy_worker_exit: - return rc; -} - -static int cyttsp4_mt_attention(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int rc = 0; - - if (!md->si) - return 0; - - mutex_lock(&md->report_lock); - if (!md->is_suspended) { - /* core handles handshake */ - rc = cyttsp4_xy_worker(cd); - } else { - dev_vdbg(dev, "%s: Ignoring report while suspended\n", - __func__); - } - mutex_unlock(&md->report_lock); - if (rc < 0) - dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc); - - return rc; -} - -static irqreturn_t cyttsp4_irq(int irq, void *handle) -{ - struct cyttsp4 *cd = handle; - struct device *dev = cd->dev; - enum cyttsp4_mode cur_mode; - u8 cmd_ofs = cd->sysinfo.si_ofs.cmd_ofs; - u8 mode[3]; - int rc; - - /* - * Check whether this IRQ should be ignored (external) - * This should be the very first thing to check since - * ignore_irq may be set for a very short period of time - */ - if (atomic_read(&cd->ignore_irq)) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - return IRQ_HANDLED; - } - - dev_dbg(dev, "%s int:0x%x\n", __func__, cd->int_status); - - mutex_lock(&cd->system_lock); - - /* Just to debug */ - if (cd->sleep_state == SS_SLEEP_ON || cd->sleep_state == SS_SLEEPING) - dev_vdbg(dev, "%s: Received IRQ while in sleep\n", __func__); - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), mode); - if (rc) { - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto cyttsp4_irq_exit; - } - dev_vdbg(dev, "%s mode[0-2]:0x%X 0x%X 0x%X\n", __func__, - mode[0], mode[1], mode[2]); - - if (IS_BOOTLOADER(mode[0], mode[1])) { - cur_mode = CY_MODE_BOOTLOADER; - dev_vdbg(dev, "%s: bl running\n", __func__); - if (cd->mode == CY_MODE_BOOTLOADER) { - /* Signal bootloader heartbeat heard */ - wake_up(&cd->wait_q); - goto cyttsp4_irq_exit; - } - - /* switch to bootloader */ - dev_dbg(dev, "%s: restart switch to bl m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - - /* catch operation->bl glitch */ - if (cd->mode != CY_MODE_UNKNOWN) { - /* Incase startup_state do not let startup_() */ - cd->mode = CY_MODE_UNKNOWN; - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* - * do not wake thread on this switch since - * it is possible to get an early heartbeat - * prior to performing the reset - */ - cd->mode = cur_mode; - - goto cyttsp4_irq_exit; - } - - switch (mode[0] & CY_HST_MODE) { - case CY_HST_OPERATE: - cur_mode = CY_MODE_OPERATIONAL; - dev_vdbg(dev, "%s: operational\n", __func__); - break; - case CY_HST_CAT: - cur_mode = CY_MODE_CAT; - dev_vdbg(dev, "%s: CaT\n", __func__); - break; - case CY_HST_SYSINFO: - cur_mode = CY_MODE_SYSINFO; - dev_vdbg(dev, "%s: sysinfo\n", __func__); - break; - default: - cur_mode = CY_MODE_UNKNOWN; - dev_err(dev, "%s: unknown HST mode 0x%02X\n", __func__, - mode[0]); - break; - } - - /* Check whether this IRQ should be ignored (internal) */ - if (cd->int_status & CY_INT_IGNORE) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - goto cyttsp4_irq_exit; - } - - /* Check for wake up interrupt */ - if (cd->int_status & CY_INT_AWAKE) { - cd->int_status &= ~CY_INT_AWAKE; - wake_up(&cd->wait_q); - dev_vdbg(dev, "%s: Received wake up interrupt\n", __func__); - goto cyttsp4_irq_handshake; - } - - /* Expecting mode change interrupt */ - if ((cd->int_status & CY_INT_MODE_CHANGE) - && (mode[0] & CY_HST_MODE_CHANGE) == 0) { - cd->int_status &= ~CY_INT_MODE_CHANGE; - dev_dbg(dev, "%s: finish mode switch m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - cd->mode = cur_mode; - wake_up(&cd->wait_q); - goto cyttsp4_irq_handshake; - } - - /* compare current core mode to current device mode */ - dev_vdbg(dev, "%s: cd->mode=%d cur_mode=%d\n", - __func__, cd->mode, cur_mode); - if ((mode[0] & CY_HST_MODE_CHANGE) == 0 && cd->mode != cur_mode) { - /* Unexpected mode change occurred */ - dev_err(dev, "%s %d->%d 0x%x\n", __func__, cd->mode, - cur_mode, cd->int_status); - dev_dbg(dev, "%s: Unexpected mode change, startup\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* Expecting command complete interrupt */ - dev_vdbg(dev, "%s: command byte:0x%x\n", __func__, mode[cmd_ofs]); - if ((cd->int_status & CY_INT_EXEC_CMD) - && mode[cmd_ofs] & CY_CMD_COMPLETE) { - cd->int_status &= ~CY_INT_EXEC_CMD; - dev_vdbg(dev, "%s: Received command complete interrupt\n", - __func__); - wake_up(&cd->wait_q); - /* - * It is possible to receive a single interrupt for - * command complete and touch/button status report. - * Continue processing for a possible status report. - */ - } - - /* This should be status report, read status regs */ - if (cd->mode == CY_MODE_OPERATIONAL) { - dev_vdbg(dev, "%s: Read status registers\n", __func__); - rc = cyttsp4_load_status_regs(cd); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - } - - cyttsp4_mt_attention(cd); - -cyttsp4_irq_handshake: - /* handshake the event */ - dev_vdbg(dev, "%s: Handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - rc = cyttsp4_handshake(cd, mode[0]); - if (rc < 0) - dev_err(dev, "%s: Fail handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - - /* - * a non-zero udelay period is required for using - * IRQF_TRIGGER_LOW in order to delay until the - * device completes isr deassert - */ - udelay(cd->cpdata->level_irq_udelay); - -cyttsp4_irq_exit: - mutex_unlock(&cd->system_lock); - return IRQ_HANDLED; -} - -static void cyttsp4_start_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - mod_timer(&cd->watchdog_timer, jiffies + - msecs_to_jiffies(CY_WATCHDOG_TIMEOUT)); -} - -static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - /* - * Ensure we wait until the watchdog timer - * running on a different CPU finishes - */ - timer_shutdown_sync(&cd->watchdog_timer); - cancel_work_sync(&cd->watchdog_work); -} - -static void cyttsp4_watchdog_timer(struct timer_list *t) -{ - struct cyttsp4 *cd = from_timer(cd, t, watchdog_timer); - - dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__); - - schedule_work(&cd->watchdog_work); - - return; -} - -static int cyttsp4_request_exclusive(struct cyttsp4 *cd, void *ownptr, - int timeout_ms) -{ - int t = msecs_to_jiffies(timeout_ms); - bool with_timeout = (timeout_ms != 0); - - mutex_lock(&cd->system_lock); - if (!cd->exclusive_dev && cd->exclusive_waits == 0) { - cd->exclusive_dev = ownptr; - goto exit; - } - - cd->exclusive_waits++; -wait: - mutex_unlock(&cd->system_lock); - if (with_timeout) { - t = wait_event_timeout(cd->wait_q, !cd->exclusive_dev, t); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exclusive access\n", - __func__); - mutex_lock(&cd->system_lock); - cd->exclusive_waits--; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - } else { - wait_event(cd->wait_q, !cd->exclusive_dev); - } - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev) - goto wait; - cd->exclusive_dev = ownptr; - cd->exclusive_waits--; -exit: - mutex_unlock(&cd->system_lock); - - return 0; -} - -/* - * returns error if was not owned - */ -static int cyttsp4_release_exclusive(struct cyttsp4 *cd, void *ownptr) -{ - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev != ownptr) { - mutex_unlock(&cd->system_lock); - return -EINVAL; - } - - dev_vdbg(cd->dev, "%s: exclusive_dev %p freed\n", - __func__, cd->exclusive_dev); - cd->exclusive_dev = NULL; - wake_up(&cd->wait_q); - mutex_unlock(&cd->system_lock); - return 0; -} - -static int cyttsp4_wait_bl_heartbeat(struct cyttsp4 *cd) -{ - long t; - int rc = 0; - - /* wait heartbeat */ - dev_vdbg(cd->dev, "%s: wait heartbeat...\n", __func__); - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_BOOTLOADER, - msecs_to_jiffies(CY_CORE_RESET_AND_WAIT_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting bl heartbeat cd->mode=%d\n", - __func__, cd->mode); - rc = -ETIME; - } - - return rc; -} - -static int cyttsp4_wait_sysinfo_mode(struct cyttsp4 *cd) -{ - long t; - - dev_vdbg(cd->dev, "%s: wait sysinfo...\n", __func__); - - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_SYSINFO, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exit bl cd->mode=%d\n", - __func__, cd->mode); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - - return 0; -} - -static int cyttsp4_reset_and_wait(struct cyttsp4 *cd) -{ - int rc; - - /* reset hardware */ - mutex_lock(&cd->system_lock); - dev_dbg(cd->dev, "%s: reset hw...\n", __func__); - rc = cyttsp4_hw_reset(cd); - cd->mode = CY_MODE_UNKNOWN; - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s:Fail hw reset r=%d\n", __func__, rc); - return rc; - } - - return cyttsp4_wait_bl_heartbeat(cd); -} - -/* - * returns err if refused or timeout; block until mode change complete - * bit is set (mode change interrupt) - */ -static int cyttsp4_set_mode(struct cyttsp4 *cd, int new_mode) -{ - u8 new_dev_mode; - u8 mode; - long t; - int rc; - - switch (new_mode) { - case CY_MODE_OPERATIONAL: - new_dev_mode = CY_HST_OPERATE; - break; - case CY_MODE_SYSINFO: - new_dev_mode = CY_HST_SYSINFO; - break; - case CY_MODE_CAT: - new_dev_mode = CY_HST_CAT; - break; - default: - dev_err(cd->dev, "%s: invalid mode: %02X(%d)\n", - __func__, new_mode, new_mode); - return -EINVAL; - } - - /* change mode */ - dev_dbg(cd->dev, "%s: %s=%p new_dev_mode=%02X new_mode=%d\n", - __func__, "have exclusive", cd->exclusive_dev, - new_dev_mode, new_mode); - - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc < 0) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read mode r=%d\n", - __func__, rc); - goto exit; - } - - /* Clear device mode bits and set to new mode */ - mode &= ~CY_HST_MODE; - mode |= new_dev_mode | CY_HST_MODE_CHANGE; - - cd->int_status |= CY_INT_MODE_CHANGE; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode), &mode); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write mode change r=%d\n", - __func__, rc); - goto exit; - } - - /* wait for mode change done interrupt */ - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_MODE_CHANGE) == 0, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - dev_dbg(cd->dev, "%s: back from wait t=%ld cd->mode=%d\n", - __func__, t, cd->mode); - - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: %s\n", __func__, - "tmo waiting mode change"); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - rc = -EINVAL; - } - -exit: - return rc; -} - -static void cyttsp4_watchdog_work(struct work_struct *work) -{ - struct cyttsp4 *cd = - container_of(work, struct cyttsp4, watchdog_work); - u8 *mode; - int retval; - - mutex_lock(&cd->system_lock); - retval = cyttsp4_load_status_regs(cd); - if (retval < 0) { - dev_err(cd->dev, - "%s: failed to access device in watchdog timer r=%d\n", - __func__, retval); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - mode = &cd->sysinfo.xy_mode[CY_REG_BASE]; - if (IS_BOOTLOADER(mode[0], mode[1])) { - dev_err(cd->dev, - "%s: device found in bootloader mode when operational mode\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - - cyttsp4_start_wd_timer(cd); -cyttsp4_timer_watchdog_exit_error: - mutex_unlock(&cd->system_lock); - return; -} - -static int cyttsp4_core_sleep_(struct cyttsp4 *cd) -{ - enum cyttsp4_sleep_state ss = SS_SLEEP_ON; - enum cyttsp4_int_state int_status = CY_INT_IGNORE; - int rc = 0; - u8 mode[2]; - - /* Already in sleep mode? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->sleep_state = SS_SLEEPING; - mutex_unlock(&cd->system_lock); - - cyttsp4_stop_wd_timer(cd); - - /* Wait until currently running IRQ handler exits and disable IRQ */ - disable_irq(cd->irq); - - dev_vdbg(cd->dev, "%s: write DEEP SLEEP...\n", __func__); - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto error; - } - - if (IS_BOOTLOADER(mode[0], mode[1])) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Device in BOOTLOADER mode.\n", __func__); - rc = -EINVAL; - goto error; - } - - mode[0] |= CY_HST_SLEEP; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode[0]), &mode[0]); - mutex_unlock(&cd->system_lock); - if (rc) { - dev_err(cd->dev, "%s: Fail write adapter r=%d\n", __func__, rc); - goto error; - } - dev_vdbg(cd->dev, "%s: write DEEP SLEEP succeeded\n", __func__); - - if (cd->cpdata->power) { - dev_dbg(cd->dev, "%s: Power down HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 0, cd->dev, &cd->ignore_irq); - } else { - dev_dbg(cd->dev, "%s: No power function\n", __func__); - rc = 0; - } - if (rc < 0) { - dev_err(cd->dev, "%s: HW Power down fails r=%d\n", - __func__, rc); - goto error; - } - - /* Give time to FW to sleep */ - msleep(50); - - goto exit; - -error: - ss = SS_SLEEP_OFF; - int_status = CY_INT_NONE; - cyttsp4_start_wd_timer(cd); - -exit: - mutex_lock(&cd->system_lock); - cd->sleep_state = ss; - cd->int_status |= int_status; - mutex_unlock(&cd->system_lock); - enable_irq(cd->irq); - return rc; -} - -static int cyttsp4_startup_(struct cyttsp4 *cd) -{ - int retry = CY_CORE_STARTUP_RETRY_COUNT; - int rc; - - cyttsp4_stop_wd_timer(cd); - -reset: - if (retry != CY_CORE_STARTUP_RETRY_COUNT) - dev_dbg(cd->dev, "%s: Retry %d\n", __func__, - CY_CORE_STARTUP_RETRY_COUNT - retry); - - /* reset hardware and wait for heartbeat */ - rc = cyttsp4_reset_and_wait(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: Error on h/w reset r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - /* exit bl into sysinfo mode */ - dev_vdbg(cd->dev, "%s: write exit ldr...\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_MODE_CHANGE; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(ldr_exit), - (u8 *)ldr_exit); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_wait_sysinfo_mode(cd); - if (rc < 0) { - u8 buf[sizeof(ldr_err_app)]; - int rc1; - - /* Check for invalid/corrupted touch application */ - rc1 = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(ldr_err_app), - buf); - if (rc1) { - dev_err(cd->dev, "%s: Fail read r=%d\n", __func__, rc1); - } else if (!memcmp(buf, ldr_err_app, sizeof(ldr_err_app))) { - dev_err(cd->dev, "%s: Error launching touch application\n", - __func__); - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = true; - mutex_unlock(&cd->system_lock); - goto exit_no_wd; - } - - if (retry--) - goto reset; - goto exit; - } - - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = false; - mutex_unlock(&cd->system_lock); - - /* read sysinfo data */ - dev_vdbg(cd->dev, "%s: get sysinfo regs..\n", __func__); - rc = cyttsp4_get_sysinfo_regs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get sysinfo regs rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_set_mode(cd, CY_MODE_OPERATIONAL); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to set mode to operational rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - cyttsp4_lift_all(&cd->md); - - /* restore to sleep if was suspended */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - cyttsp4_core_sleep_(cd); - goto exit_no_wd; - } - mutex_unlock(&cd->system_lock); - -exit: - cyttsp4_start_wd_timer(cd); -exit_no_wd: - return rc; -} - -static int cyttsp4_startup(struct cyttsp4 *cd) -{ - int rc; - - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_RUNNING; - mutex_unlock(&cd->system_lock); - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - goto exit; - } - - rc = cyttsp4_startup_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - /* Don't return fail code, mode is already changed. */ - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - -exit: - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_NONE; - mutex_unlock(&cd->system_lock); - - /* Wake the waiters for end of startup */ - wake_up(&cd->wait_q); - - return rc; -} - -static void cyttsp4_startup_work_function(struct work_struct *work) -{ - struct cyttsp4 *cd = container_of(work, struct cyttsp4, startup_work); - int rc; - - rc = cyttsp4_startup(cd); - if (rc < 0) - dev_err(cd->dev, "%s: Fail queued startup r=%d\n", - __func__, rc); -} - -static void cyttsp4_free_si_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - - if (!si) - return; - - kfree(si->si_ptrs.cydata); - kfree(si->si_ptrs.test); - kfree(si->si_ptrs.pcfg); - kfree(si->si_ptrs.opcfg); - kfree(si->si_ptrs.ddata); - kfree(si->si_ptrs.mdata); - kfree(si->btn); - kfree(si->xy_mode); - kfree(si->xy_data); - kfree(si->btn_rec_data); -} - -static int cyttsp4_core_sleep(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_sleep_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_wake_(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - int rc; - u8 mode; - int t; - - /* Already woken? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_OFF) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_AWAKE; - cd->sleep_state = SS_WAKING; - - if (cd->cpdata->power) { - dev_dbg(dev, "%s: Power up HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 1, dev, &cd->ignore_irq); - } else { - dev_dbg(dev, "%s: No power function\n", __func__); - rc = -ENOSYS; - } - if (rc < 0) { - dev_err(dev, "%s: HW Power up fails r=%d\n", - __func__, rc); - - /* Initiate a read transaction to wake up */ - cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - } else - dev_vdbg(cd->dev, "%s: HW power up succeeds\n", - __func__); - mutex_unlock(&cd->system_lock); - - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_AWAKE) == 0, - msecs_to_jiffies(CY_CORE_WAKEUP_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(dev, "%s: TMO waiting for wakeup\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_AWAKE; - /* Try starting up */ - cyttsp4_queue_startup_(cd); - mutex_unlock(&cd->system_lock); - } - - mutex_lock(&cd->system_lock); - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - - cyttsp4_start_wd_timer(cd); - - return 0; -} - -static int cyttsp4_core_wake(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_wake_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_suspend(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = true; - - rc = cyttsp4_core_sleep(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on sleep\n", __func__); - return -EAGAIN; - } - return 0; -} - -static int cyttsp4_core_resume(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = false; - - rc = cyttsp4_core_wake(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on wake\n", __func__); - return -EAGAIN; - } - - return 0; -} - -EXPORT_GPL_RUNTIME_DEV_PM_OPS(cyttsp4_pm_ops, - cyttsp4_core_suspend, cyttsp4_core_resume, NULL); - -static int cyttsp4_mt_open(struct input_dev *input) -{ - pm_runtime_get(input->dev.parent); - return 0; -} - -static void cyttsp4_mt_close(struct input_dev *input) -{ - struct cyttsp4_mt_data *md = input_get_drvdata(input); - mutex_lock(&md->report_lock); - if (!md->is_suspended) - pm_runtime_put(input->dev.parent); - mutex_unlock(&md->report_lock); -} - - -static int cyttsp4_setup_input_device(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int signal = CY_IGNORE_VALUE; - int max_x, max_y, max_p, min, max; - int max_x_tmp, max_y_tmp; - int i; - int rc; - - dev_vdbg(dev, "%s: Initialize event signals\n", __func__); - __set_bit(EV_ABS, md->input->evbit); - __set_bit(EV_REL, md->input->evbit); - __set_bit(EV_KEY, md->input->evbit); - - max_x_tmp = md->si->si_ofs.max_x; - max_y_tmp = md->si->si_ofs.max_y; - - /* get maximum values from the sysinfo data */ - if (md->pdata->flags & CY_FLAG_FLIP) { - max_x = max_y_tmp - 1; - max_y = max_x_tmp - 1; - } else { - max_x = max_x_tmp - 1; - max_y = max_y_tmp - 1; - } - max_p = md->si->si_ofs.max_p; - - /* set event signal capabilities */ - for (i = 0; i < (md->pdata->frmwrk->size / CY_NUM_ABS_SET); i++) { - signal = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_SIGNAL_OST]; - if (signal != CY_IGNORE_VALUE) { - __set_bit(signal, md->input->absbit); - min = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MIN_OST]; - max = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MAX_OST]; - if (i == CY_ABS_ID_OST) { - /* shift track ids down to start at 0 */ - max = max - min; - min = min - min; - } else if (i == CY_ABS_X_OST) - max = max_x; - else if (i == CY_ABS_Y_OST) - max = max_y; - else if (i == CY_ABS_P_OST) - max = max_p; - input_set_abs_params(md->input, signal, min, max, - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FUZZ_OST], - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FLAT_OST]); - dev_dbg(dev, "%s: register signal=%02X min=%d max=%d\n", - __func__, signal, min, max); - if ((i == CY_ABS_ID_OST) && - (md->si->si_ofs.tch_rec_size < - CY_TMA4XX_TCH_REC_SIZE)) - break; - } - } - - input_mt_init_slots(md->input, md->si->si_ofs.tch_abs[CY_TCH_T].max, - INPUT_MT_DIRECT); - rc = input_register_device(md->input); - if (rc < 0) - dev_err(dev, "%s: Error, failed register input device r=%d\n", - __func__, rc); - return rc; -} - -static int cyttsp4_mt_probe(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - struct cyttsp4_mt_platform_data *pdata = cd->pdata->mt_pdata; - int rc = 0; - - mutex_init(&md->report_lock); - md->pdata = pdata; - /* Create the input device and register it. */ - dev_vdbg(dev, "%s: Create the input device and register it\n", - __func__); - md->input = input_allocate_device(); - if (md->input == NULL) { - dev_err(dev, "%s: Error, failed to allocate input device\n", - __func__); - rc = -ENOSYS; - goto error_alloc_failed; - } - - md->input->name = pdata->inp_dev_name; - scnprintf(md->phys, sizeof(md->phys)-1, "%s", dev_name(dev)); - md->input->phys = md->phys; - md->input->id.bustype = cd->bus_ops->bustype; - md->input->dev.parent = dev; - md->input->open = cyttsp4_mt_open; - md->input->close = cyttsp4_mt_close; - input_set_drvdata(md->input, md); - - /* get sysinfo */ - md->si = &cd->sysinfo; - - rc = cyttsp4_setup_input_device(cd); - if (rc) - goto error_init_input; - - return 0; - -error_init_input: - input_free_device(md->input); -error_alloc_failed: - dev_err(dev, "%s failed.\n", __func__); - return rc; -} - -struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size) -{ - struct cyttsp4 *cd; - struct cyttsp4_platform_data *pdata = dev_get_platdata(dev); - unsigned long irq_flags; - int rc = 0; - - if (!pdata || !pdata->core_pdata || !pdata->mt_pdata) { - dev_err(dev, "%s: Missing platform data\n", __func__); - rc = -ENODEV; - goto error_no_pdata; - } - - cd = kzalloc(sizeof(*cd), GFP_KERNEL); - if (!cd) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_alloc_data; - } - - cd->xfer_buf = kzalloc(xfer_buf_size, GFP_KERNEL); - if (!cd->xfer_buf) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_free_cd; - } - - /* Initialize device info */ - cd->dev = dev; - cd->pdata = pdata; - cd->cpdata = pdata->core_pdata; - cd->bus_ops = ops; - - /* Initialize mutexes and spinlocks */ - mutex_init(&cd->system_lock); - mutex_init(&cd->adap_lock); - - /* Initialize wait queue */ - init_waitqueue_head(&cd->wait_q); - - /* Initialize works */ - INIT_WORK(&cd->startup_work, cyttsp4_startup_work_function); - INIT_WORK(&cd->watchdog_work, cyttsp4_watchdog_work); - - /* Initialize IRQ */ - cd->irq = gpio_to_irq(cd->cpdata->irq_gpio); - if (cd->irq < 0) { - rc = -EINVAL; - goto error_free_xfer; - } - - dev_set_drvdata(dev, cd); - - /* Call platform init function */ - if (cd->cpdata->init) { - dev_dbg(cd->dev, "%s: Init HW\n", __func__); - rc = cd->cpdata->init(cd->cpdata, 1, cd->dev); - } else { - dev_dbg(cd->dev, "%s: No HW INIT function\n", __func__); - rc = 0; - } - if (rc < 0) - dev_err(cd->dev, "%s: HW Init fail r=%d\n", __func__, rc); - - dev_dbg(dev, "%s: initialize threaded irq=%d\n", __func__, cd->irq); - if (cd->cpdata->level_irq_udelay > 0) - /* use level triggered interrupts */ - irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT; - else - /* use edge triggered interrupts */ - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - - rc = request_threaded_irq(cd->irq, NULL, cyttsp4_irq, irq_flags, - dev_name(dev), cd); - if (rc < 0) { - dev_err(dev, "%s: Error, could not request irq\n", __func__); - goto error_request_irq; - } - - /* Setup watchdog timer */ - timer_setup(&cd->watchdog_timer, cyttsp4_watchdog_timer, 0); - - /* - * call startup directly to ensure that the device - * is tested before leaving the probe - */ - rc = cyttsp4_startup(cd); - - /* Do not fail probe if startup fails but the device is detected */ - if (rc < 0 && cd->mode == CY_MODE_UNKNOWN) { - dev_err(cd->dev, "%s: Fail initial startup r=%d\n", - __func__, rc); - goto error_startup; - } - - rc = cyttsp4_mt_probe(cd); - if (rc < 0) { - dev_err(dev, "%s: Error, fail mt probe\n", __func__); - goto error_startup; - } - - pm_runtime_enable(dev); - - return cd; - -error_startup: - cancel_work_sync(&cd->startup_work); - cyttsp4_stop_wd_timer(cd); - pm_runtime_disable(dev); - cyttsp4_free_si_ptrs(cd); - free_irq(cd->irq, cd); -error_request_irq: - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); -error_free_xfer: - kfree(cd->xfer_buf); -error_free_cd: - kfree(cd); -error_alloc_data: -error_no_pdata: - dev_err(dev, "%s failed.\n", __func__); - return ERR_PTR(rc); -} -EXPORT_SYMBOL_GPL(cyttsp4_probe); - -static void cyttsp4_mt_release(struct cyttsp4_mt_data *md) -{ - input_unregister_device(md->input); - input_set_drvdata(md->input, NULL); -} - -int cyttsp4_remove(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - - cyttsp4_mt_release(&cd->md); - - /* - * Suspend the device before freeing the startup_work and stopping - * the watchdog since sleep function restarts watchdog on failure - */ - pm_runtime_suspend(dev); - pm_runtime_disable(dev); - - cancel_work_sync(&cd->startup_work); - - cyttsp4_stop_wd_timer(cd); - - free_irq(cd->irq, cd); - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); - cyttsp4_free_si_ptrs(cd); - kfree(cd); - return 0; -} -EXPORT_SYMBOL_GPL(cyttsp4_remove); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen core driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h deleted file mode 100644 index 6262f6e45075..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.h +++ /dev/null @@ -1,448 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * cyttsp4_core.h - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#ifndef _LINUX_CYTTSP4_CORE_H -#define _LINUX_CYTTSP4_CORE_H - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/input.h> -#include <linux/kernel.h> -#include <linux/limits.h> -#include <linux/module.h> -#include <linux/stringify.h> -#include <linux/types.h> -#include <linux/platform_data/cyttsp4.h> - -#define CY_REG_BASE 0x00 - -#define CY_POST_CODEL_WDG_RST 0x01 -#define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02 -#define CY_POST_CODEL_PANEL_TEST_FAIL 0x04 - -#define CY_NUM_BTN_PER_REG 4 - -/* touch record system information offset masks and shifts */ -#define CY_BYTE_OFS_MASK 0x1F -#define CY_BOFS_MASK 0xE0 -#define CY_BOFS_SHIFT 5 - -#define CY_TMA1036_TCH_REC_SIZE 6 -#define CY_TMA4XX_TCH_REC_SIZE 9 -#define CY_TMA1036_MAX_TCH 0x0E -#define CY_TMA4XX_MAX_TCH 0x1E - -#define CY_NORMAL_ORIGIN 0 /* upper, left corner */ -#define CY_INVERT_ORIGIN 1 /* lower, right corner */ - -/* helpers */ -#define GET_NUM_TOUCHES(x) ((x) & 0x1F) -#define IS_LARGE_AREA(x) ((x) & 0x20) -#define IS_BAD_PKT(x) ((x) & 0x20) -#define IS_BOOTLOADER(hst_mode, reset_detect) \ - ((hst_mode) & 0x01 || (reset_detect) != 0) -#define IS_TMO(t) ((t) == 0) - - -enum cyttsp_cmd_bits { - CY_CMD_COMPLETE = (1 << 6), -}; - -/* Timeout in ms. */ -#define CY_WATCHDOG_TIMEOUT 1000 - -#define CY_MAX_PRINT_SIZE 512 -#ifdef VERBOSE_DEBUG -#define CY_MAX_PRBUF_SIZE PIPE_BUF -#define CY_PR_TRUNCATED " truncated..." -#endif - -enum cyttsp4_ic_grpnum { - CY_IC_GRPNUM_RESERVED, - CY_IC_GRPNUM_CMD_REGS, - CY_IC_GRPNUM_TCH_REP, - CY_IC_GRPNUM_DATA_REC, - CY_IC_GRPNUM_TEST_REC, - CY_IC_GRPNUM_PCFG_REC, - CY_IC_GRPNUM_TCH_PARM_VAL, - CY_IC_GRPNUM_TCH_PARM_SIZE, - CY_IC_GRPNUM_RESERVED1, - CY_IC_GRPNUM_RESERVED2, - CY_IC_GRPNUM_OPCFG_REC, - CY_IC_GRPNUM_DDATA_REC, - CY_IC_GRPNUM_MDATA_REC, - CY_IC_GRPNUM_TEST_REGS, - CY_IC_GRPNUM_BTN_KEYS, - CY_IC_GRPNUM_TTHE_REGS, - CY_IC_GRPNUM_NUM -}; - -enum cyttsp4_int_state { - CY_INT_NONE, - CY_INT_IGNORE = (1 << 0), - CY_INT_MODE_CHANGE = (1 << 1), - CY_INT_EXEC_CMD = (1 << 2), - CY_INT_AWAKE = (1 << 3), -}; - -enum cyttsp4_mode { - CY_MODE_UNKNOWN, - CY_MODE_BOOTLOADER = (1 << 1), - CY_MODE_OPERATIONAL = (1 << 2), - CY_MODE_SYSINFO = (1 << 3), - CY_MODE_CAT = (1 << 4), - CY_MODE_STARTUP = (1 << 5), - CY_MODE_LOADER = (1 << 6), - CY_MODE_CHANGE_MODE = (1 << 7), - CY_MODE_CHANGED = (1 << 8), - CY_MODE_CMD_COMPLETE = (1 << 9), -}; - -enum cyttsp4_sleep_state { - SS_SLEEP_OFF, - SS_SLEEP_ON, - SS_SLEEPING, - SS_WAKING, -}; - -enum cyttsp4_startup_state { - STARTUP_NONE, - STARTUP_QUEUED, - STARTUP_RUNNING, -}; - -#define CY_NUM_REVCTRL 8 -struct cyttsp4_cydata { - u8 ttpidh; - u8 ttpidl; - u8 fw_ver_major; - u8 fw_ver_minor; - u8 revctrl[CY_NUM_REVCTRL]; - u8 blver_major; - u8 blver_minor; - u8 jtag_si_id3; - u8 jtag_si_id2; - u8 jtag_si_id1; - u8 jtag_si_id0; - u8 mfgid_sz; - u8 cyito_idh; - u8 cyito_idl; - u8 cyito_verh; - u8 cyito_verl; - u8 ttsp_ver_major; - u8 ttsp_ver_minor; - u8 device_info; - u8 mfg_id[]; -} __packed; - -struct cyttsp4_test { - u8 post_codeh; - u8 post_codel; -} __packed; - -struct cyttsp4_pcfg { - u8 electrodes_x; - u8 electrodes_y; - u8 len_xh; - u8 len_xl; - u8 len_yh; - u8 len_yl; - u8 res_xh; - u8 res_xl; - u8 res_yh; - u8 res_yl; - u8 max_zh; - u8 max_zl; - u8 panel_info0; -} __packed; - -struct cyttsp4_tch_rec_params { - u8 loc; - u8 size; -} __packed; - -#define CY_NUM_TCH_FIELDS 7 -#define CY_NUM_EXT_TCH_FIELDS 3 -struct cyttsp4_opcfg { - u8 cmd_ofs; - u8 rep_ofs; - u8 rep_szh; - u8 rep_szl; - u8 num_btns; - u8 tt_stat_ofs; - u8 obj_cfg0; - u8 max_tchs; - u8 tch_rec_size; - struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS]; - u8 btn_rec_size; /* btn record size (in bytes) */ - u8 btn_diff_ofs; /* btn data loc, diff counts */ - u8 btn_diff_size; /* btn size of diff counts (in bits) */ - struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS]; -} __packed; - -struct cyttsp4_sysinfo_ptr { - struct cyttsp4_cydata *cydata; - struct cyttsp4_test *test; - struct cyttsp4_pcfg *pcfg; - struct cyttsp4_opcfg *opcfg; - struct cyttsp4_ddata *ddata; - struct cyttsp4_mdata *mdata; -} __packed; - -struct cyttsp4_sysinfo_data { - u8 hst_mode; - u8 reserved; - u8 map_szh; - u8 map_szl; - u8 cydata_ofsh; - u8 cydata_ofsl; - u8 test_ofsh; - u8 test_ofsl; - u8 pcfg_ofsh; - u8 pcfg_ofsl; - u8 opcfg_ofsh; - u8 opcfg_ofsl; - u8 ddata_ofsh; - u8 ddata_ofsl; - u8 mdata_ofsh; - u8 mdata_ofsl; -} __packed; - -enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */ - CY_TCH_X, /* X */ - CY_TCH_Y, /* Y */ - CY_TCH_P, /* P (Z) */ - CY_TCH_T, /* TOUCH ID */ - CY_TCH_E, /* EVENT ID */ - CY_TCH_O, /* OBJECT ID */ - CY_TCH_W, /* SIZE */ - CY_TCH_MAJ, /* TOUCH_MAJOR */ - CY_TCH_MIN, /* TOUCH_MINOR */ - CY_TCH_OR, /* ORIENTATION */ - CY_TCH_NUM_ABS -}; - -struct cyttsp4_touch { - int abs[CY_TCH_NUM_ABS]; -}; - -struct cyttsp4_tch_abs_params { - size_t ofs; /* abs byte offset */ - size_t size; /* size in bits */ - size_t max; /* max value */ - size_t bofs; /* bit offset */ -}; - -struct cyttsp4_sysinfo_ofs { - size_t chip_type; - size_t cmd_ofs; - size_t rep_ofs; - size_t rep_sz; - size_t num_btns; - size_t num_btn_regs; /* ceil(num_btns/4) */ - size_t tt_stat_ofs; - size_t tch_rec_size; - size_t obj_cfg0; - size_t max_tchs; - size_t mode_size; - size_t data_size; - size_t map_sz; - size_t max_x; - size_t x_origin; /* left or right corner */ - size_t max_y; - size_t y_origin; /* upper or lower corner */ - size_t max_p; - size_t cydata_ofs; - size_t test_ofs; - size_t pcfg_ofs; - size_t opcfg_ofs; - size_t ddata_ofs; - size_t mdata_ofs; - size_t cydata_size; - size_t test_size; - size_t pcfg_size; - size_t opcfg_size; - size_t ddata_size; - size_t mdata_size; - size_t btn_keys_size; - struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; - size_t btn_rec_size; /* btn record size (in bytes) */ - size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ - size_t btn_diff_size;/* btn size of diff counts (in bits) */ -}; - -enum cyttsp4_btn_state { - CY_BTN_RELEASED, - CY_BTN_PRESSED, - CY_BTN_NUM_STATE -}; - -struct cyttsp4_btn { - bool enabled; - int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */ - int key_code; -}; - -struct cyttsp4_sysinfo { - bool ready; - struct cyttsp4_sysinfo_data si_data; - struct cyttsp4_sysinfo_ptr si_ptrs; - struct cyttsp4_sysinfo_ofs si_ofs; - struct cyttsp4_btn *btn; /* button states */ - u8 *btn_rec_data; /* button diff count data */ - u8 *xy_mode; /* operational mode and status regs */ - u8 *xy_data; /* operational touch regs */ -}; - -struct cyttsp4_mt_data { - struct cyttsp4_mt_platform_data *pdata; - struct cyttsp4_sysinfo *si; - struct input_dev *input; - struct mutex report_lock; - bool is_suspended; - char phys[NAME_MAX]; - int num_prv_tch; -}; - -struct cyttsp4 { - struct device *dev; - struct mutex system_lock; - struct mutex adap_lock; - enum cyttsp4_mode mode; - enum cyttsp4_sleep_state sleep_state; - enum cyttsp4_startup_state startup_state; - int int_status; - wait_queue_head_t wait_q; - int irq; - struct work_struct startup_work; - struct work_struct watchdog_work; - struct timer_list watchdog_timer; - struct cyttsp4_sysinfo sysinfo; - void *exclusive_dev; - int exclusive_waits; - atomic_t ignore_irq; - bool invalid_touch_app; - struct cyttsp4_mt_data md; - struct cyttsp4_platform_data *pdata; - struct cyttsp4_core_platform_data *cpdata; - const struct cyttsp4_bus_ops *bus_ops; - u8 *xfer_buf; -#ifdef VERBOSE_DEBUG - u8 pr_buf[CY_MAX_PRBUF_SIZE]; -#endif -}; - -struct cyttsp4_bus_ops { - u16 bustype; - int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - const void *values); - int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - void *values); -}; - -enum cyttsp4_hst_mode_bits { - CY_HST_TOGGLE = (1 << 7), - CY_HST_MODE_CHANGE = (1 << 3), - CY_HST_MODE = (7 << 4), - CY_HST_OPERATE = (0 << 4), - CY_HST_SYSINFO = (1 << 4), - CY_HST_CAT = (2 << 4), - CY_HST_LOWPOW = (1 << 2), - CY_HST_SLEEP = (1 << 1), - CY_HST_RESET = (1 << 0), -}; - -/* abs settings */ -#define CY_IGNORE_VALUE 0xFFFF - -/* abs signal capabilities offsets in the frameworks array */ -enum cyttsp4_sig_caps { - CY_SIGNAL_OST, - CY_MIN_OST, - CY_MAX_OST, - CY_FUZZ_OST, - CY_FLAT_OST, - CY_NUM_ABS_SET /* number of signal capability fields */ -}; - -/* abs axis signal offsets in the framworks array */ -enum cyttsp4_sig_ost { - CY_ABS_X_OST, - CY_ABS_Y_OST, - CY_ABS_P_OST, - CY_ABS_W_OST, - CY_ABS_ID_OST, - CY_ABS_MAJ_OST, - CY_ABS_MIN_OST, - CY_ABS_OR_OST, - CY_NUM_ABS_OST /* number of abs signals */ -}; - -enum cyttsp4_flags { - CY_FLAG_NONE = 0x00, - CY_FLAG_HOVER = 0x04, - CY_FLAG_FLIP = 0x08, - CY_FLAG_INV_X = 0x10, - CY_FLAG_INV_Y = 0x20, - CY_FLAG_VKEYS = 0x40, -}; - -enum cyttsp4_object_id { - CY_OBJ_STANDARD_FINGER, - CY_OBJ_LARGE_OBJECT, - CY_OBJ_STYLUS, - CY_OBJ_HOVER, -}; - -enum cyttsp4_event_id { - CY_EV_NO_EVENT, - CY_EV_TOUCHDOWN, - CY_EV_MOVE, /* significant displacement (> act dist) */ - CY_EV_LIFTOFF, /* record reports last position */ -}; - -/* x-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_X_MASK 0x7F - -/* y-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_Y_MASK 0x7F - -/* x-axis, 0:origin is on left side of panel, 1: right */ -#define CY_PCFG_ORIGIN_X_MASK 0x80 - -/* y-axis, 0:origin is on top side of panel, 1: bottom */ -#define CY_PCFG_ORIGIN_Y_MASK 0x80 - -static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size, - void *buf) -{ - return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf); -} - -static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size, - const void *buf) -{ - return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf); -} - -extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size); -extern int cyttsp4_remove(struct cyttsp4 *ts); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); -extern const struct dev_pm_ops cyttsp4_pm_ops; - -#endif /* _LINUX_CYTTSP4_CORE_H */ diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c deleted file mode 100644 index da32c151def5..000000000000 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" - -#include <linux/i2c.h> -#include <linux/input.h> - -#define CYTTSP4_I2C_DATA_SIZE (3 * 256) - -static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = { - .bustype = BUS_I2C, - .write = cyttsp_i2c_write_block_data, - .read = cyttsp_i2c_read_block_data, -}; - -static int cyttsp4_i2c_probe(struct i2c_client *client) -{ - struct cyttsp4 *ts; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "I2C functionality not Supported\n"); - return -EIO; - } - - ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq, - CYTTSP4_I2C_DATA_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_i2c_remove(struct i2c_client *client) -{ - struct cyttsp4 *ts = i2c_get_clientdata(client); - - cyttsp4_remove(ts); -} - -static const struct i2c_device_id cyttsp4_i2c_id[] = { - { CYTTSP4_I2C_NAME }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id); - -static struct i2c_driver cyttsp4_i2c_driver = { - .driver = { - .name = CYTTSP4_I2C_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_i2c_probe, - .remove = cyttsp4_i2c_remove, - .id_table = cyttsp4_i2c_id, -}; - -module_i2c_driver(cyttsp4_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c deleted file mode 100644 index 944fbbe9113e..000000000000 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Source for: - * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" - -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/spi/spi.h> - -#define CY_SPI_WR_OP 0x00 /* r/~w */ -#define CY_SPI_RD_OP 0x01 -#define CY_SPI_BITS_PER_WORD 8 -#define CY_SPI_A8_BIT 0x02 -#define CY_SPI_WR_HEADER_BYTES 2 -#define CY_SPI_RD_HEADER_BYTES 1 -#define CY_SPI_CMD_BYTES 2 -#define CY_SPI_SYNC_BYTE 0 -#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ -#define CY_SPI_DATA_SIZE (2 * 256) - -#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) - -static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, - u8 op, u16 reg, u8 *buf, int length) -{ - struct spi_device *spi = to_spi_device(dev); - struct spi_message msg; - struct spi_transfer xfer[2]; - u8 *wr_buf = &xfer_buf[0]; - u8 rd_buf[CY_SPI_CMD_BYTES]; - int retval; - int i; - - if (length > CY_SPI_DATA_SIZE) { - dev_err(dev, "%s: length %d is too big.\n", - __func__, length); - return -EINVAL; - } - - memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); - memset(rd_buf, 0, CY_SPI_CMD_BYTES); - - wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); - if (op == CY_SPI_WR_OP) { - wr_buf[1] = reg & 0xFF; - if (length > 0) - memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); - } - - memset(xfer, 0, sizeof(xfer)); - spi_message_init(&msg); - - /* - We set both TX and RX buffers because Cypress TTSP - requires full duplex operation. - */ - xfer[0].tx_buf = wr_buf; - xfer[0].rx_buf = rd_buf; - switch (op) { - case CY_SPI_WR_OP: - xfer[0].len = length + CY_SPI_CMD_BYTES; - spi_message_add_tail(&xfer[0], &msg); - break; - - case CY_SPI_RD_OP: - xfer[0].len = CY_SPI_RD_HEADER_BYTES; - spi_message_add_tail(&xfer[0], &msg); - - xfer[1].rx_buf = buf; - xfer[1].len = length; - spi_message_add_tail(&xfer[1], &msg); - break; - - default: - dev_err(dev, "%s: bad operation code=%d\n", __func__, op); - return -EINVAL; - } - - retval = spi_sync(spi, &msg); - if (retval < 0) { - dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", - __func__, retval, xfer[1].len, op); - - /* - * do not return here since was a bad ACK sequence - * let the following ACK check handle any errors and - * allow silent retries - */ - } - - if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { - dev_dbg(dev, "%s: operation %d failed\n", __func__, op); - - for (i = 0; i < CY_SPI_CMD_BYTES; i++) - dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", - __func__, i, rd_buf[i]); - for (i = 0; i < length; i++) - dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", - __func__, i, buf[i]); - - return -EIO; - } - - return 0; -} - -static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *data) -{ - int rc; - - rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); - if (rc) - return rc; - else - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, - length); -} - -static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *data) -{ - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, - length); -} - -static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { - .bustype = BUS_SPI, - .write = cyttsp_spi_write_block_data, - .read = cyttsp_spi_read_block_data, -}; - -static int cyttsp4_spi_probe(struct spi_device *spi) -{ - struct cyttsp4 *ts; - int error; - - /* Set up SPI*/ - spi->bits_per_word = CY_SPI_BITS_PER_WORD; - spi->mode = SPI_MODE_0; - error = spi_setup(spi); - if (error < 0) { - dev_err(&spi->dev, "%s: SPI setup error %d\n", - __func__, error); - return error; - } - - ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, - CY_SPI_DATA_BUF_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_spi_remove(struct spi_device *spi) -{ - struct cyttsp4 *ts = spi_get_drvdata(spi); - cyttsp4_remove(ts); -} - -static struct spi_driver cyttsp4_spi_driver = { - .driver = { - .name = CYTTSP4_SPI_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_spi_probe, - .remove = cyttsp4_spi_remove, -}; - -module_spi_driver(cyttsp4_spi_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); -MODULE_AUTHOR("Cypress"); -MODULE_ALIAS("spi:cyttsp4"); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index cd3b80401970..40a605d20285 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -136,10 +136,6 @@ struct cyttsp { struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); extern const struct dev_pm_ops cyttsp_pm_ops; #endif /* __CYTTSP_CORE_H__ */ diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index bf13b3448a6b..cb15600549cd 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -22,6 +22,61 @@ #define CY_I2C_DATA_SIZE 128 +static int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = 1, + .buf = &addr_lo, + }, + { + .addr = client_addr, + .flags = I2C_M_RD, + .len = length, + .buf = values, + }, + }; + int retval; + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + +static int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, const void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = length + 1, + .buf = xfer_buf, + }, + }; + int retval; + + xfer_buf[0] = addr_lo; + memcpy(&xfer_buf[1], values, length); + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { .bustype = BUS_I2C, .write = cyttsp_i2c_write_block_data, diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c deleted file mode 100644 index 7e752fb9fad7..000000000000 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c_common.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx3xx and Txx4xx parts. - * Supported parts include: - * CY8CTST341 - * CY8CTMA340 - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include <linux/device.h> -#include <linux/export.h> -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/types.h> - -#include "cyttsp4_core.h" - -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = 1, - .buf = &addr_lo, - }, - { - .addr = client_addr, - .flags = I2C_M_RD, - .len = length, - .buf = values, - }, - }; - int retval; - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data); - -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = length + 1, - .buf = xfer_buf, - }, - }; - int retval; - - xfer_buf[0] = addr_lo; - memcpy(&xfer_buf[1], values, length); - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); - - -MODULE_DESCRIPTION("Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cypress"); |