summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c')
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c817
1 files changed, 817 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c
new file mode 100755
index 00000000..7b79aaf4
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c
@@ -0,0 +1,817 @@
+/* drivers/input/touchscreen/sis_i2c.c
+ *
+ * Copyright (C) 2009 SiS, Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/linkage.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <mach/hardware.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "sitronix_i2c.h"
+#include "irq_gpio.h"
+
+struct sitronix_data *pContext=NULL;
+struct i2c_client *l_client=NULL;
+
+#ifdef TOUCH_KEY
+
+#define MENU_IDX 0
+#define HOME_IDX 1
+#define BACK_IDX 2
+#define SEARCH_IDX 3
+#define NUM_KEYS 4
+
+static int virtual_keys[NUM_KEYS] ={
+ KEY_BACK,
+ KEY_HOME,
+ KEY_MENU,
+ KEY_SEARCH
+};
+#endif
+
+#define I2C_BUS1 1
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sitronix_early_suspend(struct early_suspend *h);
+static void sitronix_late_resume(struct early_suspend *h);
+#endif
+
+static int sitronix_read(struct sitronix_data *sitronix, u8 *rxdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = sitronix->addr;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = rxdata;
+
+ msg[1].addr = sitronix->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = rxdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 2, I2C_BUS1);
+ ret = i2c_transfer(l_client->adapter, msg, 2);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+#ifdef SITRONIX_DEBUG
+static int sitronix_write(struct sitronix_data *sitronix, u8 *txdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = sitronix->addr;
+ msg[0].flags = 0;
+ msg[0].len = length;
+ msg[0].buf = txdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, I2C_BUS1);
+ ret = i2c_transfer(l_client->adapter, msg, 1);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+static int sitronix_get_fw_revision(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[4]={FIRMWARE_REVISION_3,0};
+
+ ret = sitronix_read(sitronix, buffer, 4);
+ if (ret < 0){
+ dbg_err("read fw revision error (%d)\n", ret);
+ return ret;
+ }
+
+ memcpy(sitronix->fw_revision, buffer, 4);
+ printk("Fw Revision (hex): %x%x%x%x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
+
+ return 0;
+}
+
+static int sitronix_get_max_touches(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[1]={MAX_NUM_TOUCHES};
+
+ ret = sitronix_read(sitronix, buffer, 1);
+ if (ret < 0){
+ dbg_err("read max touches error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->max_touches = buffer[0];
+ printk("max touches = %d \n",sitronix->max_touches);
+
+ return 0;
+}
+
+static int sitronix_get_protocol(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[1]={I2C_PROTOCOL};
+
+ ret = sitronix_read(sitronix, buffer, 1);
+ if (ret < 0){
+ dbg_err("read i2c protocol error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->touch_protocol_type = buffer[0] & I2C_PROTOCOL_BMSK;
+ sitronix->sensing_mode = (buffer[0] & (ONE_D_SENSING_CONTROL_BMSK << ONE_D_SENSING_CONTROL_SHFT)) >> ONE_D_SENSING_CONTROL_SHFT;
+ printk("i2c protocol = %d ,sensing mode = %d \n", sitronix->touch_protocol_type, sitronix->sensing_mode);
+
+ return 0;
+}
+
+static int sitronix_get_resolution(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[3]={XY_RESOLUTION_HIGH};
+
+ ret = sitronix_read(sitronix, buffer, 3);
+ if (ret < 0){
+ dbg_err("read resolution error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->resolution_x = ((buffer[0] & (X_RES_H_BMSK << X_RES_H_SHFT)) << 4) | buffer[1];
+ sitronix->resolution_y = ((buffer[0] & Y_RES_H_BMSK) << 8) | buffer[2];
+ printk("Resolution: %d x %d\n", sitronix->resolution_x, sitronix->resolution_y);
+
+ return 0;
+}
+
+static int sitronix_get_chip_id(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[3]={CHIP_ID};
+
+ ret = sitronix_read(sitronix, buffer, 3);
+ if (ret < 0){
+ dbg_err("read Chip ID error (%d)\n", ret);
+ return ret;
+ }
+
+ if(buffer[0] == 0){
+ if(buffer[1] + buffer[2] > 32)
+ sitronix->chip_id = 2;
+ else
+ sitronix->chip_id = 0;
+ }else
+ sitronix->chip_id = buffer[0];
+
+ sitronix->Num_X = buffer[1];
+ sitronix->Num_Y = buffer[2];
+ printk("Chip ID = %d, Num_X = %d, Num_Y = %d\n", sitronix->chip_id, sitronix->Num_X, sitronix->Num_Y);
+
+ return 0;
+}
+
+static int sitronix_get_device_status(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buf[3]={FIRMWARE_VERSION,0};
+
+ ret = sitronix_read(sitronix, buf, 3);
+ if (ret < 0){
+ dbg_err("read resolution error (%d)\n", ret);
+ return ret;
+ }
+
+ printk("Firmware version:%02x, Status Reg:%02x,Ctrl Reg:%02x\n", buf[0], buf[1],buf[2]);
+ return 0;
+
+}
+
+static int sitronix_get_device_info(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+
+ ret = sitronix_get_resolution(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_chip_id(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_fw_revision(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_protocol(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_max_touches(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_device_status(sitronix);
+ if(ret < 0) return ret;
+
+ if((sitronix->fw_revision[0] == 0) && (sitronix->fw_revision[1] == 0)){
+ if(sitronix->touch_protocol_type == SITRONIX_RESERVED_TYPE_0){
+ sitronix->touch_protocol_type = SITRONIX_B_TYPE;
+ printk("i2c protocol (revised) = %d \n", sitronix->touch_protocol_type);
+ }
+ }
+
+ if(sitronix->touch_protocol_type == SITRONIX_A_TYPE)
+ sitronix->pixel_length = PIXEL_DATA_LENGTH_A;
+ else if(sitronix->touch_protocol_type == SITRONIX_B_TYPE){
+ sitronix->pixel_length = PIXEL_DATA_LENGTH_B;
+ sitronix->max_touches = 2;
+ printk("max touches (revised) = %d \n", sitronix->max_touches);
+ }
+
+ return 0;
+}
+#endif
+
+static void sitronix_read_work(struct work_struct *work)
+{
+ struct sitronix_data *sitronix= container_of(work, struct sitronix_data, read_work);
+ int ret = -1;
+ u8 buf[22] = {FINGERS,0};
+ u8 i = 0, fingers = 0, tskey = 0;
+ u16 px = 0, py = 0;
+ u16 x = 0, y = 0;
+
+ ret = sitronix_read(sitronix, buf,sizeof(buf));
+ if(ret <= 0){
+ dbg_err("get raw data failed!\n");
+ goto err_exit;
+ }
+
+ fingers = buf[0]&0x0f;
+ if( fingers ){
+ /* Report co-ordinates to the multi-touch stack */
+ for(i=0; i < fingers; i++){
+ if(sitronix->swap){
+ y = ((buf[i*4+2]<<4)&0x0700)|buf[i*4+3];
+ x = ((buf[i*4+2]<<8)&0x0700)|buf[i*4+4];
+ }else{
+ x = ((buf[i*4+2]<<4)&0x0700)|buf[i*4+3];
+ y = ((buf[i*4+2]<<8)&0x0700)|buf[i*4+4];
+ }
+
+ if(!(buf[i*4+2]&0x80)) continue; /*check valid bit */
+
+
+ if(x > sitronix->xresl ) x = sitronix->xresl ;
+ if(y > sitronix->yresl ) y = sitronix->yresl ;
+
+ px = x;
+ py = y;
+ if(sitronix->xch) px = sitronix->xresl - x;
+ if(sitronix->ych) py = sitronix->yresl - y;
+
+ if (sitronix->lcd_exchg) {
+ int tmp;
+ tmp = px;
+ px = py;
+ py = sitronix->xresl - tmp;
+ }
+
+ input_report_abs(sitronix->input_dev, ABS_MT_POSITION_X, px);
+ input_report_abs(sitronix->input_dev, ABS_MT_POSITION_Y, py);
+ input_report_abs(sitronix->input_dev, ABS_MT_TRACKING_ID, i+1);
+ input_mt_sync(sitronix->input_dev);
+ sitronix->penup = 0;
+ if(sitronix->dbg) printk("F%d,raw data: x=%-4d, y=%-4d; report data: px=%-4d, py=%-4d\n", i, x, y, px, py);
+ }
+ input_sync(sitronix->input_dev);
+
+ }
+ else if(!sitronix->penup){
+ dbg("pen up.\n");
+ sitronix->penup = 1;
+ input_mt_sync(sitronix->input_dev);
+ input_sync(sitronix->input_dev);
+ }
+
+ /* virtual keys */
+ tskey = buf[1];
+ if(tskey){
+ if(!sitronix->tkey_idx){
+ sitronix->tkey_idx = tskey;
+ input_report_key(sitronix->input_dev,virtual_keys[sitronix->tkey_idx>>1] , 1);
+ input_sync(sitronix->input_dev);
+ dbg("virtual key down, idx=%d\n",sitronix->tkey_idx);
+ }
+ }else{
+ if(sitronix->tkey_idx){
+ dbg("virtual key up , idx=%d\n",sitronix->tkey_idx);
+ input_report_key(sitronix->input_dev,virtual_keys[sitronix->tkey_idx>>1] , 0);
+ input_sync(sitronix->input_dev);
+ sitronix->tkey_idx = tskey;
+ }
+ }
+
+err_exit:
+ wmt_enable_gpirq(sitronix->irqgpio);
+ return;
+}
+
+
+static irqreturn_t sitronix_isr_handler(int irq, void *dev)
+{
+ struct sitronix_data *sitronix = dev;
+
+ if (wmt_is_tsint(sitronix->irqgpio))
+ {
+ wmt_clr_int(sitronix->irqgpio);
+ if (wmt_is_tsirq_enable(sitronix->irqgpio))
+ {
+ wmt_disable_gpirq(sitronix->irqgpio);
+ if(!sitronix->earlysus) queue_work(sitronix->workqueue, &sitronix->read_work);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void sitronix_reset(struct sitronix_data *sitronix)
+{
+
+ gpio_set_value(sitronix->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(sitronix->rstgpio, 0);
+ mdelay(5);
+ gpio_set_value(sitronix->rstgpio, 1);
+ mdelay(5);
+
+ return;
+}
+
+static int sitronix_auto_clb(struct sitronix_data *sitronix)
+{
+ return 1;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sitronix_early_suspend(struct early_suspend *handler)
+{
+ struct sitronix_data *sitronix = container_of(handler, struct sitronix_data, early_suspend);
+ sitronix->earlysus = 1;
+ wmt_disable_gpirq(sitronix->irqgpio);
+ return;
+}
+
+static void sitronix_late_resume(struct early_suspend *handler)
+{
+ struct sitronix_data *sitronix = container_of(handler, struct sitronix_data, early_suspend);
+
+ sitronix->earlysus = 0;
+ sitronix_reset(sitronix);
+ msleep(200);
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+
+static int sitronix_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+ sitronix->earlysus = 1;
+ wmt_disable_gpirq(sitronix->irqgpio);
+ return 0;
+}
+
+static int sitronix_resume(struct platform_device *pdev)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ sitronix->earlysus = 0;
+ sitronix_reset(sitronix);
+ msleep(200);
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+ return 0;
+}
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "dbg \n");
+}
+
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sitronix_data *sitronix = pContext;
+
+ sscanf(buf,"%d",&sitronix->dbg);
+
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+static ssize_t cat_clb(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "calibrate --echo 1 >clb \n");
+}
+
+static ssize_t echo_clb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int cal ;
+ struct sitronix_data *sitronix = pContext;
+
+ sscanf(buf, "%d", &cal);
+ if(cal){
+ if(sitronix_auto_clb(sitronix) <= 0) printk("Auto calibrate failed.\n");
+ }
+
+ return count;
+}
+static DEVICE_ATTR(clb, S_IRUGO | S_IWUSR, cat_clb, echo_clb);
+
+static struct attribute *sitronix_attributes[] = {
+ &dev_attr_clb.attr,
+ &dev_attr_dbg.attr,
+ NULL
+};
+
+static const struct attribute_group sitronix_group = {
+ .attrs = sitronix_attributes,
+};
+
+static int sitronix_sysfs_create_group(struct sitronix_data *sitronix, const struct attribute_group *group)
+{
+ int err;
+
+ sitronix->kobj = kobject_create_and_add("wmtts", NULL) ;
+ if(!sitronix->kobj){
+ dbg_err("kobj create failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(sitronix->kobj, group);
+ if (err < 0){
+ kobject_del(sitronix->kobj);
+ dbg_err("Create sysfs group failed!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void sitronix_sysfs_remove_group(struct sitronix_data *sitronix, const struct attribute_group *group)
+{
+ sysfs_remove_group(sitronix->kobj, group);
+ kobject_del(sitronix->kobj);
+ return;
+}
+
+static int sitronix_probe(struct platform_device *pdev)
+{
+ int i;
+ int err = 0;
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ INIT_WORK(&sitronix->read_work, sitronix_read_work);
+ sitronix->workqueue = create_singlethread_workqueue(sitronix->name);
+ if (!sitronix->workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ err = sitronix_sysfs_create_group(sitronix, &sitronix_group);
+ if(err < 0){
+ dbg("create sysfs group failed.\n");
+ goto exit_create_group;
+ }
+
+ sitronix->input_dev = input_allocate_device();
+ if (!sitronix->input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ sitronix->input_dev->name = sitronix->name;
+ sitronix->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, sitronix->input_dev->propbit);
+
+ if (sitronix->lcd_exchg) {
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_X, 0, sitronix->yresl, 0, 0);
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_Y, 0, sitronix->xresl, 0, 0);
+ } else {
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_X, 0, sitronix->xresl, 0, 0);
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_Y, 0, sitronix->yresl, 0, 0);
+ }
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_TRACKING_ID, 0, 20, 0, 0);
+#ifdef TOUCH_KEY
+ for (i = 0; i <NUM_KEYS; i++)
+ set_bit(virtual_keys[i], sitronix->input_dev->keybit);
+
+ sitronix->input_dev->keycode = virtual_keys;
+ sitronix->input_dev->keycodesize = sizeof(unsigned int);
+ sitronix->input_dev->keycodemax = NUM_KEYS;
+#endif
+
+ err = input_register_device(sitronix->input_dev);
+ if (err) {
+ dbg_err("sitronix_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ sitronix->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ sitronix->early_suspend.suspend = sitronix_early_suspend;
+ sitronix->early_suspend.resume = sitronix_late_resume;
+ register_early_suspend(&sitronix->early_suspend);
+#endif
+
+ if(request_irq(sitronix->irq, sitronix_isr_handler, IRQF_SHARED, sitronix->name, sitronix) < 0){
+ dbg_err("Could not allocate irq for ts_sitronix !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+ sitronix_reset(sitronix);
+ msleep(200);
+#ifdef SITRONIX_DEBUG
+ sitronix_get_device_info(sitronix);
+#endif
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&sitronix->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(sitronix->input_dev);
+exit_input_dev_alloc_failed:
+ sitronix_sysfs_remove_group(sitronix, &sitronix_group);
+exit_create_group:
+ cancel_work_sync(&sitronix->read_work);
+ destroy_workqueue(sitronix->workqueue);
+exit_create_singlethread:
+ //kfree(sitronix);
+ return err;
+}
+
+static int sitronix_remove(struct platform_device *pdev)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&sitronix->read_work);
+ flush_workqueue(sitronix->workqueue);
+ destroy_workqueue(sitronix->workqueue);
+
+ free_irq(sitronix->irq, sitronix);
+ wmt_disable_gpirq(sitronix->irqgpio);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&sitronix->early_suspend);
+#endif
+ input_unregister_device(sitronix->input_dev);
+
+ sitronix_sysfs_remove_group(sitronix, &sitronix_group);
+ //kfree(sitronix);
+
+ dbg("remove...\n");
+ return 0;
+}
+
+static void sitronix_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device sitronix_device = {
+ .name = DEV_SITRONIX,
+ .id = 0,
+ .dev = {.release = sitronix_release},
+};
+
+static struct platform_driver sitronix_driver = {
+ .driver = {
+ .name = DEV_SITRONIX,
+ .owner = THIS_MODULE,
+ },
+ .probe = sitronix_probe,
+ .remove = sitronix_remove,
+ .suspend = sitronix_suspend,
+ .resume = sitronix_resume,
+};
+
+static int check_touch_env(struct sitronix_data *sitronix)
+{
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char *p=NULL;
+ int ret;
+
+ // Get u-boot parameter
+ if(wmt_getsyspara("wmt.io.touch", retval, &len)) return -EIO;
+
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0) return -ENODEV;
+
+ p = strchr(retval,':');
+ p++;
+
+ if(strncmp(p,"st1536",6)) return -ENODEV;
+
+ sitronix->name = DEV_SITRONIX;
+ sitronix->addr = SITRONIX_ADDR;
+ p = strchr(p,':');
+ p++;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d",
+ &sitronix->xresl, &sitronix->yresl, &sitronix->irqgpio, &sitronix->rstgpio, &sitronix->swap, &sitronix->xch, &sitronix->ych);
+
+ sitronix->irq = IRQ_GPIO;
+ printk("%s reslx=%d, resly=%d, irqgpio_num=%d, rstgpio_num=%d, XYswap=%d, Xdirch=%d, Ydirch=%d\n", sitronix->name,
+ sitronix->xresl, sitronix->yresl, sitronix->irqgpio, sitronix->rstgpio, sitronix->swap, sitronix->xch, sitronix->ych);
+
+ sitronix->penup = 1;
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ sitronix->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = DEV_SITRONIX,
+ .flags = 0x00,
+ .addr = SITRONIX_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(I2C_BUS1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+
+static int __init sitronix_init(void)
+{
+ int ret = -ENOMEM;
+ struct sitronix_data *sitronix=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ sitronix = kzalloc(sizeof(struct sitronix_data), GFP_KERNEL);
+ if(!sitronix){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = sitronix;
+ ret = check_touch_env(sitronix);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(sitronix->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", sitronix->irqgpio);
+ goto exit_free_mem;
+ }
+
+ ret = gpio_request(sitronix->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", sitronix->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(sitronix->rstgpio, 1);
+
+
+ ret = platform_device_register(&sitronix_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&sitronix_device, sitronix);
+
+ ret = platform_driver_register(&sitronix_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&sitronix_device);
+exit_free_gpio:
+
+ gpio_free(sitronix->rstgpio);
+exit_free_irqgpio:
+ gpio_free(sitronix->irqgpio);
+
+exit_free_mem:
+ kfree(sitronix);
+ pContext = NULL;
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void sitronix_exit(void)
+{
+ struct sitronix_data *sitronix;
+
+ if(!pContext) return;
+
+ sitronix = pContext;
+
+ gpio_free(sitronix->irqgpio);
+ gpio_free(sitronix->rstgpio);
+
+
+ platform_driver_unregister(&sitronix_driver);
+ platform_device_unregister(&sitronix_device);
+ kfree(pContext);
+
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(sitronix_init);
+module_exit(sitronix_exit);
+
+MODULE_DESCRIPTION("Sitronix Multi-Touch Driver");
+MODULE_LICENSE("GPL");
+