rk3168: ds1006h: update touchscreen(ct363)

This commit is contained in:
kfx
2012-12-31 17:12:24 +08:00
parent 0ad0517617
commit 1bfe9d02e8
6 changed files with 248 additions and 265 deletions

View File

@@ -102,7 +102,7 @@ struct rk29_keys_platform_data rk29_keys_pdata = {
#if defined(CONFIG_CT36X_TS)
#define TOUCH_MODEL 365
#define TOUCH_MODEL 363
#define TOUCH_MAX_X 1280
#define TOUCH_MAX_y 800
#define TOUCH_RESET_PIN RK30_PIN0_PB6

View File

@@ -315,8 +315,8 @@ int ct36x_chip_go_bootloader(struct ct36x_data *ts)
// Write source data
ret = ct36x_chip_wr_firmware(ts);
dev_err(ts->dev, "CT36X chip: Failed to write firmware\n");
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to write firmware\n");
return ret;
}
return 0;

View File

@@ -0,0 +1,225 @@
#define CT363_POINT_NUM 10
struct ct363_finger_data {
unsigned char xhi; // X coordinate Hi
unsigned char yhi; // Y coordinate Hi
unsigned char ylo : 4; // Y coordinate Lo
unsigned char xlo : 4; // X coordinate Lo
unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM
unsigned char area; // Touch area
unsigned char pressure; // Touch Pressure
};
struct ct363_priv{
int press;
int release;
int x, y;
union{
struct ct363_finger_data pts[CT363_POINT_NUM];
char buf[CT363_POINT_NUM * sizeof(struct ct363_finger_data)];
};
};
static int ct363_init_hw(struct ct36x_data *ts)
{
int ret = 0;
ret = gpio_request(ts->rst_io.gpio, "ct363_rst");
if(ret < 0){
dev_err(ts->dev, "Failed to request rst gpio\n");
return ret;
}
ret = gpio_request(ts->irq_io.gpio, "ct363_irq");
if(ret < 0){
gpio_free(ts->rst_io.gpio);
dev_err(ts->dev, "Failed to request irq gpio\n");
return ret;
}
gpio_direction_input(ts->irq_io.gpio);
gpio_pull_updown(ts->irq_io.gpio, 1);
gpio_direction_output(ts->rst_io.gpio, ts->rst_io.active_low);
return 0;
}
static void ct363_deinit_hw(struct ct36x_data *ts)
{
gpio_free(ts->rst_io.gpio);
gpio_free(ts->irq_io.gpio);
}
static void ct363_reset_hw(struct ct36x_data *ts)
{
gpio_direction_output(ts->rst_io.gpio, ts->rst_io.active_low);
msleep(50);
gpio_set_value(ts->rst_io.gpio, !ts->rst_io.active_low);
msleep(50);
gpio_set_value(ts->rst_io.gpio, ts->rst_io.active_low);
msleep(500);
}
static int ct363_init(struct ct36x_data *ts)
{
int ret = 0, fwchksum, binchksum, updcnt = 5;
struct ct363_priv *ct363 = NULL;
ret = ct363_init_hw(ts);
if(ret < 0)
return ret;
/* Hardware reset */
ct363_reset_hw(ts);
// Get binary Checksum
binchksum = ct36x_chip_get_binchksum();
ct36x_dbg(ts, "CT363 init: binchksum = %d\n", binchksum);
ret = ct36x_chip_get_fwchksum(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to get fwchksum\n");
return ret;
}
fwchksum = ret;
ct36x_dbg(ts, "CT363 init: fwchksum = %d\n", fwchksum);
while(binchksum != fwchksum && updcnt--) {
/* Update Firmware */
ret = ct36x_chip_go_bootloader(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to go bootloader\n");
return ret;
}
/* Hardware reset */
ct363_reset_hw(ts);
ret = ct36x_chip_get_fwchksum(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to get fwchksum\n");
return ret;
}
fwchksum = ret;
ct36x_dbg(ts, "CT363 update FW: fwchksum = %d\n", fwchksum);
}
if(binchksum != fwchksum){
dev_err(ts->dev, "Fail to update FW\n");
return -ENODEV;
}
/* Hardware reset */
ct363_reset_hw(ts);
msleep(5);
ts->point_num = CT363_POINT_NUM;
ct363 = kzalloc(sizeof(struct ct363_priv), GFP_KERNEL);
if(!ct363){
dev_err(ts->dev, "No memory for ct36x");
return -ENOMEM;
}
ts->priv = ct363;
return 0;
}
static void ct363_deinit(struct ct36x_data *ts)
{
struct ct363_priv *ct363 = ts->priv;
ct363_deinit_hw(ts);
kfree(ct363);
ts->priv = NULL;
return;
}
static int ct363_suspend(struct ct36x_data *ts)
{
int ret = 0;
ret = ct36x_chip_go_sleep(ts);
if(ret < 0)
dev_warn(ts->dev, "CT363 chip: failed to go to sleep\n");
return ret;
}
static int ct363_resume(struct ct36x_data *ts)
{
int i;
/* Hardware reset */
ct363_reset_hw(ts);
msleep(3);
for(i = 0; i < ts->point_num; i++){
input_mt_slot(ts->input, i);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
}
input_sync(ts->input);
return 0;
}
static void ct363_report(struct ct36x_data *ts)
{
int i, ret = 0;
int sync = 0, x, y;
int len = sizeof(struct ct363_finger_data) * ts->point_num;
struct ct363_priv *ct363 = ts->priv;
ret = ct36x_read(ts, ct363->buf, len);
if(ret < 0){
dev_warn(ts->dev, "Failed to read finger data\n");
return;
}
ct363->press = 0;
for(i = 0; i < ts->point_num; i++){
if((ct363->pts[i].xhi != 0xFF && ct363->pts[i].yhi != 0xFF) &&
(ct363->pts[i].status == 1 || ct363->pts[i].status == 2)){
x = (ct363->pts[i].xhi<<4)|(ct363->pts[i].xlo&0xF);
y = (ct363->pts[i].yhi<<4)|(ct363->pts[i].ylo&0xF);
ct363->x = ts->orientation[0] * x + ts->orientation[1] * y;
ct363->y = ts->orientation[2] * x + ts->orientation[3] * y;
if(ct363->x < 0)
ct363->x = ts->x_max - ct363->x;
if(ct363->y < 0)
ct363->y = ts->y_max - ct363->y;
input_mt_slot(ts->input, ct363->pts[i].id - 1);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 1);
input_report_abs(ts->input, ABS_MT_POSITION_X, x);
input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
input_report_abs(ts->input, ABS_MT_PRESSURE, ct363->pts[i].pressure);
ct36x_dbg(ts, "CT363 report value: x: %d, y:%d\n", ct363->x, ct363->y);
sync = 1;
ct363->press |= 0x01 << (ct363->pts[i].id - 1);
}
}
ct363->release &= ct363->release ^ ct363->press;
for(i = 0; i < ts->point_num; i++){
if ( ct363->release & (0x01<<i) ) {
input_mt_slot(ts->input, i);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
ct36x_dbg(ts, "CT363 release\n");
sync = 1;
}
}
ct363->release = ct363->press;
if(sync)
input_sync(ts->input);
return;
}
struct ct36x_ops ct363_ops = {
.init = ct363_init,
.deinit = ct363_deinit,
.suspend = ct363_suspend,
.resume = ct363_resume,
.report = ct363_report,
};

