From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c | 413 ++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c (limited to 'drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c') diff --git a/drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c b/drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c new file mode 100644 index 00000000..1c90ca70 --- /dev/null +++ b/drivers/input/touchscreen/ist30xxb/ist30xxb_sys.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Return value of Error + * EPERM : 1 (Operation not permitted) + * ENOENT : 2 (No such file or directory) + * EIO : 5 (I/O error) + * ENXIO : 6 (No such device or address) + * EINVAL : 22 (Invalid argument) + *****************************************************************************/ + +extern struct ist30xx_data *ts_data; +#if IST30XX_NOISE_MODE +#endif +const u32 pos_cmd = cpu_to_be32(CMD_GET_COORD); +struct i2c_msg pos_msg[READ_CMD_MSG_LEN] = { + { + .flags = 0, + .len = IST30XX_ADDR_LEN, + .buf = (u8 *)&pos_cmd, + }, + { .flags = I2C_M_RD, }, +}; + +int ist30xx_get_position(struct i2c_client *client, u32 *buf, u16 len) +{ + int ret, i; + + pos_msg[0].addr = client->addr; + pos_msg[1].addr = client->addr; + pos_msg[1].len = len * IST30XX_DATA_LEN, + pos_msg[1].buf = (u8 *)buf, + + ret = i2c_transfer(client->adapter, pos_msg, READ_CMD_MSG_LEN); + if (ret != READ_CMD_MSG_LEN) { + tsp_err("%s: i2c failed (%d)\n", __func__, ret); + return -EIO; + } + + for (i = 0; i < len; i++) + buf[i] = cpu_to_be32(buf[i]); + + return 0; +} + +int ist30xx_cmd_run_device(struct i2c_client *client) +{ + int ret = -EIO; + + ist30xx_reset(); + ret = ist30xx_write_cmd(client, CMD_RUN_DEVICE, 0); + msleep(10); + + return ret; +} + +int ist30xx_cmd_start_scan(struct i2c_client *client) +{ + int ret; + + ret = ist30xx_write_cmd(client, CMD_START_SCAN, 0); + + msleep(100); + +#if IST30XX_NOISE_MODE + ts_data->status.noise_mode = true; +#endif + + return ret; +} + +int ist30xx_cmd_calibrate(struct i2c_client *client) +{ + int ret = ist30xx_write_cmd(client, CMD_CALIBRATE, 0); + + tsp_info("%s\n", __func__); + + msleep(100); + + return ret; +} + +int ist30xx_cmd_check_calib(struct i2c_client *client) +{ + int ret = ist30xx_write_cmd(client, CMD_CHECK_CALIB, 0); + + tsp_info("*** Check Calibration cmd ***\n"); + + msleep(20); + + return ret; +} + +int ist30xx_cmd_update(struct i2c_client *client, int cmd) +{ + u32 val = (cmd == CMD_ENTER_FW_UPDATE ? CMD_FW_UPDATE_MAGIC : 0); + int ret = ist30xx_write_cmd(client, cmd, val); + + msleep(10); + + return ret; +} + +int ist30xx_cmd_reg(struct i2c_client *client, int cmd) +{ + int ret = ist30xx_write_cmd(client, cmd, 0); + + if (cmd == CMD_ENTER_REG_ACCESS) + msleep(100); + else if (cmd == CMD_EXIT_REG_ACCESS) + msleep(10); + + return ret; +} + + +int ist30xx_read_cmd(struct i2c_client *client, u32 cmd, u32 *buf) +{ + int ret; + u32 le_reg = cpu_to_be32(cmd); + + struct i2c_msg msg[READ_CMD_MSG_LEN] = { + { + .addr = client->addr, + .flags = 0, + .len = IST30XX_ADDR_LEN, + .buf = (u8 *)&le_reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = IST30XX_DATA_LEN, + .buf = (u8 *)buf, + }, + }; + + ret = i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN); + if (ret != READ_CMD_MSG_LEN) { + tsp_err("%s: i2c failed (%d), cmd: %x\n", __func__, ret, cmd); + return -EIO; + } + *buf = cpu_to_be32(*buf); + + return 0; +} + + +int ist30xx_write_cmd(struct i2c_client *client, u32 cmd, u32 val) +{ + int ret; + struct i2c_msg msg; + u8 msg_buf[IST30XX_ADDR_LEN + IST30XX_DATA_LEN]; + + put_unaligned_be32(cmd, msg_buf); + put_unaligned_be32(val, msg_buf + IST30XX_ADDR_LEN); + + msg.addr = client->addr; + msg.flags = 0; + msg.len = IST30XX_ADDR_LEN + IST30XX_DATA_LEN; + msg.buf = msg_buf; + + ret = i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN); + if (ret != WRITE_CMD_MSG_LEN) { + tsp_err("%s: i2c failed (%d), cmd: %x(%x)\n", __func__, ret, cmd, val); + return -EIO; + } + + return 0; +} + +#define TSP_PWR_LDO_GPIO 41 +#define GPIO_TSP_SCL 35 +#define GPIO_TSP_SDA 40 +static struct regulator *touch_regulator; +#if defined(CONFIG_MACH_CORSICA_VE) || defined(CONFIG_MACH_POCKET2) || defined(CONFIG_MACH_VIVALTO) +static void ts_power_enable(int en) +{ + int ret=0; + struct regulator *touch_regulator_1v8 = NULL; + struct regulator *touch_regulator_3v3 = NULL; + + tsp_info("[TSP] %s, %d\n", __func__, en ); + + touch_regulator_1v8 = regulator_get(NULL,"vddsim2"); + if (IS_ERR(touch_regulator_1v8)) { + touch_regulator_1v8 = NULL; + tsp_info("get touch_regulator_1v8 regulator error\n"); + return; + } + +#ifdef CONFIG_TSP_0_1_A + touch_regulator_3v3 = regulator_get(NULL,"vddcon"); +#else + touch_regulator_3v3 = regulator_get(NULL,"vddcammot"); +#endif + if (IS_ERR(touch_regulator_3v3)) { + touch_regulator_1v8 = NULL; + tsp_info("get touch_regulator_3v3 regulator error\n"); + return; + } + + if(en) { + regulator_set_voltage(touch_regulator_1v8, 1800000, 1800000); + ret = regulator_enable(touch_regulator_1v8); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_1v8 enable failed (%d)\n",__func__, ret); + } + + regulator_set_voltage(touch_regulator_3v3, 3300000, 3300000); + ret = regulator_enable(touch_regulator_3v3); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v3 enable failed (%d)\n",__func__, ret); + } + } + else + { + ret = regulator_disable(touch_regulator_1v8); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 disable failed (%d)\n",__func__, ret); + } + + ret = regulator_disable(touch_regulator_3v3); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 disable failed (%d)\n",__func__, ret); + } + } +} +#elif defined(CONFIG_MACH_YOUNG2) +static void ts_power_enable(int en) +{ + int ret=0; + struct regulator *touch_regulator_3v0 = NULL; + + tsp_info("[TSP] %s, %d\n", __func__, en ); + + touch_regulator_3v0 = regulator_get(NULL,"vddsim2"); + if (IS_ERR(touch_regulator_3v0)) { + touch_regulator_3v0 = NULL; + tsp_info("get touch_regulator_3v0 regulator error\n"); + return; + } + if(en) { + regulator_set_voltage(touch_regulator_3v0, 3000000, 3000000); + ret = regulator_enable(touch_regulator_3v0); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 enable failed (%d)\n",__func__, ret); + } + } + else + { + ret = regulator_disable(touch_regulator_3v0); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 disable failed (%d)\n",__func__, ret); + } + } +} +#elif defined(CONFIG_MACH_PIKEAYOUNG2DTV) +static void ts_power_enable(int en) +{ + int ret=0; + struct regulator *touch_regulator_1v8 = NULL; + struct regulator *touch_regulator_3v3 = NULL; + + tsp_info("[TSP] %s, %d\n", __func__, en ); + + touch_regulator_3v3 = regulator_get(NULL,"vddsim2"); + if (IS_ERR(touch_regulator_3v3)) { + touch_regulator_3v3 = NULL; + tsp_info("get touch_regulator_1v8 regulator error\n"); + return; + } + + touch_regulator_1v8 = regulator_get(NULL,"vdd18"); + + if (IS_ERR(touch_regulator_1v8)) { + touch_regulator_1v8 = NULL; + tsp_info("get touch_regulator_1v8 regulator error\n"); + return; + } + + if(en) { + regulator_set_voltage(touch_regulator_1v8, 1800000, 1800000); + ret = regulator_enable(touch_regulator_1v8); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_1v8 enable failed (%d)\n",__func__, ret); + } + + regulator_set_voltage(touch_regulator_3v3, 3000000, 3000000); + ret = regulator_enable(touch_regulator_3v3); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 enable failed (%d)\n",__func__, ret); + } + } + else + { + ret = regulator_disable(touch_regulator_3v3); + if (ret) { + tsp_info(KERN_ERR "%s: touch_regulator_3v0 disable failed (%d)\n",__func__, ret); + } + } +} +#endif +int ist30xx_power_on(void) +{ + if (ts_data->status.power != 1) { + tsp_info("%s()\n", __func__); + /* VDD enable */ + msleep(5); + /* VDDIO enable */ + ts_power_enable(1); + msleep(100); + ts_data->status.power = 1; + } + + return 0; +} + + +int ist30xx_power_off(void) +{ + if (ts_data->status.power != 0) { + tsp_info("%s()\n", __func__); + /* VDDIO disable */ + msleep(5); + + /* VDD disable */ + ts_power_enable(0); + msleep(50); + ts_data->status.power = 0; + ts_data->status.noise_mode = false; + } + + return 0; +} + + +int ist30xx_reset(void) +{ + tsp_info("%s()\n", __func__); + ist30xx_power_off(); + msleep(10); + ist30xx_power_on(); + + ts_data->status.power = 1; + return 0; +} + + +int ist30xx_internal_suspend(struct ist30xx_data *data) +{ + ist30xx_power_off(); + return 0; +} + + +int ist30xx_internal_resume(struct ist30xx_data *data) +{ + ist30xx_power_on(); + ist30xx_write_cmd(data->client, CMD_RUN_DEVICE, 0); + msleep(10); + return 0; +} + + +int ist30xx_init_system(void) +{ + int ret; + + // TODO : place additional code here. +#if 1 + ret = ist30xx_power_on(); + if (ret) { + printk("[TSP] %s: ist30xx_power_on failed (%d)\n", __func__, ret); + return -EIO; + } +#endif + +#if 0 + ret = ist30xx_reset(); + if (ret) { + tsp_err("%s: ist30xx_reset failed (%d)\n", __func__, ret); + return -EIO; + } +#endif + + return 0; +} -- cgit v1.3.1