601 lines
15 KiB
C
Executable File
601 lines
15 KiB
C
Executable File
/*--------------------------------------------------------------------------
|
||
* driver/input/gt82x_ts.c
|
||
*
|
||
*
|
||
*
|
||
* Change Date:
|
||
* 2013.03.05, create.
|
||
*
|
||
*--------------------------------------------------------------------------*/
|
||
#include <common.h>
|
||
#include <asm/arch/eint.h>
|
||
#include <asm/arch/twi.h>
|
||
#include <sys_config.h>
|
||
#include <asm/arch/gt82x_ts.h>
|
||
#include <asm/arch/cpu.h>
|
||
#include <asm/arch/gic.h>
|
||
|
||
extern int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
|
||
extern int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len);
|
||
extern void i2c_init(int speed, int slaveaddr);
|
||
|
||
static const int chip_id_value[3] = {0x13,0x27,0x28};
|
||
static uchar read_chip_value;
|
||
struct ctp_config_info config_info;
|
||
|
||
static int gpio_wakeup_hdle = 0;
|
||
static int gpio_wakeup_enable = 1;
|
||
static u32 pio_handle;
|
||
static u32 port = 0;
|
||
static u32 port_num= 0;
|
||
|
||
struct info_x_y {
|
||
s32 x[5];
|
||
s32 y[5];
|
||
};
|
||
struct info_x_y info_x_y = {
|
||
{0, 0, 0, 0, 0},
|
||
{0, 0, 0, 0, 0}};
|
||
|
||
static void ctp_wakeup(void);
|
||
|
||
/*******************************************************
|
||
Function:
|
||
write i2c end cmd.
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
static int i2c_end_cmd(void)
|
||
{
|
||
int ret = -1;
|
||
uchar temp = 0;
|
||
|
||
ret = i2c_write(0x5d, 0x8000, 2, &temp, 0);
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
Read data from the i2c slave device.
|
||
Input:.
|
||
addr:operate address.
|
||
buf:read data buffer.
|
||
len:operate length.
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*********************************************************/
|
||
static int i2c_read_bytes(uint addr, uchar *buf, int len)
|
||
{
|
||
int ret = -1;
|
||
|
||
ret = i2c_read(0x5d, addr, 2, buf, len);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
write data to the i2c slave device.
|
||
Input:
|
||
addr:operate address.
|
||
buf:write data buffer.
|
||
len:operate length.
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*********************************************************/
|
||
static int i2c_write_bytes(uint addr, uchar *buf, int len)
|
||
{
|
||
int ret = -1;
|
||
|
||
ret = i2c_write(0x5d, addr, 2, buf, len);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
read chip id function.
|
||
Input:
|
||
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*********************************************************/
|
||
static int goodix_read_id(void)
|
||
{
|
||
int ret=-1;
|
||
|
||
ctp_wakeup();
|
||
|
||
ret=i2c_read_bytes(0x0f7d, &read_chip_value, 1);
|
||
if (0 > ret)
|
||
tpdbg("%s: read id failed %d\n", __func__, ret);
|
||
|
||
tpdbg("chip_id_value:0x%x\n",read_chip_value);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
CTP initialize function.
|
||
Input:
|
||
nothing.
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
static int goodix_init_panel(void)
|
||
{
|
||
int ret=-1;
|
||
int i = 0;
|
||
uchar config_info1[112];
|
||
uchar data_info0[] = {
|
||
0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,
|
||
0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,
|
||
0x0A,0x19,0x0B,0x1A,0xFF,0x15,0x16,0x17,
|
||
0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x03,0x0D,
|
||
0x04,0x0E,0x05,0x0F,0x06,0x10,0x07,0x11,
|
||
0x08,0x12,0xFF,0x0D,0xFF,0x0F,0x10,0x11,
|
||
0x12,0x13,0x0F,0x03,0x10,0x88,0x88,0x20,
|
||
0x00,0x00,0x06,0x00,0x00,0x02,0x50,0x3C,
|
||
0x35,0x03,0x00,0x05,0x00,0x03,0x20,0x05,
|
||
0x00,0x5A,0x5A,0x46,0x46,0x08,0x00,0x03,
|
||
0x19,0x05,0x14,0x10,0x00,0x07,0x00,0x00,
|
||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||
0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01
|
||
};
|
||
uchar data_info1[] = {
|
||
0x00,0x0F,0x01,0x10,0x02,0x11,0x03,0x12,
|
||
0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,
|
||
0x08,0x17,0x09,0x18,0x0A,0x19,0x0B,0x1A,
|
||
0x0C,0x1B,0x0D,0x1C,0x0E,0x1D,0x13,0x09,
|
||
0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,
|
||
0x0E,0x04,0x0D,0x03,0x0C,0x02,0x0B,0x01,
|
||
0x0A,0x00,0x0B,0x03,0x10,0x00,0x00,0x2C,
|
||
0x00,0x00,0x03,0x00,0x00,0x02,0x40,0x30,
|
||
0x60,0x03,0x00,0x05,0x00,0x03,0x20,0x05,
|
||
0x00,0x66,0x4E,0x60,0x49,0x06,0x00,0x23,
|
||
0x19,0x05,0x14,0x10,0x03,0xFC,0x01,0x00,
|
||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
|
||
};
|
||
tpdbg("init panel\n");
|
||
|
||
if (read_chip_value == 0x13) { //813
|
||
ret = i2c_write_bytes(0x0F80, data_info0, 112);
|
||
if(0 > ret)
|
||
tpdbg("write reg failed %d\n", ret);
|
||
} else if(read_chip_value == 0x28) { //828
|
||
ret = i2c_write_bytes(0x0F80, data_info1, 112);
|
||
}
|
||
i2c_end_cmd();
|
||
udelay(10000);
|
||
tpdbg("init panel ret = %d\n",ret);
|
||
if (ret < 0)
|
||
return ret;
|
||
udelay(100000);
|
||
|
||
ret = i2c_read_bytes(0x0F80, config_info1, 112);
|
||
for ( i = 0;i<112;i++) {
|
||
tpdbg("i = %d config_info1[i] = %x \n",i,config_info1[i]);
|
||
|
||
}
|
||
udelay(10000);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
Touch down report function.
|
||
Input:
|
||
ts:private data.
|
||
id:tracking id.
|
||
x:input x.
|
||
y:input y.
|
||
w:input weight.
|
||
return value:
|
||
*******************************************************/
|
||
static void goodix_touch_down(s32 id,s32 x,s32 y,s32 w)
|
||
{
|
||
tpdbg("source data:ID:%d, X:%d, Y:%d, W:%d\n", id, x, y, w);
|
||
if (1 == config_info.exchange_x_y_flag) {
|
||
swap(x, y);
|
||
}
|
||
if (1 == config_info.revert_x_flag) {
|
||
x = config_info.screen_max_x - x;
|
||
}
|
||
if (1 == config_info.revert_y_flag) {
|
||
y = config_info.screen_max_y - y;
|
||
}
|
||
|
||
info_x_y.x[id] = x;
|
||
info_x_y.y[id] = y;
|
||
|
||
tpdbg("report data:ID:%d, X:%d, Y:%d, W:%d\n", id, x, y, w);
|
||
return;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
Touch up report function.
|
||
Input:
|
||
|
||
return value:
|
||
*******************************************************/
|
||
static void goodix_touch_up(void)
|
||
{
|
||
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
CTP irq sevice function.
|
||
Input:
|
||
irq sevice data.
|
||
return value:
|
||
*******************************************************/
|
||
static void goodix_ts_irq_hanbler(void)
|
||
{
|
||
u8* coor_data = NULL;
|
||
uchar point_data[2 + 5 * MAX_FINGER_NUM + 1]={0};
|
||
u8 check_sum = 0;
|
||
u8 touch_num = 0;
|
||
u8 finger = 0;
|
||
u8 key_value = 0;
|
||
s32 input_x = 0;
|
||
s32 input_y = 0;
|
||
s32 input_w = 0;
|
||
s32 idx = 0;
|
||
s32 ret = -1;
|
||
//s32 i = 0;
|
||
|
||
tpdbg("===enter goodix_ts_irq_hanbler===\n");
|
||
|
||
ret = i2c_read_bytes(0x0f40, point_data, 8);
|
||
if (ret < 0) {
|
||
printf("I2C read error!");
|
||
}
|
||
finger = point_data[0];
|
||
touch_num = (finger & 0x01) + !!(finger & 0x02) + !!(finger & 0x04) + !!(finger & 0x08) + !!(finger & 0x10);
|
||
if (touch_num > 1) {
|
||
uchar buf[23];
|
||
ret = i2c_read_bytes(0x0f48, buf, 5 * (touch_num - 1));
|
||
if (ret < 0){
|
||
printf("I2C read error!/n");
|
||
}
|
||
memcpy(&point_data[8], &buf, 5 * (touch_num - 1));
|
||
}
|
||
i2c_end_cmd();
|
||
|
||
if (ret < 0) {
|
||
printf("I2C read error!");
|
||
goto exit_work_func;
|
||
}
|
||
|
||
if((finger & 0xC0) != 0x80) {
|
||
printf("Data not ready!");
|
||
goto exit_work_func;
|
||
}
|
||
|
||
key_value = point_data[1]&0x0f; // 1, 2, 4, 8
|
||
if ((key_value & 0x0f) == 0x0f) {
|
||
if (goodix_init_panel()){
|
||
printf("Reload config failed!\n");
|
||
}
|
||
goto exit_work_func;
|
||
}
|
||
|
||
coor_data = &point_data[2];
|
||
check_sum = 0;
|
||
for ( idx = 0; idx < 5 * touch_num; idx++) {
|
||
check_sum += coor_data[idx];
|
||
}
|
||
if (check_sum != coor_data[5 * touch_num]) {
|
||
printf("Check sum error!");
|
||
goto exit_work_func;
|
||
}
|
||
|
||
if (touch_num) {
|
||
s32 pos = 0;
|
||
|
||
for (idx = 0; idx < MAX_FINGER_NUM; idx++){
|
||
if (!(finger & (0x01 << idx))){
|
||
continue;
|
||
}
|
||
input_x = coor_data[pos] << 8;
|
||
input_x |= coor_data[pos + 1];
|
||
|
||
input_y = coor_data[pos + 2] << 8;
|
||
input_y |= coor_data[pos + 3];
|
||
|
||
input_w = coor_data[pos + 4];
|
||
|
||
pos += 5;
|
||
|
||
goodix_touch_down(idx, input_x, input_y, input_w);
|
||
}
|
||
}else{
|
||
tpdbg("Touch Release!");
|
||
goodix_touch_up();
|
||
}
|
||
|
||
exit_work_func:
|
||
return;
|
||
}
|
||
|
||
/* add by guoyingyang */
|
||
void gpio_handle_irq(void * pio_handle)
|
||
{
|
||
unsigned int reg_value = 0;
|
||
volatile unsigned int *reg_addr = NULL;
|
||
|
||
reg_addr = SUNXI_PIO_EINT_STATUS(port);
|
||
reg_value = *reg_addr;
|
||
printf("===== enter gpio_irq =======\n");
|
||
//ƥ<><C6A5>gpio<69>жϺţ<CFBA><C5A3><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>gpio<69>жϺ<D0B6><CFBA><EFBFBD>
|
||
if(reg_value & (0x01 << port_num))
|
||
{
|
||
goodix_ts_irq_hanbler();
|
||
//<2F><><EFBFBD><EFBFBD>gpio<69>ж<EFBFBD>pendingλ
|
||
reg_value |= ( 0x01 << port_num );
|
||
*reg_addr = reg_value ;
|
||
printf("clear pending_bit \n ");
|
||
}
|
||
return ;
|
||
}
|
||
/*******************************************************
|
||
Function:
|
||
ctp_wakeup - function.
|
||
Input:
|
||
|
||
return value:
|
||
*********************************************************/
|
||
static void ctp_wakeup(void)
|
||
{
|
||
printf("ctp_wakeup. \n");
|
||
if (1 == gpio_wakeup_enable) {
|
||
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 0, "ctp_wakeup")){
|
||
printf("err when operate gpio. \n");
|
||
}
|
||
udelay(2000);
|
||
if(EGPIO_SUCCESS != gpio_write_one_pin_value(gpio_wakeup_hdle, 1, "ctp_wakeup")){
|
||
printf("err when operate gpio. \n");
|
||
}
|
||
udelay(20000);
|
||
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
ctp_free_platform_irq.
|
||
Input:
|
||
|
||
return value:
|
||
*******************************************************/
|
||
static void ctp_free_platform_irq(void)
|
||
{
|
||
eint_irq_disable(port,port_num);
|
||
|
||
if (pio_handle) {
|
||
gpio_release(pio_handle, 2);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
ctp_init_platform_irq.
|
||
Input:
|
||
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
static int ctp_init_platform_irq(void)
|
||
{
|
||
int ret = -1;
|
||
user_gpio_set_t *tmp = NULL;
|
||
|
||
pio_handle = gpio_request_ex("ctp_para", "ctp_int_port");
|
||
if (!pio_handle) {
|
||
printf("[%s] gpio_request_ex fail! %d\n",__func__,__LINE__);
|
||
return ret;
|
||
}
|
||
tmp = (user_gpio_set_t *)((char *)pio_handle + 16);
|
||
//ret = eint_irq_request(0, 3, goodix_ts_irq_hanbler, EINT_TRIGGER_STATUS_NEG, &test_a);
|
||
//if (ret)
|
||
// printf("request gpio irq err!\n");
|
||
irq_install_handler(AW_IRQ_EINTB, (interrupt_handler_t *)gpio_handle_irq, (void*)&pio_handle);
|
||
|
||
port = tmp->port;
|
||
port_num = tmp->port_num;
|
||
|
||
ret = eint_irq_enable(port,port_num);
|
||
if (ret)
|
||
printf("enable irq err!\n");
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
ctp_free_platform_resource.
|
||
Input:
|
||
|
||
return value:
|
||
*******************************************************/
|
||
static void ctp_free_platform_resource(void)
|
||
{
|
||
if (gpio_wakeup_hdle) {
|
||
gpio_release(gpio_wakeup_hdle, 2);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
initialize platform related resource.
|
||
Input:
|
||
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
static int ctp_init_platform_resource(void)
|
||
{
|
||
int ret = 0;
|
||
|
||
gpio_wakeup_hdle = gpio_request_ex("ctp_para", "ctp_wakeup");
|
||
if (!gpio_wakeup_hdle) {
|
||
tpdbg("tp_wakeup request gpio fail!\n");
|
||
gpio_wakeup_enable = 0;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
CTP print config info function.
|
||
Input:
|
||
CTP config info
|
||
return value:
|
||
*******************************************************/
|
||
void ctp_print_info(struct ctp_config_info info)
|
||
{
|
||
tpdbg("info.ctp_used:%d\n",info.ctp_used);
|
||
tpdbg("info.twi_id:%d\n",info.twi_id);
|
||
tpdbg("info.screen_max_x:%d\n",info.screen_max_x);
|
||
tpdbg("info.screen_max_y:%d\n",info.screen_max_y);
|
||
tpdbg("info.revert_x_flag:%d\n",info.revert_x_flag);
|
||
tpdbg("info.revert_y_flag:%d\n",info.revert_y_flag);
|
||
tpdbg("info.exchange_x_y_flag:%d\n",info.exchange_x_y_flag);
|
||
tpdbg("info.irq_gpio_number:%d\n",info.irq_gpio_number);
|
||
tpdbg("info.wakeup_gpio_number:%d\n",info.wakeup_gpio_number);
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
get config info from sysconfig.fex file.
|
||
Input:
|
||
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
static int ctp_fetch_sysconfig_para(void)
|
||
{
|
||
int ret = -1;
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_used", &config_info.ctp_used, 1)) {
|
||
tpdbg("ctp_used script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if(1 != config_info.ctp_used){
|
||
tpdbg("ctp_unused. \n");
|
||
return ret;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch ("ctp_para", "ctp_twi_id",
|
||
&config_info.twi_id, 1)){
|
||
tpdbg("ctp_twi_id script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_screen_max_x", &config_info.screen_max_x, 1)) {
|
||
tpdbg("ctp_screen_max_x script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_screen_max_y", &config_info.screen_max_y, 1)) {
|
||
tpdbg("ctp_screen_max_y script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_revert_x_flag", &config_info.revert_x_flag, 1)) {
|
||
tpdbg("ctp_revert_x_flag script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_revert_y_flag", &config_info.revert_y_flag, 1)) {
|
||
tpdbg("ctp_revert_y_flag script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
if (SCRIPT_PARSER_OK != script_parser_fetch("ctp_para", "ctp_exchange_x_y_flag", &config_info.exchange_x_y_flag, 1)) {
|
||
tpdbg("ctp_exchange_x_y_flag script_get_item err. \n");
|
||
goto script_get_item_err;
|
||
}
|
||
|
||
ctp_print_info(config_info);
|
||
return 0;
|
||
|
||
script_get_item_err:
|
||
tpdbg("=========script_get_item_err============\n");
|
||
return ret;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
goodix ctp load function.
|
||
Input:
|
||
|
||
return value:
|
||
= 0; success;
|
||
< 0; err
|
||
*******************************************************/
|
||
int goodix_init(void)
|
||
{
|
||
int err = -1;
|
||
i2c_init(40000,0);
|
||
printf("%s.enter\n", __func__);
|
||
if (ctp_fetch_sysconfig_para()) {
|
||
printf("ctp_fetch_sysconfig_para err.\n");
|
||
return -1;
|
||
}
|
||
|
||
err = ctp_init_platform_resource();
|
||
if (0 != err) {
|
||
printf("ctp_init_platform_resource err. \n");
|
||
}
|
||
|
||
goodix_read_id();
|
||
|
||
goodix_init_panel();
|
||
|
||
err = ctp_init_platform_irq();
|
||
if (0 != err) {
|
||
printf("ctp_init_platform_irq err. \n");
|
||
}
|
||
printf("%s.over\n", __func__);
|
||
return err;
|
||
}
|
||
|
||
/*******************************************************
|
||
Function:
|
||
goodix ctp remove function.
|
||
Input:
|
||
|
||
return value:
|
||
*******************************************************/
|
||
int goodix_remove(void)
|
||
{
|
||
ctp_free_platform_resource();
|
||
ctp_free_platform_irq();
|
||
|
||
return 0;
|
||
}
|
||
|