/*
* Goodix GT9xx touchscreen driver
*
* Copyright (C) 2010 - 2014 Goodix. Ltd.
*
* 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 a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* 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.
*
* Version: 2.4
* Release Date: 2014/11/28 tftp -r conprog.bin -g 10.0.0.10
*/
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/ioctl.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/irq.h>
#include "gt9xx.h"
#if GTP_ICS_SLOT_REPORT
#include <linux/input/mt.h>
#endif
static const char *goodix_ts_name = "goodix-ts";
static const char *goodix_input_phys = "input/ts";
static struct workqueue_struct *goodix_wq;
struct i2c_client * i2c_connect_client = NULL;
int gtp_rst_gpio;
int gtp_int_gpio;
u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]
= {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
#if GTP_HAVE_TOUCH_KEY
static const u16 touch_key_array[] = GTP_KEY_TAB;
#define GTP_MAX_KEY_NUM (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
#if GTP_DEBUG_ON
static const int key_codes[] = {KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH};
static const char *key_names[] = {"Key_Home", "Key_Back", "Key_Menu", "Key_Search"};
#endif
#endif
static s8 gtp_i2c_test(struct i2c_client *client);
void gtp_reset_guitar(struct i2c_client *client, s32 ms);
s32 gtp_send_cfg(struct i2c_client *client);
void gtp_int_sync(s32 ms);
static ssize_t gt91xx_config_read_proc(struct file *, char __user *, size_t, loff_t *);
static ssize_t gt91xx_config_write_proc(struct file *, const char __user *, size_t, loff_t *);
static struct proc_dir_entry *gt91xx_config_proc = NULL;
static const struct file_operations config_proc_ops = {
.owner = THIS_MODULE,
.read = gt91xx_config_read_proc,
.write = gt91xx_config_write_proc,
};
static int gtp_register_powermanger(struct goodix_ts_data *ts);
static int gtp_unregister_powermanger(struct goodix_ts_data *ts);
#if GTP_CREATE_WR_NODE
//extern s32 init_wr_node(struct i2c_client*);
//extern void uninit_wr_node(void);
#endif
#if GTP_AUTO_UPDATE
extern u8 gup_init_update_proc(struct goodix_ts_data *);
#endif
#if GTP_ESD_PROTECT
static struct delayed_work gtp_esd_check_work;
static struct workqueue_struct * gtp_esd_check_workqueue = NULL;
static void gtp_esd_check_func(struct work_struct *);
static s32 gtp_init_ext_watchdog(struct i2c_client *client);
void gtp_esd_switch(struct i2c_client *, s32);
#endif
//*********** For GT9XXF Start **********//
#if GTP_COMPATIBLE_MODE
extern s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len);
extern s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len);
extern s32 gup_clk_calibration(void);
extern s32 gup_fw_download_proc(void *dir, u8 dwn_mode);
extern u8 gup_check_fs_mounted(char *path_name);
void gtp_recovery_reset(struct i2c_client *client);
static s32 gtp_esd_recovery(struct i2c_client *client);
s32 gtp_fw_startup(struct i2c_client *client);
static s32 gtp_main_clk_proc(struct goodix_ts_data *ts);
static s32 gtp_bak_ref_proc(struct goodix_ts_data *ts, u8 mode);
#endif
//********** For GT9XXF End **********//
#if GTP_GESTURE_WAKEUP
typedef enum
{
DOZE_DISABLED = 0,
DOZE_ENABLED = 1,
DOZE_WAKEUP = 2,
}DOZE_T;
static DOZE_T doze_status = DOZE_DISABLED;
static s8 gtp_enter_doze(struct goodix_ts_data *ts);
#endif
#ifdef GTP_CONFIG_OF
int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid);
#endif
/*******************************************************
Function:
Read data from the i2c slave device.
Input:
client: i2c device.
buf[0~1]: read start address.
buf[2~len-1]: read data buffer.
len: GTP_ADDR_LENGTH + read bytes count
Output:
numbers of i2c_msgs to transfer:
2: succeed, otherwise: failed
*********************************************************/
s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
{
struct i2c_msg msgs[2];
s32 ret=-1;
s32 retries = 0;
//GTP_DEBUG_FUNC();
msgs[0].flags = !I2C_M_RD;
msgs[0].addr = client->addr;
msgs[0].len = GTP_ADDR_LENGTH;
msgs[0].buf = &buf[0];
//msgs[0].scl_rate = 300 * 1000; // for Rockchip, etc.
msgs[1].flags = I2C_M_RD;
msgs[1].addr = client->addr;
msgs[1].len = len - GTP_ADDR_LENGTH;
msgs[1].buf = &buf[GTP_ADDR_LENGTH];
//msgs[1].scl_rate = 300 * 1000;
while(retries < 5)
{
ret = i2c_transfer(client->adapter, msgs, 2);
if(ret == 2)break;
retries++;
}
if((retries >= 5))
{
#if GTP_COMPATIBLE_MODE
struct goodix_ts_data *ts = i2c_get_clientdata(client);
#endif
#if GTP_GESTURE_WAKEUP
// reset chip would quit doze mode
if (DOZE_ENABLED == doze_status)
{
return ret;
}
#endif
GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
#if GTP_COMPATIBLE_MODE
if (CHIP_TYPE_GT9F == ts->chip_type)
{
gtp_recovery_reset(client);
}
else
#endif
{
gtp_reset_guitar(client, 10);
}
}
return ret;
}
/*******************************************************
Function:
Write data to the i2c slave device.
Input:
client: i2c device.
buf[0~1]: write start address.
buf[2~len-1]: data buffer
len: GTP_ADDR_LENGTH + write bytes count
Output:
numbers of i2c_msgs to transfer:
1: succeed, otherwise: failed
*********************************************************/
s32 gtp_i2c_write(struct i2c_client *client,u8 *buf,s32 len)
{
struct i2c_msg msg;
s32 ret = -1;
s32 retries = 0;
// GTP_DEBUG_FUNC();
msg.flags = !I2C_M_RD;
msg.addr = client->addr;
msg.len = len;
msg.buf = buf;
//msg.scl_rate = 300 * 1000; // for Rockchip, etc
while(retries < 5)
{
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret == 1)break;
retries++;
}
if((retries >= 5))
{
#if GTP_COMPATIBLE_MODE
struct goodix_ts_data *ts = i2c_get_clientdata(client);
#endif
#if GTP_GESTURE_WAKEUP
if (DOZE_ENABLED == doze_status)
{
return ret;
}
#endif
GTP_ERROR("I2C Write: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
#if GTP_COMPATIBLE_MODE
if (CHIP_TYPE_GT9F == ts->chip_type)
{
gtp_recovery_reset(client);
}
else
#endif
{
gtp_reset_guitar(client, 10);
}
}
return ret;
}
/*******************************************************
Function:
i2c read twice, compare the results
Input:
client: i2c device
addr: operate address
rxbuf: read data to store, if compare successful
len: bytes to read
Output:
FAIL: read failed
SUCCESS: read successful
*********************************************************/
s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len)
{
u8 buf[16] = {0};
u8 confirm_buf[16] = {0};
u8 retry = 0;
while (retry++ < 3)
{
memset(buf, 0xAA, 16);
buf[0] = (u8)(addr >> 8);
buf[1] = (u8)(addr & 0xFF);
评论0