/*--------------------------------------------------------------------------------------------------------- * driver/input/touchscreen/goodix_touch.c * * Copyright(c) 2010 Goodix Technology Corp.      * Author: Eltonny * Date: 2010.11.11                                     *                                                                                                          *---------------------------------------------------------------------------------------------------------*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/time.h>#include <linux/delay.h>#define DEBUG 1#include <linux/device.h>#include <linux/earlysuspend.h>#include <linux/platform_device.h>#include <linux/hrtimer.h>#include <linux/i2c.h>#include <linux/input.h>#include <linux/interrupt.h>#include <linux/io.h>#include <linux/irq.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <linux/gpio.h>#include <linux/ioc4.h>#include <linux/io.h>#include <mach/ut210_gpio_reg.h>#include "goodix_touch.h"#include "goodix_queue.h"#ifndef GUITAR_GT80X#error The code does not match the hardware version.#endif#define GOODIX_DEBUG_F#ifdef GOODIX_DEBUG_F#define GOODIXTS_DEBUG(fmt,args...)  printk(  "[goodix_ts]: " fmt, ## args) //printk( KERN_DEBUG "[egalax_i2c]: " fmt, ## args)#define DBG() printk("[%s]:%d => \n",__FUNCTION__,__LINE__)#else#define GOODIXTS_DEBUG(fmt,args...)  do{ }while(0)#define DBG() do{ }while(0)#endif#ifdef utv210static volatile  VIC_REG *VICREG;                 static volatile UT210_GPIO_REG *UT210_GPIOREG;    //denis_wei add 2010-12-08#define TIMER     //采用的是定时器扫描的方式#ifdef  EINT29     //如果是定义EINT29表示采用的是中断的方式    是对中断的定义  #define EINT_KEY      (IRQ_RTC_TIC)//按键中断#define KEY_EINT_EN  do { VICREG->VICINTENABLE  |= (0x1<<29); \ VICREG->VICINTENCLEAR &= (~(0x1<<29));}while(0)#define KEY_EINT_DIS  do {VICREG->VICINTENABLE  &= (~(0x1<<29));\ VICREG->VICINTENCLEAR |= (0x1<<29); } while(0) static void goodix_key_callback(struct work_struct *work);static DECLARE_WORK(key_work, goodix_key_callback);static struct input_dev * s_input_dev = NULL;#endif/***wangyulu******/#define MAX_BUTTON_CNT 3static int goodix_scancode[MAX_BUTTON_CNT] = {0x1A,0x1B,0x1C};static int goodix_keycode[MAX_BUTTON_CNT] = {KEY_BACK, KEY_HOME,KEY_MENU};static int goodix_scancode_history[MAX_BUTTON_CNT] = {0,0,0,0};///wangyulu lock_key time#ifdef TIMER    //对定时器的定义#define KEY_DETECT_INTERVAL      (msecs_to_jiffies(60))//定时60msstatic struct timer_list key_timer;static void lockkey_timer_callback(struct work_struct *work);static DECLARE_WORK(lock_work, lockkey_timer_callback);static struct input_dev * s_input_dev = NULL;static void goodix_key_timer_handler(unsigned long data);#endif#endif#define MID706_SP  static struct point_queue  finger_list; //record the fingers list /*************************************************/static struct i2c_client * i2c_connect_client = NULL;#ifdef CONFIG_HAS_EARLYSUSPENDstatic void goodix_ts_early_suspend(struct early_suspend *h);static void goodix_ts_late_resume(struct early_suspend *h);#endif#define GOODIX_KEY_I2C (0xC4>>1)//触摸按键芯片的设备地址 /*Function as i2c_master_send */static int i2c_write_key(struct i2c_client *client,uint8_t *data,int len){ struct i2c_msg msg; int ret=-1; //发送设备地址 msg.flags=!I2C_M_RD;//写消息 msg.addr=GOODIX_KEY_I2C; msg.len=len; msg.buf=data;   ret=i2c_transfer(i2c_get_adapter(1),&msg,1); return ret;}//************ urbetter+ ******************static int goodix_i2c_rxdata(char *rxdata, int length){ int ret; struct i2c_msg msgs[] = {  {   .addr = GOODIX_KEY_I2C,   .flags = 0,   .len = 1,   .buf = rxdata,  },  {   .addr = GOODIX_KEY_I2C,   .flags = I2C_M_RD,   .len = length,   .buf = rxdata,  }, }; ret = i2c_transfer(i2c_get_adapter(1), msgs, 2);//i2c_get_adapter(1)选着iic 1 if (ret < 0) pr_err("msg %s i2c read error: %d\n", __func__, ret);  return ret;}#ifdef TIMER ////轮询处理函数wangyulustatic void goodix_key_timer_handler(unsigned long data){ //ceshi schedule_work(&lock_work); mod_timer(&key_timer,jiffies + KEY_DETECT_INTERVAL);}/////lock_key的处理函数 key_703 wangyulustatic void lockkey_timer_callback(struct work_struct *work){     int i; int boy_flag = 0; unsigned char buf[2]; buf[0] = 0xc5; goodix_i2c_rxdata(buf, 1); //printk("key_TIMER=0x%02X\n", buf[0]); //没有按下是0xff  boy for(i = 0; i < MAX_BUTTON_CNT; i++) {         if((buf[0] == goodix_scancode_history[i]) || (buf[0] == goodix_scancode[i]))      {            printk("key_TIMER=0x%02X\n", buf[0]); //没有按下是0xff  boy            goodix_scancode_history[i]= buf[0];        input_report_key(s_input_dev, goodix_keycode[i], 1);     }      if(buf[0] == 0xFF)      {        input_report_key(s_input_dev, goodix_keycode[i], 0);      } }}#endifstatic int goodix_key_input_init(struct goodix_ts_data *ts){ int i; s_input_dev = ts->input_dev; set_bit(EV_KEY, ts->input_dev->evbit); for(i = 0; i < MAX_BUTTON_CNT; i++)  set_bit(goodix_keycode[i], ts->input_dev->keybit);         /******wangyulu********添加time*****/#ifdef TIMER          init_timer(&key_timer);      key_timer.function = goodix_key_timer_handler;      key_timer.expires = jiffies + KEY_DETECT_INTERVAL;      add_timer(&key_timer);#endif}static int goodix_init_key(struct goodix_ts_data *ts){ int ret=-1;#ifdef EINT29 //KEY_EINT_NUM INT11 wangyulu gpio_request(S5PV210_GPH3(5), "goodix_key_int"); s3c_gpio_cfgpin(S5PV210_GPH3(5), 0xf<<20); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN); set_irq_type(EINT_KEY, IRQ_TYPE_EDGE_RISING); gpio_free(S5PV210_GPH3(5)); KEY_EINT_EN;#else if(ts->use_irq)  enable_irq(ts->client->irq);#endif uint8_t config_info[]={          0x88,0x08,0x90,0x90,0x90,0x90,0x50,0x58,0x55,0x56,       0x0e,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,       0x00,0x05,0x06,0x07,0x00,0xc8};#endif ret=i2c_write_key(ts->client,config_info,sizeof(config_info)); if(ret > 0)  ret = 0;     goodix_key_input_init(ts); //urbetter+ boy return ret;}#ifdef EINT29///add wangyulu 按键中断处理函数static irqreturn_t goodix_key_irq_handler(int irq, void *dev_id){ struct goodix_ts_data *ts = dev_id;     printk("goodix_key_irq_handler\n"); //没有按下是0xff  boy KEY_EINT_DIS; schedule_work(&key_work); return IRQ_HANDLED;}static void goodix_key_callback(struct work_struct *work)/////adb wangyulu interrupter{     int i; int boy_flag = 0; unsigned char buf[2]; buf[0] = 0xc5; goodix_i2c_rxdata(buf, 1); printk("key_EINT29=0x%02X\n", buf[0]); //没有按下是0xff  boy for(i = 0; i < MAX_BUTTON_CNT; i++) {         if((buf[0] == goodix_scancode_history[i]) || (buf[0] == goodix_scancode[i]))      {           goodix_scancode_history[i]= buf[0];          input_report_key(s_input_dev, goodix_keycode[i], 1);     }      if(buf[0] == 0xFF)      {         input_report_key(s_input_dev, goodix_keycode[i], 0);      } }     KEY_EINT_EN;}#endifstatic void utv210_gpio_init(void){     int ret = 0;     VICREG = ioremap(0xf2000000, sizeof(VIC_REG));                         UT210_GPIOREG  = ioremap(0xe0200000, sizeof(UT210_GPIO_REG));       //wangyulu key#ifdef EINT29 set_irq_type(EINT_KEY, IRQ_TYPE_EDGE_RISING);     ret = gpio_request(S5PV210_GPH3(5), "goodix_key_int"); if (ret < 0) {    gpio_free(S5PV210_GPH3(5));  // now bug; TODO } ret = gpio_request(S5PV210_GPH3(5), "goodix_key_int"); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN);     gpio_free(S5PV210_GPH3(5));     //denis_wei add 2010-12-10 for touch interrupt detect     UT210_GPIOREG->GPH1.GP_CON &= ~((0xf<<20) );//gph13 as input port UT210_GPIOREG->GPH1.GP_CON |= ((0xf<<20));//gph13 interrupt port     UT210_GPIOREG->GPH1.GP_DAT &= ~((0x1<<20) );//gph13. output 1  UT210_GPIOREG->GPH1.GP_PUD &= ~((0x3<<20) );//gph13 pull disable UT210_GPIOREG->GPH1.GP_PUD |= ((0x2<<20));//gph13 pull-up enable#endif#ifdef TIMER      s3c_gpio_cfgpin(S5PV210_GPH3(5), 0x0<<20); gpio_direction_output(S5PV210_GPH3(5), 1); s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN);#endif    }/******************************************************* 功能: 触摸屏探测函数 在注册驱动时调用(要求存在对应的client); 用于IO,中断等资源申请;设备注册;触摸屏初始化等工作参数: client:待驱动的设备结构体 id:设备IDreturn: 执行结果码,0表示正常执行********************************************************/static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){ struct goodix_ts_data *ts; int ret = 0; int retry=0; int count=0; u8 testbuf[6] = {0, 0, 0, 0, 0}; struct goodix_i2c_rmi_platform_data *pdata; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))  {  dev_err(&client->dev, "System need I2C function.\n");  ret = -ENODEV;  goto err_check_functionality_failed; } ts = kzalloc(sizeof(*ts), GFP_KERNEL); if (ts == NULL) {  ret = -ENOMEM;  goto err_alloc_data_failed; } //utv210_gpio_init();  /***wangyulu****/ ts->client = client; i2c_set_clientdata(client, ts); pdata = client->dev.platform_data;  ts->input_dev = input_allocate_device(); if (ts->input_dev == NULL) {  ret = -ENOMEM;  dev_dbg(&client->dev,"Failed to allocate input device\n");  goto err_input_dev_alloc_failed; } ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);     ret = input_register_device(ts->input_dev); if (ret) {  dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);   goto  err_input_register_device_failed; } utv210_gpio_init();  goodix_init_key(ts);#ifdef EINT29///wangyulu 按键中断申请 ret = request_irq(EINT_KEY, goodix_key_irq_handler,   IRQ_TYPE_EDGE_RISING, client->name, ts); if( ret )  {  printk("Can't allocate touchscreen's interrupt\n");  dev_err(&client->dev,"Can't allocate touchscreen's interrupt!ERRNO:%d\n", ret);  goto Fail_utv210_int; } ts->use_irq = 1; KEY_EINT_DIS;#endif printk("#############line =%d\n", __LINE__);err_input_register_device_failed: input_free_device(ts->input_dev);err_input_dev_alloc_failed:  i2c_set_clientdata(client, NULL);Fail_utv210_int:err_alloc_data_failed:err_check_functionality_failed: return ret;}/******************************************************* 功能: 驱动资源释放参数: client:设备结构体return: 执行结果码,0表示正常执行********************************************************/static int goodix_ts_remove(struct i2c_client *client){ struct goodix_ts_data *ts = i2c_get_clientdata(client); unregister_early_suspend(&ts->early_suspend); dev_notice(&client->dev,"The driver is removing...\n"); i2c_set_clientdata(client, NULL); input_unregister_device(ts->input_dev);#ifdef EINT29   free_irq(EINT_KEY, ts);#endif if(ts->input_dev)  kfree(ts->input_dev); kfree(ts); return 0;}//停用设备static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg){ int ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); if(ts->bad_data)     return 0; }static int goodix_ts_resume(struct i2c_client *client){ int ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); if(ts->bad_data)  return 0;#ifdef EINT29     KEY_EINT_EN;#else if (ts->use_irq) {  enable_irq(client->irq); }#endif  return 0;}#ifdef CONFIG_HAS_EARLYSUSPENDstatic void goodix_ts_early_suspend(struct early_suspend *h){     struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_suspend(ts->client, PMSG_SUSPEND);}static void goodix_ts_late_resume(struct early_suspend *h){ struct goodix_ts_data *ts; ts = container_of(h, struct goodix_ts_data, early_suspend); goodix_ts_resume(ts->client); }#endif#undef GOODIX_I2C_NAME#define GOODIX_I2C_NAME "Goodix-key-703" //boy static const struct i2c_device_id goodix_ts_id[] = { { GOODIX_I2C_NAME, 0 }, { }};//设备驱动结构体struct i2c_driver goodix_ts_driver = { .probe  = goodix_ts_probe, .remove  = goodix_ts_remove,#ifndef CONFIG_HAS_EARLYSUSPEND .suspend = goodix_ts_suspend, .resume  = goodix_ts_resume,#endif .id_table = goodix_ts_id, .driver = {  .name = GOODIX_I2C_NAME,  .owner = THIS_MODULE, },};/******************************************************* 功能: 驱动加载函数return: 执行结果码,0表示正常执行********************************************************/ static int __devinit goodix_ts_init(void) {  int ret;   ret=i2c_add_driver(&goodix_ts_driver);  return ret;  }/******************************************************* 功能: 驱动卸载函数参数: client:设备结构体********************************************************/ static void __exit goodix_ts_exit(void) {   i2c_del_driver(&goodix_ts_driver); }late_initcall(goodix_ts_init);module_exit(goodix_ts_exit);MODULE_DESCRIPTION("Goodix Touchscreen Driver");MODULE_LICENSE("GPL");

转载自:http://blog.csdn.net/Baiduluckyboy/article/details/6616533

更多相关文章

  1. android获取设备唯一标识device_token
  2. Android 加载图片文件 函数
  3. Android 获取设备宽高分辨率
  4. 如何获取Android设备名称(常用ADB命令介绍)
  5. android保持在休眠时,后台程序继续运行(让程序获取设备电源锁)
  6. Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
  7. Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听
  8. js判断当前设备是 Android 还是 iOS
  9. android 长按键菜单

随机推荐

  1. 成功开发Android(安卓)app-5(视图)
  2. 右上标的实现
  3. android节点网站代码
  4. 【Android】去除小数点后多余的零
  5. Android(安卓)Cursor之MergeCursor
  6. 通过网卡连接android设备
  7. [置顶] Android开发最佳实践---Futurice
  8. Android开发之自动换行LinearLayout
  9. 基于 Android(安卓)NDK 的学习之旅-----
  10. Android(安卓)Material Design控件之Navi