/*---------------------------------------------------------------------------------------------------------
* driver/input/touchscreen/goodix_touch.c
*
* Copyright(c) 2010 Goodix Technology Corp.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
* Change Date:
* 2010.11.11, add point_queue's definiens.
*
* 2011.03.09, rewrite point_queue's definiens.
*
* 2011.05.12, delete point_queue for Android 2.2/Android 2.3 and so on.
*
*---------------------------------------------------------------------------------------------------------*/
#include <linux/i2c.h>
#include <linux/input.h>
#include "goodix_touch.h"
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/irqs.h>
#include <mach/system.h>
#include <mach/hardware.h>
#include <mach/sys_config.h>
#include "ctp_platform_ops.h"
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/pm.h>
#include <linux/earlysuspend.h>
#endif
#define FOR_TSLIB_TEST
//#define PRINT_INT_INFO
//#define PRINT_POINT_INFO
#define PRINT_SUSPEND_INFO
#define TEST_I2C_TRANSFER
//#undef CONFIG_HAS_EARLYSUSPEND
#ifndef GUITAR_GT80X
#error The code does not match the hardware version.
#endif
struct goodix_ts_data {
int retry;
int panel_type;
char phys[32];
struct i2c_client *client;
struct input_dev *input_dev;
uint8_t use_irq;
uint8_t use_shutdown;
uint32_t gpio_shutdown;
uint32_t gpio_irq;
uint32_t screen_width;
uint32_t screen_height;
struct ts_event event;
struct hrtimer timer;
struct work_struct work;
int (*power)(struct goodix_ts_data * ts, int on);
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
};
const char *f3x_ts_name = "gt80x";
static struct workqueue_struct *goodix_wq;
#define X_DIFF (800)
#ifdef PRINT_POINT_INFO
#define print_point_info(fmt, args...) \
do{ \
printk(fmt, ##args); \
}while(0)
#else
#define print_point_info(fmt, args...) //
#endif
#ifdef PRINT_INT_INFO
#define print_int_info(fmt, args...) \
do{ \
printk(fmt, ##args); \
}while(0)
#else
#define print_int_info(fmt, args...) //
#endif
///////////////////////////////////////////////
//specific tp related macro: need be configured for specific tp
#define CTP_IRQ_NO (gpio_int_info[0].port_num)
#define CTP_IRQ_MODE (NEGATIVE_EDGE)
#define CTP_NAME GOODIX_I2C_NAME
#define TS_RESET_LOW_PERIOD (15)
#define TS_INITIAL_HIGH_PERIOD (15)
#define TS_WAKEUP_LOW_PERIOD (100)
#define TS_WAKEUP_HIGH_PERIOD (100)
#define TS_POLL_DELAY (10) /* ms delay between samples */
#define TS_POLL_PERIOD (10) /* ms delay between samples */
#define SCREEN_MAX_HEIGHT (screen_max_x)
#define SCREEN_MAX_WIDTH (screen_max_y)
#define PRESS_MAX (255)
static void* __iomem gpio_addr = NULL;
static int gpio_int_hdle = 0;
static int gpio_wakeup_hdle = 0;
static int gpio_reset_hdle = 0;
static int gpio_wakeup_enable = 1;
static int gpio_reset_enable = 1;
static user_gpio_set_t gpio_int_info[1];
static int screen_max_x = 0;
static int screen_max_y = 0;
static int revert_x_flag = 0;
static int revert_y_flag = 0;
static int exchange_x_y_flag = 0;
static __u32 twi_addr = 0;
static __u32 twi_id = 0;
static int int_cfg_addr[]={PIO_INT_CFG0_OFFSET,PIO_INT_CFG1_OFFSET,
PIO_INT_CFG2_OFFSET, PIO_INT_CFG3_OFFSET};
/* Addresses to scan */
union{
unsigned short dirty_addr_buf[2];
const unsigned short normal_i2c[2];
}u_i2c_addr = {{0x00},};
/*
* ctp_get_pendown_state : get the int_line data state,
*
* return value:
* return PRESS_DOWN: if down
* return FREE_UP: if up,
* return 0: do not need process, equal free up.
*/
static int ctp_get_pendown_state(void)
{
unsigned int reg_val;
static int state = FREE_UP;
//get the input port state
reg_val = readl(gpio_addr + PIOH_DATA);
//printk("reg_val = %x\n",reg_val);
if(!(reg_val & (1<<CTP_IRQ_NO))){
state = PRESS_DOWN;
print_int_info("pen down. \n");
}else{ //touch panel is free up
state = FREE_UP;
print_int_info("free up. \n");
}
return state;
}
/**
* ctp_clear_penirq - clear int pending
*
*/
static void ctp_clear_penirq(void)
{
int reg_val;
//clear the IRQ_EINT29 interrupt pending
//printk("clear pend irq pending\n");
reg_val = readl(gpio_addr + PIO_INT_STAT_OFFSET);
//writel(reg_val,gpio_addr + PIO_INT_STAT_OFFSET);
//writel(reg_val&(1<<(IRQ_EINT21)),gpio_addr + PIO_INT_STAT_OFFSET);
if((reg_val = (reg_val&(1<<(CTP_IRQ_NO))))){
print_int_info("==CTP_IRQ_NO=\n");
writel(reg_val,gpio_addr + PIO_INT_STAT_OFFSET);
}
return;
}
/**
* ctp_set_irq_mode - according sysconfig's subkey "ctp_int_port" to config int port.
*
* return value:
* 0: success;
* others: fail;
*/
static int ctp_set_irq_mode(char *major_key , char *subkey, ext_int_mode int_mode)
{
int ret = 0;
__u32 reg_num = 0;
__u32 reg_addr = 0;
__u32 reg_val = 0;
//config gpio to int mode
pr_info("%s: config gpio to int mode. \n", __func__);
#ifndef SYSCONFIG_GPIO_ENABLE
#else
if(gpio_int_hdle){
gpio_release(gpio_int_hdle, 2);
}
gpio_int_hdle = gpio_request_ex(major_key, subkey);
if(!gpio_int_hdle){
pr_info("request tp_int_port failed. \n");
ret = -1;
goto request_tp_int_port_failed;
}
gpio_get_one_pin_status(gpio_int_hdle, gpio_int_info, subkey, 1);
pr_info("%s, %d: gpio_int_info, port = %d, port_num = %d. \n", __func__, __LINE__, \
gpio_int_info[0].port, gpio_int_info[0].port_num);
#endif
#ifdef AW_GPIO_INT_API_ENABLE
#else
pr_info(" INTERRUPT CONFIG\n");
reg_num = (gpio_int_info[0].port_num)%8;
reg_addr = (gpio_int_info[0].port_num)/8;
reg_val = readl(gpio_addr + int_cfg_addr[reg_addr]);
reg_val &= (~(7 << (reg_num * 4)));
reg_val |= (int_mode << (reg_num * 4));
writel(reg_val,gpio_addr+int_cfg_addr[reg_addr]);
ctp_clear_penirq();
reg_val = readl(gpio_addr+PIO_INT_CTRL_OFFSET);
reg_val |= (1 << (gpio_int_info[0].port_num));
writel(reg_val,gpio_addr+PIO_INT_CTRL_OFFSET);
udelay(1);
#endif
request_tp_int_port_failed:
return ret;
}
/**
* ctp_set_gpio_mode - according sysconfig's subkey "ctp_io_port" to config io port.
*
* return value:
* 0: success;
* others: fail;
*/
static int ctp_set_gpio_mode(void)
{
//int reg_val;
int ret = 0;
//config gpio to io mode
printk("%s: config gpio to io mode. \n", __func__);
#ifndef SYSCONFIG_GPIO_ENABLE
#else
if(gpio_int_hdle){
gpio_release(gpio_int_hdle, 2);
}
gpio_int_hdle = gpio_request_ex("ctp_para", "ctp_io_port");
if(!gpio_int_hdle){
printk("request ctp_io_port failed. \n");
ret = -1;
goto request_tp_io_port_failed;
}
#endif
return ret;
request_tp_io_port_failed:
return ret;
}
/**
* ctp_judge_int_occur - whether interrupt occur.
*
* return value:
* 0: int occur;
* others: no int occur;
*/
static int ctp_judge_int_occur(void)
{
//int reg_val[3];
int reg_val;
int ret = -1;
reg_val = readl(gpio_addr + PIO_INT_STAT_OFFSET);
if(reg_val&(1<<(CTP_IRQ_NO))){
ret = 0;
}
re
评论0