--- /dev/null
+/* drivers/input/ts/chips/gt828.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <linux/input/mt.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif \r
+#include <linux/ts-auto.h>\r
+ \r
+ \r
+#if 0\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+//Register define\r
+#define GTP_READ_COOR_ADDR 0x0F40\r
+#define GTP_REG_SLEEP 0x0FF2\r
+#define GTP_REG_SENSOR_ID 0x0FF5\r
+#define GTP_REG_CONFIG_DATA 0x0F80\r
+#define GTP_REG_VERSION 0x0F7D\r
+\r
+\r
+\r
+/****************operate according to ts chip:start************/\r
+\r
+int ts_i2c_end_cmd(struct i2c_client *client)\r
+{\r
+ int result = -1;\r
+ char end_cmd_data[2]={0x80, 0x00};\r
+\r
+ result = ts_tx_data(client, end_cmd_data, 2);\r
+ if(result < 0)\r
+ {\r
+ printk("%s:fail to init ts\n",__func__);\r
+ return result;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+\r
+static int ts_active(struct i2c_client *client, int enable)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client); \r
+ int result = 0;\r
+\r
+ if(enable)\r
+ {\r
+ gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW);\r
+ msleep(10);\r
+ gpio_direction_output(ts->pdata->reset_pin, GPIO_HIGH);\r
+ msleep(100);\r
+ }\r
+ else\r
+ {\r
+ gpio_direction_output(ts->pdata->reset_pin, GPIO_LOW); \r
+ }\r
+ \r
+ \r
+ return result;\r
+}\r
+\r
+static int ts_init(struct i2c_client *client)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client);\r
+ int result = 0;\r
+ char version_data[4] = {ts->ops->version_reg >> 8, ts->ops->version_reg & 0xff};\r
+ \r
+ //read version\r
+ result = ts_rx_data(client, version_data, 4);\r
+ if(result < 0)\r
+ {\r
+ printk("%s:fail to init ts\n",__func__);\r
+ return result;\r
+ }\r
+ version_data[4]='\0';\r
+ \r
+ result = ts_i2c_end_cmd(client);\r
+ if(result < 0)\r
+ {\r
+ printk("%s:fail to end ts\n",__func__);\r
+ //return result;\r
+ }\r
+ \r
+ printk("%s:%s version is %s\n",__func__,ts->ops->name, version_data);\r
+\r
+ //init some register\r
+ //to do\r
+ \r
+ return result;\r
+}\r
+\r
+\r
+static int ts_report_value(struct i2c_client *client)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client); \r
+ struct ts_platform_data *pdata = ts->pdata;\r
+ struct ts_event *event = &ts->event;\r
+ unsigned char buf[2 + 2 + 5 * 5 + 1] = {0};\r
+ int result = 0 , i = 0, off = 0, id = 0;\r
+ int finger = 0;\r
+ int checksum = 0;\r
+\r
+ buf[0] = ts->ops->read_reg >> 8;\r
+ buf[1] = ts->ops->read_reg & 0xff;\r
+ result = ts_rx_data_word(client, buf, ts->ops->read_len);\r
+ if(result < 0)\r
+ {\r
+ printk("%s:fail to init ts\n",__func__);\r
+ return result;\r
+ }\r
+\r
+ result = ts_i2c_end_cmd(client);\r
+ if(result < 0)\r
+ {\r
+ printk("%s:fail to end ts\n",__func__);\r
+ return result;\r
+ }\r
+ \r
+ //for(i=0; i<ts->ops->read_len; i++)\r
+ //DBG("buf[%d]=0x%x\n",i,buf[i]);\r
+ finger = buf[0];\r
+ if((finger & 0xc0) != 0x80)\r
+ {\r
+ DBG("%s:data not ready!\n",__func__);\r
+ return -1;\r
+ }\r
+\r
+\r
+#if 0 \r
+ event->touch_point = 0;\r
+ for(i=0; i<ts->ops->max_point; i++)\r
+ {\r
+ if(finger & (1<<i))\r
+ event->touch_point++;\r
+ }\r
+\r
+ check_sum = 0;\r
+ for ( i = 0; i < 5 * event->touch_point; i++)\r
+ {\r
+ check_sum += buf[2+i];\r
+ }\r
+ if (check_sum != buf[5 * event->touch_point])\r
+ {\r
+ DBG("%s:check sum error!\n",__func__);\r
+ return -1;\r
+ }\r
+#endif\r
+ \r
+ for(i = 0; i<ts->ops->max_point; i++)\r
+ {\r
+ off = i*5+2;\r
+\r
+ id = i; \r
+ event->point[id].id = id;\r
+ event->point[id].status = !!(finger & (1 << i));\r
+ event->point[id].x = (buf[off+0]<<8) | buf[off+1];\r
+ event->point[id].y = (buf[off+2]<<8) | buf[off+3];\r
+ event->point[id].press = buf[off+4]; \r
+ \r
+ if(ts->ops->xy_swap)\r
+ {\r
+ swap(event->point[id].x, event->point[id].y);\r
+ }\r
+\r
+ if(ts->ops->x_revert)\r
+ {\r
+ event->point[id].x = ts->ops->pixel.max_x - event->point[id].x; \r
+ }\r
+\r
+ if(ts->ops->y_revert)\r
+ {\r
+ event->point[id].y = ts->ops->pixel.max_y - event->point[id].y;\r
+ }\r
+\r
+ if(event->point[id].status != 0)\r
+ { \r
+ input_mt_slot(ts->input_dev, event->point[id].id);\r
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, event->point[id].id);\r
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, event->point[id].press);\r
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, event->point[id].x);\r
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, event->point[id].y);\r
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);\r
+ DBG("%s:%s press down,id=%d,x=%d,y=%d\n",__func__,ts->ops->name, event->point[id].id, event->point[id].x,event->point[id].y);\r
+ }\r
+ else if ((event->point[id].status == 0) && (event->point[id].last_status != 0))\r
+ { \r
+ input_mt_slot(ts->input_dev, event->point[i].id); \r
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);\r
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);\r
+ DBG("%s:%s press up,id=%d\n",__func__,ts->ops->name, event->point[i].id);\r
+ }\r
+\r
+ event->point[i].last_status = event->point[i].status; \r
+ \r
+ }\r
+ \r
+ input_sync(ts->input_dev);\r
+\r
+ return 0;\r
+}\r
+\r
+static int ts_suspend(struct i2c_client *client)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client); \r
+ struct ts_platform_data *pdata = ts->pdata;\r
+\r
+ if(ts->ops->active)\r
+ ts->ops->active(client, 0);\r
+ \r
+ return 0;\r
+}\r
+\r
+\r
+\r
+\r
+static int ts_resume(struct i2c_client *client)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client); \r
+ struct ts_platform_data *pdata = ts->pdata;\r
+ \r
+ if(ts->ops->active)\r
+ ts->ops->active(client, 1);\r
+ return 0;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+struct ts_operate ts_gt828_ops = {\r
+ .name = "gt828",\r
+ .slave_addr = 0x5d,\r
+ .id_i2c = TS_ID_GT828, //i2c id number\r
+ .reg_size = 2,\r
+ .pixel = {1024,600},\r
+ .id_reg = GTP_REG_SENSOR_ID,\r
+ .id_data = TS_UNKNOW_DATA,\r
+ .version_reg = 0x0F7D,\r
+ .version_len = 0,\r
+ .version_data = NULL,\r
+ .read_reg = GTP_READ_COOR_ADDR, //read data\r
+ .read_len = 2 + 2 + 5 * 5 + 1, //data length\r
+ .trig = IRQF_TRIGGER_FALLING, \r
+ .max_point = 5,\r
+ .xy_swap = 0,\r
+ .x_revert = 0,\r
+ .y_revert = 0,\r
+ .range = {1024,600},\r
+ .irq_enable = 1,\r
+ .poll_delay_ms = 0,\r
+ .active = ts_active, \r
+ .init = ts_init,\r
+ .check_irq = NULL,\r
+ .report = ts_report_value,\r
+ .firmware = NULL,\r
+ .suspend = ts_suspend,\r
+ .resume = ts_resume,\r
+};\r
+\r
+/****************operate according to ts chip:end************/\r
+\r
+//function name should not be changed\r
+static struct ts_operate *ts_get_ops(void)\r
+{\r
+ return &ts_gt828_ops;\r
+}\r
+\r
+\r
+static int __init ts_gt828_init(void)\r
+{\r
+ struct ts_operate *ops = ts_get_ops();\r
+ int result = 0;\r
+ result = ts_register_slave(NULL, NULL, ts_get_ops); \r
+ DBG("%s\n",__func__);\r
+ return result;\r
+}\r
+\r
+static void __exit ts_gt828_exit(void)\r
+{\r
+ struct ts_operate *ops = ts_get_ops();\r
+ ts_unregister_slave(NULL, NULL, ts_get_ops);\r
+}\r
+\r
+\r
+subsys_initcall(ts_gt828_init);\r
+module_exit(ts_gt828_exit);\r
+\r
struct ts_private_data *ts =\r
(struct ts_private_data *) i2c_get_clientdata(client); \r
int result = 0;\r
- char temp = ops->id_reg;\r
+ char temp[4] = {ops->id_reg & 0xff};\r
int i = 0;\r
\r
DBG("%s:start\n",__func__);\r
if(ops->id_reg >= 0)\r
{\r
- for(i=0; i<1; i++)\r
+ for(i=0; i<2; i++)\r
{\r
- result = ts_rx_data(client, &temp, 1);\r
- *value = temp;\r
+ if(ops->reg_size == 2)\r
+ {\r
+ temp[0] = ops->id_reg >> 8;\r
+ temp[1] = ops->id_reg & 0xff;\r
+ result = ts_rx_data_word(client, &temp, 2);\r
+ *value = (temp[0] << 8) | temp[1];\r
+ }\r
+ else\r
+ {\r
+ result = ts_rx_data(client, &temp, 1);\r
+ *value = temp[0];\r
+ }\r
if(!result)\r
break;\r
+\r
}\r
\r
if(result)\r
}\r
\r
\r
+static int ts_get_version(struct ts_operate *ops, struct i2c_client *client)\r
+{\r
+ struct ts_private_data *ts =\r
+ (struct ts_private_data *) i2c_get_clientdata(client); \r
+ int result = 0;\r
+ char temp[TS_MAX_VER_LEN + 1] = {0};\r
+ int i = 0;\r
+ \r
+ DBG("%s:start\n",__func__);\r
+ \r
+ if(ops->version_reg >= 0)\r
+ {\r
+ if((ops->version_len < 0) || (ops->version_len > TS_MAX_VER_LEN))\r
+ {\r
+ printk("%s:version_len is error\n",__func__,ops->version_len);\r
+ ops->version_len = TS_MAX_VER_LEN;\r
+ }\r
+ \r
+ if(ops->reg_size == 2)\r
+ {\r
+ result = ts_rx_data_word(client, temp, ops->version_len);\r
+ }\r
+ else\r
+ {\r
+ result = ts_rx_data(client, temp, ops->version_len);\r
+ }\r
+ \r
+\r
+ if(result)\r
+ return result;\r
+ \r
+ if(ops->version_data)\r
+ {\r
+ for(i=0; i<ops->version_len; i++)\r
+ {\r
+ if(temp[i] == ops->version_data[i])\r
+ continue;\r
+ printk("%s:version %s is not %s\n",__func__,temp, ops->version_data);\r
+ result = -1;\r
+ }\r
+ }\r
+ \r
+ DBG("%s:%s version: %s\n",__func__,ops->name, temp);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+\r
static int ts_chip_init(struct i2c_client *client)\r
{\r
struct ts_private_data *ts =\r
}\r
\r
client->addr = ops->slave_addr; //use slave_addr of ops\r
- \r
+#if 0 \r
if(ops->active)\r
{\r
result = ops->active(client, TS_ENABLE);\r
if(result < 0)\r
{\r
- printk("%s:fail to init ts\n",__func__);\r
+ printk("%s:fail to active ts\n",__func__);\r
continue;\r
}\r
}\r
-\r
+#endif\r
result = ts_get_id(ops, client, &ts->devid);//get id\r
if(result < 0)\r
{ \r
printk("%s:fail to read %s devid:0x%x\n",__func__, ops->name, ts->devid); \r
continue;\r
}\r
+\r
+ result = ts_get_version(ops, client); //get version\r
+ if(result < 0)\r
+ { \r
+ printk("%s:fail to read %s version\n",__func__, ops->name); \r
+ continue;\r
+ }\r
\r
ts->ops = ops; //save ops\r
\r
\r
static int senosr_i2c_read(struct i2c_adapter *i2c_adap,\r
unsigned char address, unsigned char reg,\r
- unsigned int len, unsigned char *data)\r
+ unsigned int tx_len, unsigned int rx_len, unsigned char *data)\r
{\r
struct i2c_msg msgs[2];\r
int res;\r
msgs[0].addr = address;\r
msgs[0].flags = 0; /* write */\r
msgs[0].buf = ®\r
- msgs[0].len = 1;\r
+ msgs[0].len = tx_len;\r
msgs[0].scl_rate = TS_I2C_RATE;\r
\r
msgs[1].addr = address;\r
msgs[1].flags = I2C_M_RD;\r
msgs[1].buf = data;\r
- msgs[1].len = len;\r
+ msgs[1].len = rx_len;\r
msgs[1].scl_rate = TS_I2C_RATE; \r
\r
res = i2c_transfer(i2c_adap, msgs, 2);\r
#endif\r
int ret = 0;\r
char reg = rxData[0];\r
- ret = senosr_i2c_read(client->adapter, client->addr, reg, length, rxData);\r
+ ret = senosr_i2c_read(client->adapter, client->addr, reg, 1, length, rxData);\r
\r
#ifdef TS_DEBUG_ENABLE\r
DBG("addr=0x%x,len=%d,rxdata:",reg,length);\r
}\r
EXPORT_SYMBOL(ts_rx_data);\r
\r
+int ts_rx_data_word(struct i2c_client *client, char *rxData, int length)\r
+{\r
+#ifdef TS_DEBUG_ENABLE\r
+ struct ts_private_data* ts = \r
+ (struct ts_private_data *)i2c_get_clientdata(client);\r
+ int i = 0;\r
+#endif\r
+ int ret = 0;\r
+ char reg = rxData[0];\r
+ ret = senosr_i2c_read(client->adapter, client->addr, reg, 2, length, rxData);\r
+ \r
+#ifdef TS_DEBUG_ENABLE\r
+ DBG("addr=0x%x,len=%d,rxdata:",reg,length);\r
+ for(i=0; i<length; i++)\r
+ DBG("0x%x,",rxData[i]);\r
+ DBG("\n");\r
+#endif \r
+ return ret;\r
+}\r
+EXPORT_SYMBOL(ts_rx_data_word);\r
+\r
+\r
int ts_tx_data(struct i2c_client *client, char *txData, int length)\r
{\r
#ifdef TS_DEBUG_ENABLE \r