phonepad: commit phonepad(i30) lcd&tp code
authorlinjh <linjh@rock-chips.com>
Thu, 27 Sep 2012 09:36:04 +0000 (17:36 +0800)
committerlinjh <linjh@rock-chips.com>
Thu, 27 Sep 2012 10:04:00 +0000 (18:04 +0800)
[reference file]
modified:
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/video/display/screen/Kconfig
drivers/video/display/screen/Makefile
new file:
drivers/input/touchscreen/i30_ts.c
drivers/video/display/screen/lcd_I30_800x480.c

drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/i30_ts.c [new file with mode: 0755]
drivers/video/display/screen/Kconfig
drivers/video/display/screen/Makefile
drivers/video/display/screen/lcd_I30_800x480.c [new file with mode: 0755]

index 7e52d0be83693bfa8f7cfd06a66fc9fa74d71c21..f845d0cef81dca1c4c13c8ba90d52bbe586e0936 100644 (file)
@@ -1012,6 +1012,10 @@ config TOUCHSCREEN_FT5306
        tristate "FT5306 based touchscreens: FT5306 Interface"
        depends on I2C2_RK29 || I2C2_RK30
 
+config TOUCHSCREEN_I30
+       tristate "i30 based touchscreens: i30(ft5306) Interface"
+       depends on I2C2_RK29 || I2C2_RK30
+
 config TOUCHSCREEN_SITRONIX_A720
        tristate "SITRONIX based touchscreens: SITRONIX Interface for a720"
        depends on I2C2_RK29 || I2C2_RK30 
index b26f7e4393bf94802e45a668bdfa57f808b4d97c..c16a52bc175e2742be613ed7c6af3a2d8ff4d084 100644 (file)
@@ -92,3 +92,4 @@ obj-$(CONFIG_TOUCHSCREEN_NAS)         += nas_ts.o
 obj-$(CONFIG_LAIBAO_TS)                += ft5x0x_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PIXCIR)      += pixcir_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C_RK)      += rmi4/
