#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
// 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;
--- /dev/null
+#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,
+};
+++ /dev/null
-#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,
-};
#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{
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);
#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;
};
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)
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;
}
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;
}
#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;
}
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;