View File

@@ -1,255 +0,0 @@
#define CT365_POINT_NUM 10
struct ct365_finger_data {
unsigned char status : 4; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 4; // ID information, from 1 to CFG_MAX_POINT_NUM
unsigned char xhi; // X coordinate Hi
unsigned char yhi; // Y coordinate Hi
unsigned char ylo : 4; // Y coordinate Lo
unsigned char xlo : 4; // X coordinate Lo
unsigned char area; // Touch area
unsigned char pressure; // Touch Pressure
};
struct ct365_priv{
int press;
int release;
int x, y;
union{
struct ct365_finger_data pts[CT365_POINT_NUM];
char buf[CT365_POINT_NUM * sizeof(struct ct365_finger_data)];
};
};
static int ct365_init_hw(struct ct36x_data *ts)
{
int ret = 0;
ret = gpio_request(ts->rst_io.gpio, "ct365_rst");
if(ret < 0){
dev_err(ts->dev, "Failed to request rst gpio\n");
return ret;
}
ret = gpio_request(ts->irq_io.gpio, "ct365_irq");
if(ret < 0){
gpio_free(ts->rst_io.gpio);
dev_err(ts->dev, "Failed to request irq gpio\n");
return ret;
}
gpio_direction_input(ts->irq_io.gpio);
gpio_pull_updown(ts->irq_io.gpio, 1);
gpio_direction_output(ts->rst_io.gpio, ts->rst_io.active_low);
return 0;
}
static void ct365_deinit_hw(struct ct36x_data *ts)
{
gpio_free(ts->rst_io.gpio);
gpio_free(ts->irq_io.gpio);
}
static void ct365_reset_hw(struct ct36x_data *ts)
{
gpio_direction_output(ts->rst_io.gpio, ts->rst_io.active_low);
msleep(50);
gpio_set_value(ts->rst_io.gpio, !ts->rst_io.active_low);
msleep(50);
gpio_set_value(ts->rst_io.gpio, ts->rst_io.active_low);
msleep(500);
}
static int ct365_init(struct ct36x_data *ts)
{
int ret = 0, fwchksum, binchksum, updcnt = 5;
struct ct365_priv *ct365 = NULL;
ret = ct365_init_hw(ts);
if(ret < 0)
return ret;
/* Hardware reset */
ct365_reset_hw(ts);
// Get binary Checksum
binchksum = ct36x_chip_get_binchksum();
ct36x_dbg(ts, "CT365 init: binchksum = %d\n", binchksum);
ret = ct36x_chip_get_fwchksum(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to get fwchksum\n");
return ret;
}
fwchksum = ret;
ct36x_dbg(ts, "CT365 init: fwchksum = %d\n", fwchksum);
while(binchksum != fwchksum && updcnt--) {
/* Update Firmware */
ret = ct36x_chip_go_bootloader(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to go bootloader\n");
return ret;
}
/* Hardware reset */
ct365_reset_hw(ts);
ret = ct36x_chip_get_fwchksum(ts);
if(ret < 0){
dev_err(ts->dev, "CT36X chip: Failed to get fwchksum\n");
return ret;
}
fwchksum = ret;
ct36x_dbg(ts, "CT365 update FW: fwchksum = %d\n", fwchksum);
}
if(binchksum != fwchksum){
dev_err(ts->dev, "Fail to update FW\n");
return -ENODEV;
}
/* Hardware reset */
ct365_reset_hw(ts);
ret = ct36x_chip_set_idle(ts);
if(ret < 0){
dev_err(ts->dev, "CT365 init: Failed to set idle\n");
return ret;
}
msleep(5);
ts->point_num = CT365_POINT_NUM;
ct365 = kzalloc(sizeof(struct ct365_priv), GFP_KERNEL);
if(!ct365){
dev_err(ts->dev, "No memory for ct36x");
return -ENOMEM;
}
return 0;
}
static void ct365_deinit(struct ct36x_data *ts)
{
struct ct365_priv *ct365 = ts->priv;
ct365_deinit_hw(ts);
kfree(ct365);
ts->priv = NULL;
return;
}
static int ct365_suspend(struct ct36x_data *ts)
{
int ret = 0;
char buf[3];
buf[0] = 0xFF;
buf[1] = 0x8F;
buf[2] = 0xFF;
ret = ct36x_write(ts, buf, 3);
if(ret < 0)
dev_warn(ts->dev, "CT365 suspend: i2c write(0xff, 0x8f, 0xff) error\n");
msleep(3);
buf[0] = 0x00;
buf[1] = 0xAF;
ret = ct36x_write(ts, buf, 2);
if(ret < 0)
dev_warn(ts->dev, "CT365 suspend: i2c write(0x00, 0xaf) error\n");
msleep(3);
return ret;
}
static int ct365_resume(struct ct36x_data *ts)
{
int i, ret = 0;
char buf[2];
/* Hardware reset */
ct365_reset_hw(ts);
buf[0] = 0x00;
buf[1] = 0x5A;
ret = ct36x_update_write(ts, 0x7F, buf, 2);
if(ret < 0)
dev_warn(ts->dev, "CT365 resume: i2c update write(0x00, 0xaf) error\n");
msleep(3);
for(i = 0; i < ts->point_num; i++){
input_mt_slot(ts->input, i);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
}
input_sync(ts->input);
return 0;
}
static void ct365_report(struct ct36x_data *ts)
{
int i, ret = 0;
int sync = 0, x, y;
int len = sizeof(struct ct365_finger_data) * ts->point_num;
struct ct365_priv *ct365 = ts->priv;
ret = ct36x_read(ts, ct365->buf, len);
if(ret < 0){
dev_warn(ts->dev, "Failed to read finger data\n");
return;
}
ct36x_dbg(ts, "Read fingers data:\n");
ct365->press = 0;
for(i = 0; i < ts->point_num; i++){
ct36x_dbg(ts, "pst[%d]: id: %d, status: %d, area: %d, pressure: %d\n"
"xhi: %d, xlo:%d, yhi: %d, ylo: %d\n",
i, ct365->pts[i].id, ct365->pts[i].status, ct365->pts[i].area, ct365->pts[i].pressure,
ct365->pts[i].xhi, ct365->pts[i].ylo, ct365->pts[i].yhi, ct365->pts[i].ylo);
if((ct365->pts[i].xhi != 0xFF && ct365->pts[i].yhi != 0xFF) &&
(ct365->pts[i].status == 1 || ct365->pts[i].status == 2)){
x = (ct365->pts[i].xhi<<4)|(ct365->pts[i].xlo&0xF);
y = (ct365->pts[i].yhi<<4)|(ct365->pts[i].ylo&0xF);
ct365->x = ts->orientation[0] * x + ts->orientation[1] * y;
ct365->y = ts->orientation[2] * x + ts->orientation[3] * y;
if(ct365->x < 0)
ct365->x = ts->x_max - ct365->x;
if(ct365->y < 0)
ct365->y = ts->y_max - ct365->y;
input_mt_slot(ts->input, ct365->pts[i].id - 1);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 1);
input_report_abs(ts->input, ABS_MT_POSITION_X, x);
input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
input_report_abs(ts->input, ABS_MT_PRESSURE, ct365->pts[i].pressure);
sync = 1;
ct365->press |= 0x01 << (ct365->pts[i].id - 1);
}
}
ct365->release &= ct365->release ^ ct365->press;
for(i = 0; i < ts->point_num; i++){
if ( ct365->release & (0x01<<i) ) {
input_mt_slot(ts->input, i);
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
sync = 1;
}
}
ct365->release = ct365->press;
if(sync)
input_sync(ts->input);
return;
}
struct ct36x_ops ct365_ops = {
.init = ct365_init,
.deinit = ct365_deinit,
.suspend = ct365_suspend,
.resume = ct365_resume,
.report = ct365_report,
};