+obj-$(CONFIG_TOUCHSCREEN_I30)  += i30_ts.o
diff --git a/drivers/input/touchscreen/i30_ts.c b/drivers/input/touchscreen/i30_ts.c
new file mode 100755 (executable)
index 0000000..2efb102
--- /dev/null
@@ -0,0 +1,914 @@
+/* 
+ * drivers/input/touchscreen/ft5x0x_ts.c
+ *
+ * FocalTech ft5x0x TouchScreen driver. 
+ *
+ * Copyright (c) 2010  Focal tech Ltd.
+ *
+ * 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.
+ *
+ *
+ *     note: only support mulititouch  Wenfs 2010-10-01
+ */
+
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/input-polldev.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#ifdef CONFIG_ANDROID_POWER
+#include <linux/android_power.h>
+#endif
+#include <mach/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+#include <asm/hardware/gic.h>
+#include <mach/iomux.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+//#include <mach/rk29_iomap.h>
+#include <mach/board.h>
+//#include <mach/rk29_nand.h>
+//#include <mach/rk29_camera.h>                          /* ddl@rock-chips.com : camera support */
+#include <media/soc_camera.h>                               /* ddl@rock-chips.com : camera support */
+//#include <mach/vpu_mem.h>
+#include <mach/sram.h>
+#include <linux/earlysuspend.h>
+static struct early_suspend ft5306_power;
+
+
+
+
+#define CONFIG_FT5X0X_MULTITOUCH  1
+#define MAX_POINT                 5
+#define FT5306_IIC_SPEED          50*1000    //300*1000
+#define FT5X0X_REG_THRES          0x80         /* Thresshold, the threshold be low, the sensitivy will be high */
+#define FT5X0X_REG_REPORT_RATE    0x88         /* **************report rate, in unit of 10Hz **************/
+#define FT5X0X_REG_PMODE          0xA5         /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */    
+#define FT5X0X_REG_FIRMID         0xA6         /* ***************firmware version **********************/
+#define FT5X0X_REG_NOISE_MODE     0xb2         /* to enable or disable power noise, 1 -- enable, 0 -- disable */
+#define SCREEN_MAX_X              800
+#define SCREEN_MAX_Y              480
+#define PRESS_MAX                 255
+#define FT5X0X_NAME                  "ft5x0x_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"// 
+#define TOUCH_MAJOR_MAX           200
+#define WIDTH_MAJOR_MAX           200
+//FT5X0X_REG_PMODE
+#define PMODE_ACTIVE              0x00
+#define PMODE_MONITOR             0x01
+#define PMODE_STANDBY             0x02
+#define PMODE_HIBERNATE           0x03
+
+
+struct ts_event {
+       s16  cur_touch_id[MAX_POINT];
+    s16  last_touch_id[MAX_POINT];
+};
+
+struct tp_event {
+       u16     x;
+       u16     y;
+    s16 id;
+       u16     pressure;
+       u8  touch_point;
+       u8  flag;
+};
+
+struct ft5x0x_ts_data {
+       struct i2c_client *client;
+       struct input_dev        *input_dev;
+       int    irq;
+       struct ts_event         event;
+       struct work_struct      pen_event_work;
+       struct workqueue_struct *ts_workqueue;
+};
+static struct i2c_client *this_client;
+
+/***********************************************************************/
+
+#define    FTS_PACKET_LENGTH        128
+
+
+static u8 CTPM_FW[]=
+{
+#include "ft5406_app.i"
+};
+
+typedef enum
+{
+    ERR_OK,
+    ERR_MODE,
+    ERR_READID,
+    ERR_ERASE,
+    ERR_STATUS,
+    ERR_ECC,
+    ERR_DL_ERASE_FAIL,
+    ERR_DL_PROGRAM_FAIL,
+    ERR_DL_VERIFY_FAIL
+}E_UPGRADE_ERR_TYPE;
+
+/***********************************************************************/
+
+/***********************************************************************
+    [function]: 
+                          callback:                send data to ctpm by i2c interface;
+    [parameters]:
+                           txdata[in]:              data buffer which is used to send data;
+                           length[in]:              the length of the data buffer;
+    [return]:
+                           FTS_TRUE:              success;
+                           FTS_FALSE:             fail;
+************************************************************************/
+static int fts_i2c_txdata(u8 *txdata, int length)
+{
+       int ret;
+
+       struct i2c_msg msg;
+
+       msg.addr = this_client->addr;
+       msg.flags = 0;
+       msg.len = length;
+       msg.buf = txdata;
+       msg.scl_rate = FT5306_IIC_SPEED;
+       
+       ret = i2c_transfer(this_client->adapter, &msg, 1);
+       if (ret < 0)
+               pr_err("%s i2c write error: %d\n", __func__, ret);
+
+       return ret;
+}
+
+/***********************************************************************
+    [function]: 
+                          callback:               write data to ctpm by i2c interface;
+    [parameters]:
+                           buffer[in]:             data buffer;
+                           length[in]:            the length of the data buffer;
+    [return]:
+                           FTS_TRUE:            success;
+                           FTS_FALSE:           fail;
+************************************************************************/
+static bool  i2c_write_interface(u8* pbt_buf, int dw_lenth)
+{
+    int ret;
+    ret=i2c_master_send(this_client, pbt_buf, dw_lenth);
+    if(ret<=0)
+    {
+        printk("[TSP]i2c_write_interface error line = %d, ret = %d\n", __LINE__, ret);
+        return false;
+    }
+
+    return true;
+}
+
+/***********************************************************************
+    [function]: 
+                          callback:                read register value ftom ctpm by i2c interface;
+    [parameters]:
+                        reg_name[in]:         the register which you want to write;
+                           tx_buf[in]:              buffer which is contained of the writing value;
+    [return]:
+                           FTS_TRUE:              success;
+                           FTS_FALSE:             fail;
+************************************************************************/
+static bool fts_register_write(u8 reg_name, u8* tx_buf)
+{
+       u8 write_cmd[2] = {0};
+
+       write_cmd[0] = reg_name;
+       write_cmd[1] = *tx_buf;
+
+       /*call the write callback function*/
+       return i2c_write_interface(write_cmd, 2);
+}
+
+/***********************************************************************
+[function]: 
+                      callback:         send a command to ctpm.
+[parameters]:
+                         btcmd[in]:       command code;
+                         btPara1[in]:     parameter 1;    
+                         btPara2[in]:     parameter 2;    
+                         btPara3[in]:     parameter 3;    
+                      num[in]:         the valid input parameter numbers, 
+                                           if only command code needed and no 
+                                           parameters followed,then the num is 1;    
+[return]:
+                         FTS_TRUE:      success;
+                         FTS_FALSE:     io fail;
+************************************************************************/
+static bool cmd_write(u8 btcmd,u8 btPara1,u8 btPara2,u8 btPara3,u8 num)
+{
+    u8 write_cmd[4] = {0};
+
+    write_cmd[0] = btcmd;
+    write_cmd[1] = btPara1;
+    write_cmd[2] = btPara2;
+    write_cmd[3] = btPara3;
+    return i2c_write_interface(write_cmd, num);
+}
+
+/***********************************************************************
+    [function]: 
+                          callback:              read data from ctpm by i2c interface;
+    [parameters]:
+                           buffer[in]:            data buffer;
+                           length[in]:           the length of the data buffer;
+    [return]:
+                           FTS_TRUE:            success;
+                           FTS_FALSE:           fail;
+************************************************************************/
+static bool i2c_read_interface(u8* pbt_buf, int dw_lenth)
+{
+    int ret;
+    
+    ret=i2c_master_recv(this_client, pbt_buf, dw_lenth);
+
+    if(ret<=0)
+    {
+        printk("[TSP]i2c_read_interface error\n");
+        return false;
+    }
+  
+    return true;
+}
+
+
+/***********************************************************************
+[function]: 
+                      callback:         read a byte data  from ctpm;
+[parameters]:
+                         buffer[in]:       read buffer;
+                         length[in]:      the size of read data;    
+[return]:
+                         FTS_TRUE:      success;
+                         FTS_FALSE:     io fail;
+************************************************************************/
+static bool byte_read(u8* buffer, int length)
+{
+    return i2c_read_interface(buffer, length);
+}
+
+/***********************************************************************
+[function]: 
+                      callback:         write a byte data  to ctpm;
+[parameters]:
+                         buffer[in]:       write buffer;
+                         length[in]:      the size of write data;    
+[return]:
+                         FTS_TRUE:      success;
+                         FTS_FALSE:     io fail;
+************************************************************************/
+static bool byte_write(u8* buffer, int length)
+{
+    
+    return i2c_write_interface(buffer, length);
+}
+
+/***********************************************************************
+    [function]: 
+                          callback:                 read register value ftom ctpm by i2c interface;
+    [parameters]:
+                        reg_name[in]:         the register which you want to read;
+                           rx_buf[in]:              data buffer which is used to store register value;
+                           rx_length[in]:          the length of the data buffer;
+    [return]:
+                           FTS_TRUE:              success;
+                           FTS_FALSE:             fail;
+************************************************************************/
+static bool fts_register_read(u8 reg_name, u8* rx_buf, int rx_length)
+{
+       u8 read_cmd[2]= {0};
+       u8 cmd_len      = 0;
+
+       read_cmd[0] = reg_name;
+       cmd_len = 1;    
+
+       /*send register addr*/
+       if(!i2c_write_interface(&read_cmd[0], cmd_len))
+       {
+               return false;
+       }
+
+       /*call the read callback function to get the register value*/           
+       if(!i2c_read_interface(rx_buf, rx_length))
+       {
+               return false;
+       }
+       return true;
+}
+
+
+
+/***********************************************************************
+[function]: 
+                        callback:          burn the FW to ctpm.
+[parameters]:
+                           pbt_buf[in]:     point to Head+FW ;
+                           dw_lenth[in]:   the length of the FW + 6(the Head length);    
+[return]:
+                           ERR_OK:          no error;
+                           ERR_MODE:      fail to switch to UPDATE mode;
+                           ERR_READID:   read id fail;
+                           ERR_ERASE:     erase chip fail;
+                           ERR_STATUS:   status error;
+                           ERR_ECC:        ecc error.
+************************************************************************/
+E_UPGRADE_ERR_TYPE  fts_ctpm_fw_upgrade(u8* pbt_buf, int dw_lenth)
+{
+    u8  cmd,reg_val[2] = {0};
+       u8  buffer[2] = {0};
+    u8  packet_buf[FTS_PACKET_LENGTH + 6];
+    u8  auc_i2c_write_buf[10];
+    u8  bt_ecc;
+       
+    int  j,temp,lenght,i_ret,packet_number, i = 0;
+    int  i_is_new_protocol = 0;
+       
+
+    /******write 0xaa to register 0xfc******/
+    cmd=0xaa;
+    fts_register_write(0xfc,&cmd);
+    mdelay(50);
+       
+     /******write 0x55 to register 0xfc******/
+    cmd=0x55;
+    fts_register_write(0xfc,&cmd);
+    printk("[TSP] Step 1: Reset CTPM test\n");
+   
+    mdelay(10);   
+
+
+    /*******Step 2:Enter upgrade mode ****/
+    printk("\n[TSP] Step 2:enter new update mode\n");
+    auc_i2c_write_buf[0] = 0x55;
+    auc_i2c_write_buf[1] = 0xaa;
+    do
+    {
+        i ++;
+        i_ret = fts_i2c_txdata(auc_i2c_write_buf, 2);
+        mdelay(5);
+    }while(i_ret <= 0 && i < 10 );
+
+    if (i > 1)
+    {
+        i_is_new_protocol = 1;
+    }
+
+    /********Step 3:check READ-ID********/        
+    cmd_write(0x90,0x00,0x00,0x00,4);
+    byte_read(reg_val,2);
+    if (reg_val[0] == 0x79 && reg_val[1] == 0x3)
+    {
+        printk("[TSP] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+    }
+    else
+    {
+        printk("[TSP] Step 3: error CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+        return ERR_READID;
+        //i_is_new_protocol = 1;
+    }
+    
+
+     /*********Step 4:erase app**********/
+    if (i_is_new_protocol)
+    {
+        cmd_write(0x61,0x00,0x00,0x00,1);
+    }
+    else
+    {
+        cmd_write(0x60,0x00,0x00,0x00,1);
+    }
+    mdelay(1500);
+    printk("[TSP] Step 4: erase. \n");
+
+
+
+    /*Step 5:write firmware(FW) to ctpm flash*/
+    bt_ecc = 0;
+    printk("[TSP] Step 5: start upgrade. \n");
+    dw_lenth = dw_lenth - 8;
+    packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+    packet_buf[0] = 0xbf;
+    packet_buf[1] = 0x00;
+    for (j=0;j<packet_number;j++)
+    {
+        temp = j * FTS_PACKET_LENGTH;
+        packet_buf[2] = (u8)(temp>>8);
+        packet_buf[3] = (u8)temp;
+        lenght = FTS_PACKET_LENGTH;
+        packet_buf[4] = (u8)(lenght>>8);
+        packet_buf[5] = (u8)lenght;
+
+        for (i=0;i<FTS_PACKET_LENGTH;i++)
+        {
+            packet_buf[6+i] = pbt_buf[j*FTS_PACKET_LENGTH + i]; 
+            bt_ecc ^= packet_buf[6+i];
+        }
+        
+        byte_write(&packet_buf[0],FTS_PACKET_LENGTH + 6);
+        mdelay(FTS_PACKET_LENGTH/6 + 1);
+        if ((j * FTS_PACKET_LENGTH % 1024) == 0)
+        {
+              printk("[TSP] upgrade the 0x%x th byte.\n", ((unsigned int)j) * FTS_PACKET_LENGTH);
+        }
+    }
+
+    if ((dw_lenth) % FTS_PACKET_LENGTH > 0)
+    {
+        temp = packet_number * FTS_PACKET_LENGTH;
+        packet_buf[2] = (u8)(temp>>8);
+        packet_buf[3] = (u8)temp;
+
+        temp = (dw_lenth) % FTS_PACKET_LENGTH;
+        packet_buf[4] = (u8)(temp>>8);
+        packet_buf[5] = (u8)temp;
+
+        for (i=0;i<temp;i++)
+        {
+            packet_buf[6+i] = pbt_buf[ packet_number*FTS_PACKET_LENGTH + i]; 
+            bt_ecc ^= packet_buf[6+i];
+        }
+
+        byte_write(&packet_buf[0],temp+6);    
+        mdelay(20);
+    }
+
+    /***********send the last six byte**********/
+    for (i = 0; i<6; i++)
+    {
+        temp = 0x6ffa + i;
+        packet_buf[2] = (u8)(temp>>8);
+        packet_buf[3] = (u8)temp;
+        temp =1;
+        packet_buf[4] = (u8)(temp>>8);
+        packet_buf[5] = (u8)temp;
+        packet_buf[6] = pbt_buf[ dw_lenth + i]; 
+        bt_ecc ^= packet_buf[6];
+
+        byte_write(&packet_buf[0],7);  
+        mdelay(20);
+    }
+
+    /********send the opration head************/
+    cmd_write(0xcc,0x00,0x00,0x00,1);
+    byte_read(reg_val,1);
+    printk("[TSP] Step 6:  ecc read 0x%x, new firmware 0x%x. \n", reg_val[0], bt_ecc);
+    if(reg_val[0] != bt_ecc)
+    {
+        return ERR_ECC;
+    }
+
+    /*******Step 7: reset the new FW**********/
+    cmd_write(0x07,0x00,0x00,0x00,1);
+       mdelay(100);//100ms     
+       fts_register_read(0xfc, buffer, 1);     
+       if (buffer[0] == 1)
+       {
+       cmd=4;
+       fts_register_write(0xfc, &cmd);
+       mdelay(2500);//2500ms   
+        do     
+        {      
+        fts_register_read(0xfc, buffer, 1);    
+        mdelay(100);//100ms    
+        }while (buffer[0] != 1);                       
+       }
+    return ERR_OK;
+}
+
+
+/***********************************************************************/
+
+int fts_ctpm_fw_upgrade_with_i_file(void)
+{
+   u8*     pbt_buf = 0;
+   int i_ret;
+    
+   pbt_buf = CTPM_FW;
+   i_ret =  fts_ctpm_fw_upgrade(pbt_buf,sizeof(CTPM_FW));
+   
+   return i_ret;
+}
+
+/***********************************************************************/
+
+unsigned char fts_ctpm_get_upg_ver(void)
+{
+    unsigned int ui_sz;
+       
+    ui_sz = sizeof(CTPM_FW);
+    if (ui_sz > 2)
+    {
+        return CTPM_FW[ui_sz - 2];
+    }
+    else
+        return 0xff; 
+}
+
+static int ft5306_init_touchid(s16 touch_buf[], unsigned len,s16 init_val)
+{
+       int i;
+       for(i=0;i<len;i++){
+               touch_buf[i] = init_val;
+       }
+       return 0;
+}
+
+/*read the it7260 register ,used i2c bus*/
+static int ft5306_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len)
+{
+       int ret; 
+       ret = i2c_master_reg8_recv(client, reg, buf, len, FT5306_IIC_SPEED);
+       return ret; 
+}
+
+
+/* set the it7260 registe,used i2c bus*/
+static int ft5306_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], unsigned short len)
+{
+       int ret; 
+       ret = i2c_master_reg8_send(client, reg, buf, (int)len, FT5306_IIC_SPEED);
+       return ret;
+}
+
+static void ft5306_queue_work(struct work_struct *work)
+{
+       struct ft5x0x_ts_data *data = container_of(work, struct ft5x0x_ts_data, pen_event_work);
+       struct tp_event event;
+       u8 start_reg=0x0;
+       u8 buf[32] = {0};
+       int ret,i,offset,points;
+               
+#if CONFIG_FT5X0X_MULTITOUCH
+       ret = ft5306_read_regs(data->client,start_reg, buf, 6*MAX_POINT+1);
+#else
+       ret = ft5306_read_regs(data->client,start_reg, buf, 7);
+#endif
+       if (ret < 0) {
+               dev_err(&data->client->dev, "ft5306_read_regs fail:%d!\n",ret);
+               enable_irq(data->irq);
+               return;
+       }
+       
+       points = buf[2] & 0x07;
+       memset(&event, 0, sizeof(struct tp_event));
+#if CONFIG_FT5X0X_MULTITOUCH
+       ft5306_init_touchid(data->event.cur_touch_id,MAX_POINT,-1);
+//     dev_info(&data->client->dev, 
+//             "ft5306 multiple report points = %d :\n",points);
+       for(i=0;i<points;i++){
+               offset = i*6+3;
+               event.x = (((s16)(buf[offset+0] & 0x0F))<<8) | ((s16)buf[offset+1]);
+               event.y = (((s16)(buf[offset+2] & 0x0F))<<8) | ((s16)buf[offset+3]);
+               event.id = (s16)(buf[offset+2] & 0xF0)>>4;
+               event.flag = ((buf[offset+0] & 0xc0) >> 6);
+               event.pressure = 200;
+               if(event.x<=SCREEN_MAX_X && event.y<=SCREEN_MAX_Y && event.id < MAX_POINT){
+//                     dev_info(&data->client->dev, 
+//                             "ft5306 multiple report event[%d]:x = %d,y = %d,last_id = %d,cur_id = %d,flag = %d,pressure = %d\n",
+//                             i,event.x,event.y,data->event.last_touch_id[event.id],event.id,event.flag,event.pressure);
+                       input_mt_slot(data->input_dev, event.id);
+                       data->event.cur_touch_id[event.id] = event.id;
+                       if(data->event.last_touch_id[event.id] != event.id){
+                               input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event.id);
+                               data->event.last_touch_id[event.id] = event.id;
+                       }
+                       input_report_abs(data->input_dev, ABS_MT_POSITION_X,  event.x);
+                       input_report_abs(data->input_dev, ABS_MT_POSITION_Y,  event.y);
+//                     dev_info(&data->client->dev,"new last_id=%d,cur_id = %d\n",data->event.last_touch_id[event.id],
+//                             data->event.cur_touch_id[event.id]);
+               }
+       }
+       for(i=0;i<MAX_POINT;i++){
+               if(data->event.last_touch_id[i] != data->event.cur_touch_id[i]){
+//                     dev_info(&data->client->dev,"release id=%d: last_id=%d,cur_id = %d\n",i,data->event.last_touch_id[i],
+//                             data->event.cur_touch_id[i]);
+                       data->event.last_touch_id[i] = data->event.cur_touch_id[i];
+                       input_mt_slot(data->input_dev, i);
+                       input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, data->event.cur_touch_id[i]);
+               }
+       }
+#else
+       if (points == 0) {
+               input_report_abs(data->input_dev, ABS_PRESSURE, 0);
+               input_report_key(data->input_dev, BTN_TOUCH, 0);
+               input_sync(data->input_dev);
+               enable_irq(data->irq);
+//             dev_info(&data->client->dev, "ft5306 touch release\n");
+               return; 
+       }
+       event.x = (s16)(buf[3] & 0x0F)<<8 | (s16)buf[4];
+       event.y = (s16)(buf[5] & 0x0F)<<8 | (s16)buf[6];
+       event.pressure =200;
+       input_report_abs(data->input_dev, ABS_X, event.x);
+       input_report_abs(data->input_dev, ABS_Y, event.y);
+       input_report_abs(data->input_dev, ABS_PRESSURE, event.pressure);
+       input_report_key(data->input_dev, BTN_TOUCH, 1);
+       //dev_info(&data->client->dev, "ft5306 single report event:x = %d,y = %d\n",event.x,event.y);
+#endif
+       input_sync(data->input_dev);
+       enable_irq(data->irq);
+       return;
+}
+
+static irqreturn_t ft5306_interrupt(int irq, void *dev_id)
+{
+       struct ft5x0x_ts_data *ft5x0x_ts = dev_id;
+
+       //printk("ft5306_interrupt\n");
+       disable_irq_nosync(ft5x0x_ts->irq);
+       if (!work_pending(&ft5x0x_ts->pen_event_work)) 
+               queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work);
+       return IRQ_HANDLED;
+}
+
+static int ft5306_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client);
+       struct ft5306_platform_data *pdata = client->dev.platform_data;
+       
+       if (pdata->platform_sleep)                              
+               pdata->platform_sleep();
+       disable_irq(ft5x0x_ts->irq);
+       return 0;
+}
+
+
+static int ft5306_resume(struct i2c_client *client)
+{
+       struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client);
+       struct ft5306_platform_data *pdata = client->dev.platform_data;
+       
+       enable_irq(ft5x0x_ts->irq);
+       if (pdata->platform_wakeup)                              
+               pdata->platform_wakeup();
+       return 0;
+}
+
+static void ft5306_suspend_early(struct early_suspend *h)
+{
+       ft5306_suspend(this_client,PMSG_SUSPEND);
+}
+
+static void ft5306_resume_early(struct early_suspend *h)
+{
+       ft5306_resume(this_client);
+}
+static int __devexit ft5306_remove(struct i2c_client *client)
+{
+       struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client);
+
+       free_irq(ft5x0x_ts->irq, ft5x0x_ts);
+       input_unregister_device(ft5x0x_ts->input_dev);
+       kfree(ft5x0x_ts);
+       cancel_work_sync(&ft5x0x_ts->pen_event_work);
+       destroy_workqueue(ft5x0x_ts->ts_workqueue);
+       i2c_set_clientdata(client, NULL);
+    unregister_early_suspend(&ft5306_power);
+    this_client = NULL;
+       return 0;
+}
+
+static int  ft5306_probe(struct i2c_client *client ,const struct i2c_device_id *id)
+{
+       struct ft5x0x_ts_data *ft5x0x_ts;
+       struct input_dev *input_dev;
+       struct ft5306_platform_data *pdata = client->dev.platform_data;
+       int err = 0;
+       int ret = 0;
+       int retry = 0;
+       u8 buf_w[1];
+       u8 buf_r[1];
+       const u8 buf_test[1] = {0};
+    unsigned char reg_value;
+    unsigned char reg_version;
+
+       dev_info(&client->dev, "ft5x0x_ts_probe!\n");
+       if (!pdata) {
+               dev_err(&client->dev, "platform data is required!\n");
+               return -EINVAL;
+       }
+
+       if (pdata->init_platform_hw)                              
+               pdata->init_platform_hw();
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
+               dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
+               return -ENODEV;
+       }
+       
+       ft5x0x_ts = kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL);
+       if (!ft5x0x_ts) {
+               return -ENOMEM;
+       }
+
+       while(retry < 5)
+       {
+               ret=ft5306_set_regs(client,FT5X0X_REG_PMODE, buf_test,1);
+               if(ret > 0)break;
+               retry++;
+       }
+       if(ret <= 0)
+       {
+               printk("FT5306 I2C TEST ERROR!\n");
+               err = -ENODEV;
+               goto exit_i2c_test_fail;
+       }
+       buf_r[0] = 0xff;
+       err = ft5306_read_regs(client,FT5X0X_REG_PMODE,buf_r,1);
+       printk("read buf[FT5X0X_REG_PMODE] = %d\n", buf_r[0]);
+
+       
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               err = -ENOMEM;
+               printk("failed to allocate input device\n");
+               goto exit_input_dev_alloc_failed;
+       }
+       ft5x0x_ts->client = this_client = client;
+       ft5x0x_ts->irq = pdata->irq_pin;
+       ft5x0x_ts->input_dev = input_dev;
+
+       set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+       set_bit(EV_ABS, input_dev->evbit);
+       
+#if CONFIG_FT5X0X_MULTITOUCH
+       ft5306_init_touchid(ft5x0x_ts->event.cur_touch_id,MAX_POINT,-1);
+       ft5306_init_touchid(ft5x0x_ts->event.last_touch_id,MAX_POINT,-1);
+       input_mt_init_slots(input_dev, MAX_POINT);
+       input_set_abs_params(input_dev,ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
+       input_set_abs_params(input_dev,ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
+#else
+       set_bit(ABS_X, input_dev->absbit);
+       set_bit(ABS_Y, input_dev->absbit);
+       set_bit(ABS_PRESSURE, input_dev->absbit);
+       set_bit(BTN_TOUCH, input_dev->keybit);
+       input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, PRESS_MAX, 0 , 0);
+#endif
+       
+       input_dev->name         = FT5X0X_NAME;
+       input_dev->id.bustype = BUS_I2C;
+       
+       err = input_register_device(input_dev);
+       if (err) {
+               printk("ft5x0x_ts_probe: failed to register input device: \n");
+               goto exit_input_register_device_failed;
+       }
+
+       if (!ft5x0x_ts->irq) {
+               err = -ENODEV;
+               dev_err(&ft5x0x_ts->client->dev, "no IRQ?\n");
+               goto exit_no_irq_fail;
+       }else{
+               ft5x0x_ts->irq = gpio_to_irq(ft5x0x_ts->irq);
+       }
+
+       //INIT_WORK(&ft5x0x_ts->pen_event_work, ft5306_ts_pen_irq_work);
+       INIT_WORK(&ft5x0x_ts->pen_event_work, ft5306_queue_work);
+       ft5x0x_ts->ts_workqueue = create_singlethread_workqueue("ft5x0x_ts");
+       if (!ft5x0x_ts->ts_workqueue) {
+               err = -ESRCH;
+               goto exit_create_singlethread;
+       }
+
+       /***wait CTP to bootup normally***/
+        msleep(200); 
+        
+        fts_register_read(FT5X0X_REG_FIRMID, &reg_version,1);
+        printk("[TSP] firmware version = 0x%2x\n", reg_version);
+        fts_register_read(FT5X0X_REG_REPORT_RATE, &reg_value,1);
+        printk("[TSP]firmware report rate = %dHz\n", reg_value*10);
+        fts_register_read(FT5X0X_REG_THRES, &reg_value,1);
+        printk("[TSP]firmware threshold = %d\n", reg_value * 4);
+        fts_register_read(FT5X0X_REG_NOISE_MODE, &reg_value,1);
+        printk("[TSP]nosie mode = 0x%2x\n", reg_value);
+
+#if 0
+         if (fts_ctpm_get_upg_ver() != reg_version)  
+         {
+                 printk("[TSP] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver());
+                 msleep(200);
+                 err =  fts_ctpm_fw_upgrade_with_i_file();
+                 if (err == 0)
+                 {
+                         printk("[TSP] ugrade successfuly.\n");
+                         msleep(300);
+                         fts_register_read(FT5X0X_REG_FIRMID, &reg_value,1);
+                         printk("FTS_DBG from old version 0x%2x to new version = 0x%2x\n", reg_version, reg_value);
+                 }
+                 else
+                 {
+                         printk("[TSP]  ugrade fail err=%d, line = %d.\n",err, __LINE__);
+                 }
+                 msleep(4000);
+         }
+#endif
+
+       //printk("client->dev.driver->name %s  ,%d \n",client->dev.driver->name,ft5x0x_ts->irq);
+       ret = request_irq(ft5x0x_ts->irq, ft5306_interrupt, IRQF_TRIGGER_FALLING, client->dev.driver->name, ft5x0x_ts);
+       if (ret < 0) {
+               dev_err(&client->dev, "irq %d busy?\n", ft5x0x_ts->irq);
+               goto exit_irq_request_fail;
+       }
+       
+       i2c_set_clientdata(client, ft5x0x_ts);
+       ft5306_power.suspend =ft5306_suspend_early;
+       ft5306_power.resume =ft5306_resume_early;
+       ft5306_power.level = 0x2;
+       register_early_suspend(&ft5306_power);
+
+       buf_w[0] = 6;
+       err = ft5306_set_regs(client,0x88,buf_w,1);
+       buf_r[0] = 0;
+       err = ft5306_read_regs(client,0x88,buf_r,1);
+       printk("read buf[0x88] = %d\n", buf_r[0]);
+    return 0;
+
+       i2c_set_clientdata(client, NULL);
+       free_irq(ft5x0x_ts->irq,ft5x0x_ts);
+exit_irq_request_fail:
+       cancel_work_sync(&ft5x0x_ts->pen_event_work);
+       destroy_workqueue(ft5x0x_ts->ts_workqueue);
+exit_create_singlethread:
+exit_no_irq_fail:
+       input_unregister_device(input_dev);
+exit_input_register_device_failed:
+       input_free_device(input_dev);
+exit_input_dev_alloc_failed:
+exit_i2c_test_fail:
+       if (pdata->exit_platform_hw)                              
+               pdata->exit_platform_hw();
+       kfree(ft5x0x_ts);
+       return err;
+}
+
+
+
+static struct i2c_device_id ft5306_idtable[] = {
+       { FT5X0X_NAME, 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, ft5306_idtable);
+
+static struct i2c_driver ft5306_driver  = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = FT5X0X_NAME
+       },
+       .id_table       = ft5306_idtable,
+       .probe      = ft5306_probe,
+       .remove         = __devexit_p(ft5306_remove),
+};
+
+static int __init ft5306_ts_init(void)
+{
+       return i2c_add_driver(&ft5306_driver);
+}
+
+static void __exit ft5306_ts_exit(void)
+{
+       printk("Touchscreen driver of ft5306 exited.\n");
+       i2c_del_driver(&ft5306_driver);
+}
+
+
+/***********************************************************************/
+
+module_init(ft5306_ts_init);
+module_exit(ft5306_ts_exit);
+
+MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");
+MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");
+
index b48432077a67586146a1f8265f96d07eb5f994b2..4f91721ad1509d75c63976301f8a2cbca77d0c49 100755 (executable)
@@ -104,6 +104,9 @@ config LCD_HSD07PFW1
        depends on MFD_RK610
        bool "RGB lcd panel HSD07PFW1"
 
