From 9034a60edeec4f5265cbf0b38387024afcd13d4d Mon Sep 17 00:00:00 2001 From: linjh Date: Thu, 27 Sep 2012 17:36:04 +0800 Subject: [PATCH] phonepad: commit phonepad(i30) lcd&tp code [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 | 4 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/i30_ts.c | 914 ++++++++++++++++++ drivers/video/display/screen/Kconfig | 3 + drivers/video/display/screen/Makefile | 1 + .../video/display/screen/lcd_I30_800x480.c | 109 +++ 6 files changed, 1032 insertions(+) create mode 100755 drivers/input/touchscreen/i30_ts.c create mode 100755 drivers/video/display/screen/lcd_I30_800x480.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 7e52d0be8369..f845d0cef81d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -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 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index b26f7e4393bf..c16a52bc175e 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -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 index 000000000000..2efb1029b330 --- /dev/null +++ b/drivers/input/touchscreen/i30_ts.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ANDROID_POWER +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +//#include +//#include /* ddl@rock-chips.com : camera support */ +#include /* ddl@rock-chips.com : camera support */ +//#include +#include +#include +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>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 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>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;iclient,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>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;ievent.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, ®_version,1); + printk("[TSP] firmware version = 0x%2x\n", reg_version); + fts_register_read(FT5X0X_REG_REPORT_RATE, ®_value,1); + printk("[TSP]firmware report rate = %dHz\n", reg_value*10); + fts_register_read(FT5X0X_REG_THRES, ®_value,1); + printk("[TSP]firmware threshold = %d\n", reg_value * 4); + fts_register_read(FT5X0X_REG_NOISE_MODE, ®_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, ®_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(""); +MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver"); + diff --git a/drivers/video/display/screen/Kconfig b/drivers/video/display/screen/Kconfig index b48432077a67..4f91721ad150 100755 --- a/drivers/video/display/screen/Kconfig +++ b/drivers/video/display/screen/Kconfig @@ -104,6 +104,9 @@ config LCD_HSD07PFW1 depends on MFD_RK610 bool "RGB lcd panel HSD07PFW1" +config LCD_I30_800X480 + bool "lcd I30" + endchoice diff --git a/drivers/video/display/screen/Makefile b/drivers/video/display/screen/Makefile index e96a92379f9c..553a45d80e1e 100755 --- a/drivers/video/display/screen/Makefile +++ b/drivers/video/display/screen/Makefile @@ -46,3 +46,4 @@ obj-$(CONFIG_LCD_RK2928_A720) += lcd_YQ70CPT9160.o obj-$(CONFIG_LCD_HSD07PFW1) += lcd_hsd07pfw1.o 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 index 000000000000..ee210e126101 --- /dev/null +++ b/drivers/video/display/screen/lcd_I30_800x480.c @@ -0,0 +1,109 @@ +#include +#include +#include "../../rk29_fb.h" +#include +#include +#include +#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__); + } + +} + -- 2.34.1