View File

@@ -22,14 +22,14 @@
#include <mach/board.h>
#include <mach/gpio.h>
#if 1
#if 0
#define ct36x_dbg(ts, format, arg...) \
dev_printk(KERN_INFO , ts->dev , format , ## arg)
#else
#define ct36x_dbg(ts, format, arg...)
#endif
#define CT36X_I2C_RATE (100 * 1000)
#define CT36X_I2C_RATE (200 * 1000)
struct ct36x_data;
struct ct36x_ops{
@@ -96,6 +96,7 @@ static inline int ct36x_update_write(struct ct36x_data *ts, unsigned short addr,
return ret;
}
int ct36x_chip_set_idle(struct ct36x_data *ts);
int ct36x_chip_go_sleep(struct ct36x_data *ts);
int ct36x_chip_get_binchksum(void);
int ct36x_chip_get_fwchksum(struct ct36x_data *ts);
int ct36x_chip_go_bootloader(struct ct36x_data *ts);

View File

@@ -2,13 +2,13 @@
#include "core.c"
#include "ct360.c"
#include "ct365.c"
#include "ct363.c"
int inline ct36x_set_ops(struct ct36x_data *ts, int model)
{
switch(model){
case 360: ts->ops = &ct360_ops; break;
case 365: ts->ops = &ct365_ops; break;
case 363: ts->ops = &ct363_ops; break;
default: return -EINVAL;
};
@@ -40,8 +40,13 @@ module_param(irq, int, 0644);
static int rst = -1;
module_param(rst, int, 0644);
static int orientation[4] = {1, 0, 1, 0};
module_param_array(orientation, int, NULL, 0644);
static int ct36x_check_param(void)
{
int i;
if(en != 1)
return -EINVAL;
if(model < 0)
@@ -52,6 +57,10 @@ static int ct36x_check_param(void)
return -EINVAL;
if(x_max <= 0 || y_max <= 0)
return -EINVAL;
for(i = 0; i < 4; i++){
if(orientation[i] != 0 && orientation[i] != 1 && orientation[i] != -1)
return -EINVAL;
}
return 0;
}
@@ -66,12 +75,15 @@ static struct i2c_board_info __initdata ct36x_info = {
static int ct36x_add_client(void)
{
int i;
struct port_config ct36x_rst, ct36x_irq;
ct36x_pdata.model = model;
ct36x_pdata.x_max = x_max;
ct36x_pdata.y_max = y_max;
for(i = 0; i < 4; i++)
ct36x_pdata.orientation = orientation[i];
ct36x_rst = get_port_config(rst);
ct36x_pdata.rst_io.gpio = ct36x_rst.gpio;
ct36x_pdata.rst_io.active_low = ct36x_rst.io.active_low;
@@ -86,15 +98,15 @@ static int ct36x_add_client(void)
}
#endif
static irqreturn_t ct36x_irq(int irq, void *data)
static irqreturn_t ct36x_irq_handler(int irq, void *data)
{
struct ct36x_data *ts = data;
disable_irq_nosync(ts->irq);
//disable_irq(ts->irq);
if(ts->ops->report)
ts->ops->report(ts);
enable_irq(ts->irq);
//enable_irq(ts->irq);
return IRQ_HANDLED;
}
@@ -204,7 +216,7 @@ static int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id
register_early_suspend(&ts->early_suspend);
#endif
ts->irq = gpio_to_irq(ts->irq_io.gpio);
ret = request_threaded_irq(ts->irq, NULL, ct36x_irq, IRQF_ONESHOT, CT36X_NAME, ts);
ret = request_threaded_irq(ts->irq, NULL, ct36x_irq_handler, IRQF_ONESHOT, CT36X_NAME, ts);
if(ret < 0){
dev_err(ts->dev, "Failed to request threaded irq\n");
goto err_request_threaded_irq;