+config LCD_I30_800X480
+        bool "lcd I30"
+
 endchoice
 
 
index e96a92379f9c782c7a2cb276ea3fcf2b2e7bc0d2..553a45d80e1e913fd5a109511ba6810d009fcc56 100755 (executable)
@@ -46,3 +46,4 @@ obj-$(CONFIG_LCD_RK2928_A720) += lcd_YQ70CPT9160.o
 obj-$(CONFIG_LCD_HSD07PFW1) += lcd_hsd07pfw1.o\r
 obj-$(CONFIG_LCD_HJ080NA)    += lcd_hj080na.o
 obj-$(CONFIG_LCD_HJ101NA)   += lcd_hj101na.o
+obj-$(CONFIG_LCD_I30_800X480)   += lcd_I30_800x480.o
diff --git a/drivers/video/display/screen/lcd_I30_800x480.c b/drivers/video/display/screen/lcd_I30_800x480.c
new file mode 100755 (executable)
index 0000000..ee210e1
--- /dev/null
@@ -0,0 +1,109 @@
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include "../../rk29_fb.h"
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <mach/board.h>
+#include "screen.h"
+
+/* Base */
+#define LCD_WIDTH       154    //need modify
+#define LCD_HEIGHT      85
+
+#define OUT_TYPE               SCREEN_RGB
+#define OUT_FACE               OUT_P666
+#define OUT_CLK                         30000000
+#define LCDC_ACLK       150000000     //29 lcdc axi DMA ÆµÂÊ
+
+/* Timing */
+#define H_PW                   48 //10
+#define H_BP                   88 //100
+#define H_VD                   800
+#define H_FP                   40 //210
+
+#define V_PW                   3 //10
+#define V_BP                   32 //10
+#define V_VD                   480
+#define V_FP                   13 //18
+
+/* Other */
+#define DCLK_POL               1
+#define SWAP_RB                        0
+
+static struct rk29lcd_info *gLcd_info = NULL;
+
+static int init(void)
+{
+       int ret = 0;
+       
+       if(gLcd_info && gLcd_info->io_init)
+               gLcd_info->io_init();
+
+       return 0;
+}
+
+static int standby(u8 enable)
+{
+       if(!enable)
+       {
+               if(gLcd_info && gLcd_info->io_enable)
+                       gLcd_info->io_enable();
+       }
+       else 
+       {
+               if(gLcd_info && gLcd_info->io_disable)
+                       gLcd_info->io_disable();
+       }
+       return 0;
+}
+
+void set_lcd_info(struct rk29fb_screen *screen,  struct rk29lcd_info *lcd_info )
+{
+    /* screen type & face */
+    screen->type = OUT_TYPE;
+    screen->face = OUT_FACE;
+
+    /* Screen size */
+    screen->x_res = H_VD;
+    screen->y_res = V_VD;
+
+    screen->width = LCD_WIDTH;
+    screen->height = LCD_HEIGHT;
+
+    /* Timing */
+    screen->lcdc_aclk = LCDC_ACLK;
+    screen->pixclock = OUT_CLK;
+       screen->left_margin = H_BP;
+       screen->right_margin = H_FP;
+       screen->hsync_len = H_PW;
+       screen->upper_margin = V_BP;
+       screen->lower_margin = V_FP;
+       screen->vsync_len = V_PW;
+
+       /* Pin polarity */
+       screen->pin_hsync = 0;
+       screen->pin_vsync = 0;
+       screen->pin_den = 0;
+       screen->pin_dclk = DCLK_POL;
+
+       /* Swap rule */
+    screen->swap_rb = SWAP_RB;
+    screen->swap_rg = 0;
+    screen->swap_gb = 0;
+    screen->swap_delta = 0;
+    screen->swap_dumy = 0;
+
+       /* Operation function*/
+       screen->init = init;
+       screen->standby = standby;
+       if(lcd_info)
+       {
+               gLcd_info = lcd_info;
+       }
+       else
+       {
+               printk("%s lcd_info==NULL\n", __func__);
+       }
+
+}
+