zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/input/touchscreen/touchscreen.c b/ap/os/linux/linux-3.4.x/drivers/input/touchscreen/touchscreen.c
new file mode 100644
index 0000000..062727b
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/input/touchscreen/touchscreen.c
@@ -0,0 +1,550 @@
+/* drivers/input/touchscreen/touchscreen.c 

+* 

+* TouchScreen driver. 

+* 

+* Copyright (c) 

+* 

+* 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/i2c.h> 

+#include <linux/input.h> 

+#include <linux/delay.h> 

+#include <linux/slab.h> 

+#include <linux/interrupt.h> 

+#include <mach/irqs.h> 

+#include <linux/kernel.h> 

+#include <linux/semaphore.h> 

+#include <linux/mutex.h> 

+#include <linux/module.h> 

+#include <linux/gpio.h> 

+#include <linux/syscalls.h> 

+#include <linux/unistd.h> 

+#include <linux/uaccess.h> 

+#include <linux/fs.h> 

+#include <linux/string.h> 

+#include <linux/timer.h> 

+#include <linux/of.h> 

+#include <linux/of_gpio.h> 

+#include <linux/irq.h>

+#include <mach/gpio_cfg.h>

+#include <linux/input/touchscreen.h> 

+

+static struct mutex i2c_rw_access;

+static u8 s_pmode = 0;

+static struct input_dev *tp_input_dev; 

+static struct touchscreen_operations *ts_operations[MAX_TOUCHSCREEN_DEV_TYPE] = { NULL };

+static struct touchscreen_register *touchscreen_dev_register_tbl[MAX_TOUCHSCREEN_DEV_TYPE]  = { NULL };

+static struct ts_data *s_touchscreen_data = NULL;

+

+enum touchscreen_type touchscreen_detected_type = MAX_TOUCHSCREEN_DEV_TYPE;

+

+void touchscreen_set_operations(enum touchscreen_type id, struct touchscreen_operations *pt_operations)

+{

+    ts_operations[id] = pt_operations;

+}

+

+void touchscreen_register(enum touchscreen_type id, struct touchscreen_register *pt_register)

+{

+    touchscreen_dev_register_tbl[id] = pt_register;

+}

+

+int tp_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen)

+{

+    int ret = 0;

+

+    if (client == NULL)

+    {

+		dev_err(&client->dev, "[IIC][%s]i2c_client==NULL!\n", __func__); 

+        return -1;

+    }

+

+    mutex_lock(&i2c_rw_access);

+	

+    if (readlen > 0)

+    {

+        if (writelen > 0)

+        {

+            struct i2c_msg msgs[] =

+            {

+                {

+                    .addr = client->addr,

+                    .flags = 0,

+                    .len = writelen,

+                    .buf = writebuf,

+                },

+                {

+                    .addr = client->addr,

+                    .flags = I2C_M_RD,

+                    .len = readlen,

+                    .buf = readbuf,

+                },

+            };

+            ret = i2c_transfer(client->adapter, msgs, 2);

+            if (ret < 0)

+            {

+				dev_err(&client->dev, "%s [IIC]: i2c_transfer(write) error, ret=%d!!\n", __func__,ret); 

+            }

+        }

+        else

+        {

+            struct i2c_msg msgs[] =

+            {

+                {

+                    .addr = client->addr,

+                    .flags = I2C_M_RD,

+                    .len = readlen,

+                    .buf = readbuf,

+                },

+            };

+            ret = i2c_transfer(client->adapter, msgs, 1);

+            if (ret < 0)

+            {

+			   dev_err(&client->dev, "%s IIC]: i2c_transfer(read) error, ret=%d!!\n", __func__,ret); 

+            }

+        }

+    }

+

+    mutex_unlock(&i2c_rw_access);

+	

+    return ret;

+}

+

+int tp_i2c_write(struct i2c_client *client, char *writebuf, int writelen)

+{

+    int ret = 0;

+

+    if (client == NULL)

+    {

+		dev_err(&client->dev, "[IIC][%s]i2c_client==NULL!\n", __func__); 

+        return -1;

+    }

+

+    mutex_lock(&i2c_rw_access);

+	

+    if (writelen > 0)

+    {

+        struct i2c_msg msgs[] =

+        {

+            {

+                .addr = client->addr,

+                .flags = 0,

+                .len = writelen,

+                .buf = writebuf,

+            },

+        };

+        ret = i2c_transfer(client->adapter, msgs, 1);

+        if (ret < 0)

+        {

+           dev_err(&client->dev, "%s [IIC]: i2c_transfer(write) error, ret=%d!!.\n", __func__,ret); 

+        }

+    }

+	

+    mutex_unlock(&i2c_rw_access);

+

+    return ret;

+}

+

+int tp_read(struct i2c_client *client, u8 regaddr, u8 len, u8 *regvalue) //len:1 hyn_i2c_read_reg

+{

+    return tp_i2c_read(client, &regaddr, 1, regvalue, len);

+}

+

+int tp_write(struct i2c_client *client, u8 regaddr, u8 regvalue) //len: 2( any value) hyn_i2c_write_reg

+{

+    u8 buf[2] = {0};

+

+    buf[0] = regaddr;

+    buf[1] = regvalue;

+    return tp_i2c_write(client, buf, sizeof(buf));

+}

+

+static int tp_read_touchdata(struct ts_data *data) 

+{ 

+	int ret = -1; 

+

+	if (NULL == ts_operations[touchscreen_detected_type]) {

+		return -1;

+	}

+

+	if (NULL == ts_operations[touchscreen_detected_type]->ts_read_touchdata) {   

+		return -1;

+	}

+	

+	ret = ts_operations[touchscreen_detected_type]->ts_read_touchdata(data);

+

+	if (ret >= 0)

+	{

+		return 0;

+	}

+	return ret; 

+	

+}

+

+static void tp_report_values(struct ts_data *data) 

+{ 

+	struct ts_event *event = data->events; 

+

+	if (data->touch_points > 0) { 

+		input_report_abs(data->input_dev, ABS_X, event[0].x); 

+		input_report_abs(data->input_dev, ABS_Y, event[0].y); 

+		input_report_key(data->input_dev, BTN_TOUCH, 1); 

+

+		input_sync(data->input_dev); 

+	} else if (data->touch_points == 0) { 

+		input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0); 

+		input_report_key(data->input_dev, BTN_TOUCH, 0); /*Up*/

+		input_sync(data->input_dev); 

+	} 

+} 

+

+static irqreturn_t tp_ts_interrupt(int irq, void *dev_id) 

+{ 

+	struct ts_data *touchscreen_data = dev_id; 

+	int ret = 0; 

+       //printk("[TP]tp_ts_interrupt happen \n");

+	ret = tp_read_touchdata(touchscreen_data); 

+	

+	if (ret == 0) 

+		tp_report_values(touchscreen_data); 

+

+	return IRQ_HANDLED; 

+} 

+

+#ifdef CONFIG_SYSFS

+static ssize_t tp_sysfs_show(struct device *dev,

+		struct device_attribute *attr, char *buf);

+static ssize_t tp_sysfs_store(struct device *dev,

+		struct device_attribute *attr, const char *buf, size_t count);

+

+

+DEVICE_ATTR(tp_mode, S_IWUSR | S_IRUGO, tp_sysfs_show, tp_sysfs_store);

+

+static struct attribute * tp_sysfs_attrs[] = {

+	&dev_attr_tp_mode.attr,

+	NULL

+};

+

+static const struct attribute_group tp_sysfs_attr_group = {

+	.attrs = tp_sysfs_attrs,

+};

+

+static int tp_sysfs_create_group(struct ts_data *touchscreen_data)

+{

+	return sysfs_create_group(&touchscreen_data->input_dev->dev.kobj, &tp_sysfs_attr_group);

+}

+

+static void tp_sysfs_remove_group(struct ts_data *touchscreen_data)

+{

+	sysfs_remove_group(&touchscreen_data->client->dev.kobj, &tp_sysfs_attr_group);

+}

+

+static ssize_t tp_sysfs_show(struct device *dev,

+		struct device_attribute *attr, char *buf)

+{

+	u8 val = 0;

+	int ret = 0;

+	

+	ret = tp_read(s_touchscreen_data->client, TP_REG_ID_PMODE, 1, &val);

+	if(ret < 0)

+		val = 0xff;

+

+	return scnprintf(buf, PAGE_SIZE, "%d",val);

+}

+

+static ssize_t tp_sysfs_store(struct device *dev,

+		struct device_attribute *attr, const char *buf, size_t count)

+{

+	u8 pmode_sleep  = 0x03;

+	unsigned long pmode = 0;

+	u8 read_val = 0xff;

+	if(strict_strtoul(buf, 0, &pmode))

+		return -EINVAL;

+	

+	if (pmode) {

+		if(TP_SLEEP_OFF == s_touchscreen_data->pmode)

+			return count;

+		gpio_set_value(PIN_TP_RST, 0); 

+		msleep(20); 

+		gpio_set_value(PIN_TP_RST, 1); 

+		msleep(200); 

+		s_touchscreen_data->pmode = TP_SLEEP_OFF;

+		//tp_write(s_touchscreen_data->client, TP_REG_ID_PMODE, &s_pmode);

+		//printk("tp_sysfs_store sleep out read_val =  %d, pmode = %d ,s_pmode = %d\n",read_val,pmode,s_pmode);

+	} else {

+		if(TP_SLEEP_ON == s_touchscreen_data->pmode)

+			return count;

+		tp_write(s_touchscreen_data->client, TP_REG_ID_PMODE, pmode_sleep);

+		s_touchscreen_data->pmode = TP_SLEEP_ON;

+		//printk("tp_sysfs_store sleep in  read_val =  %d, pmode = %d ,s_pmode = %d\n",read_val,pmode,s_pmode);

+	}

+	

+	return count;

+}

+#else

+static int tp_sysfs_create_group(struct ts_data *touchscreen_data)

+{

+	return 0;

+}

+

+static void tp_sysfs_remove_group(struct ts_data *touchscreen_data)

+{

+	return;

+}

+#endif

+

+static int ts_init_gpio(void)

+{

+       int err;

+	/* ÅäÖô¥ÃþÆÁʹÓõÄirq reset GPIO Òý½Å*/

+	err = gpio_request(PIN_TP_IRQ, "touchscreen_irq");

+	if (err) { 

+		printk( "[TP]request touchscreen irq gpio failed\n"); 

+		return -1;

+	}

+	zx29_gpio_config(PIN_TP_IRQ, TP_IRQ_FUN_SEL);

+	zx29_gpio_set_inttype(PIN_TP_IRQ, IRQ_TYPE_EDGE_FALLING);

+	zx29_gpio_pd_pu_set(PIN_TP_IRQ,  IO_CFG_PULL_DISABLE);

+

+	err = gpio_request(PIN_TP_RST, "touchscreen_reset");

+ 	if (err) { 

+		printk( "[TP]request touchscreen reset gpio failed\n"); 

+		return -1;

+	}

+	zx29_gpio_config(PIN_TP_RST, TP_RST_GPIO_SEL);

+	gpio_direction_output(PIN_TP_RST, GPIO_OUT);

+	

+	gpio_set_value(PIN_TP_RST, 0); 

+	msleep(20); 

+	gpio_set_value(PIN_TP_RST, 1); 

+	msleep(200); 

+

+	return 0;

+}

+

+static int touchscreen_dev_detect(struct i2c_client *client)

+{

+	int ret = 0;

+	u32 dev_index = 0;

+	

+	ret = ts_init_gpio();

+	if(ret < 0)

+	{

+		return -1;

+	}

+

+	for (dev_index =0; dev_index < MAX_TOUCHSCREEN_DEV_TYPE; dev_index++) {

+		if (touchscreen_detected_type !=  MAX_TOUCHSCREEN_DEV_TYPE) {

+			printk(KERN_ERR "[TP]touchscreen_dev_detect:touchscreen_type=%d have been detected!\n",touchscreen_detected_type);	

+			return 0;

+		}

+		

+		if ( NULL == touchscreen_dev_register_tbl[dev_index]) {

+			printk(KERN_ERR "[TP]touchscreen_dev_detect:touchscreen_type=%d have been detected!\n",touchscreen_detected_type);	

+			return -1;

+		}

+		

+		if (touchscreen_dev_register_tbl[dev_index]->ts_id_detect != NULL) {

+			ret = touchscreen_dev_register_tbl[dev_index]->ts_id_detect(client);

+			printk("[TP]touchscreen_dev_detect dev_index = 0x%x, ret = 0x%x\n",dev_index,ret);

+			if (ret != 0) {

+			}

+			else{

+				break;

+			}

+		}	

+	}

+	

+	if (touchscreen_detected_type ==  MAX_TOUCHSCREEN_DEV_TYPE) {

+		printk(KERN_ERR "[TP]touchscreen_dev_detect:do not have the driver for this touchscreen type!\n");

+		return -ENXIO;

+	}

+	return 0;

+}

+

+static int ts_probe(struct i2c_client *client, 

+const struct i2c_device_id *id) 

+{ 

+	struct ts_data *touchscreen_data; 

+	struct input_dev *input_dev; 

+	int err = 0; 

+	int ret = -1;

+	

+	mutex_init(&i2c_rw_access);

+	

+	ret = touchscreen_dev_detect(client);

+	if(ret < 0)

+	{

+		dev_err(&client->dev, "[TP]%s: touchscreen_dev_detect irq failed\n", __func__); 

+		return -1;

+	}

+

+	touchscreen_data = kzalloc(sizeof(struct ts_data), GFP_KERNEL); 

+	s_touchscreen_data = touchscreen_data;

+	

+	if (!touchscreen_data) { 

+		err = -ENOMEM; 

+		goto exit_alloc_data_failed; 

+	} 

+	

+	i2c_set_clientdata(client, touchscreen_data); 

+	touchscreen_data->client = client; 

+	touchscreen_data->x_max = 4095; 

+	touchscreen_data->y_max = 4095; 

+	/* ×¢²á¶ÁÈ¡ÖÐ¶Ï */

+	err = devm_request_threaded_irq(&client->dev, gpio_to_irq(PIN_TP_IRQ), 

+				NULL, tp_ts_interrupt, IRQF_ONESHOT, 

+				client->dev.driver->name, touchscreen_data); 

+	

+	if (err < 0) { 

+		dev_err(&client->dev, "[TP]%s: request irq failed\n", __func__); 

+		goto exit_irq_request_failed; 

+	} 

+	/* ·ÖÅäÒ»¸öʼþÉϱ¨½á¹¹Ìå */

+	input_dev = input_allocate_device(); 

+	if (!input_dev) { 

+		err = -ENOMEM; 

+		dev_err(&client->dev, "[TP]failed to allocate input device\n"); 

+		goto exit_input_dev_alloc_failed; 

+	} 

+

+	touchscreen_data->input_dev = input_dev; 

+	/* ×¢²áÉ豸֧³ÖµÄevent ÀàÐÍ */

+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 

+

+	set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit); 

+	set_bit(ABS_MT_POSITION_X, input_dev->absbit); 

+	set_bit(ABS_MT_POSITION_Y, input_dev->absbit); 

+	set_bit(ABS_MT_PRESSURE, input_dev->absbit); 

+

+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, touchscreen_data->x_max, 0, 0); 

+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, touchscreen_data->y_max, 0, 0); 

+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0); 

+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0); 

+	input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, CFG_MAX_TOUCH_POINTS, 0, 0); 

+	input_set_abs_params(input_dev, ABS_X, 0, touchscreen_data->x_max, 0, 0); 

+	input_set_abs_params(input_dev, ABS_Y, 0, touchscreen_data->y_max, 0, 0); 

+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, PRESS_MAX, 0, 0); 

+	

+	/* EV KEY °´¼üʼþ EV_ABS ¾ø¶Ô×ø±ê£¬Èç´¥ÃþÆÁÉϱ¨µÄ×ø±ê */

+	set_bit(EV_KEY, input_dev->evbit); 

+	set_bit(EV_ABS, input_dev->evbit); 

+       

+	input_dev->name = TOUCHSCREEN_NAME; 

+	/* ×¢²áÕâ¸öinput É豸 */

+	err = input_register_device(input_dev); 

+	if (err) { 

+		dev_err(&client->dev, 

+		"[TP]ts_probe: failed to register input device: %s\n", 

+		dev_name(&client->dev)); 

+		goto exit_input_register_device_failed; 

+	} 

+		

+	tp_sysfs_create_group(touchscreen_data);

+	

+	return 0; 

+

+	exit_input_register_device_failed: 

+	input_free_device(input_dev); 

+

+	exit_input_dev_alloc_failed: 

+	exit_irq_request_failed: 

+	i2c_set_clientdata(client, NULL); 

+	kfree(touchscreen_data); 

+

+	exit_alloc_data_failed: 

+	return err; 

+} 

+

+#ifdef CONFIG_PM 

+static int ts_suspend(struct i2c_client *client, pm_message_t mesg) 

+{ 

+	u8 pmode_sleep	= 0x03;

+	struct ts_data *ts = i2c_get_clientdata(client); 

+	dev_dbg(&ts->client->dev, "[TP]ts_suspend \n"); 

+	disable_irq(PIN_TP_IRQ); 

+	

+	tp_write(s_touchscreen_data->client, TP_REG_ID_PMODE, pmode_sleep);

+	

+	return 0; 

+} 

+

+static int ts_resume(struct i2c_client *client) 

+{ 

+	struct ts_data *ts = i2c_get_clientdata(client); 

+	dev_dbg(&ts->client->dev, "[TP]ts_resume.\n"); 

+	if (gpio_is_valid(PIN_TP_RST)) { 

+		gpio_set_value(PIN_TP_RST, 0); 

+		msleep(20); 

+		gpio_set_value(PIN_TP_RST, 1); 

+		msleep(200); 

+	} 

+	enable_irq(PIN_TP_IRQ); 

+	return 0; 

+} 

+#endif 

+

+static int ts_remove(struct i2c_client *client) 

+{ 

+	struct ts_data *touchscreen_data; 

+	touchscreen_data = i2c_get_clientdata(client); 

+	tp_sysfs_remove_group(touchscreen_data);

+	input_unregister_device(touchscreen_data->input_dev); 

+	kfree(touchscreen_data); 

+	i2c_set_clientdata(client, NULL); 

+	return 0; 

+} 

+

+static const struct i2c_device_id ts_id[] = { 

+	{TOUCHSCREEN_NAME, 0}, 

+	{} 

+}; 

+

+MODULE_DEVICE_TABLE(i2c, ts_id); 

+

+#define ts_match_table NULL 

+

+static struct i2c_driver ts_driver = { 

+	.probe = ts_probe, 

+	.remove = ts_remove, 

+	.id_table = ts_id, 

+	.driver = { 

+		.name = TOUCHSCREEN_NAME, 

+		.owner = THIS_MODULE, 

+		.of_match_table = ts_match_table, 

+	}, 

+#ifdef CONFIG_PM

+	.suspend = ts_suspend, 

+	.resume = ts_resume, 

+#endif

+}; 

+

+static int __init ts_init(void) 

+{ 

+	int ret; 

+	ret = i2c_add_driver(&ts_driver); 

+	if (ret) 

+		pr_err("[TP]Adding touchscreen driver failed (errno = %d)\n", ret); 

+

+	return ret; 

+} 

+

+static void __exit ts_exit(void) 

+{ 

+	i2c_del_driver(&ts_driver); 

+} 

+

+module_init(ts_init); 

+module_exit(ts_exit); 

+

+MODULE_AUTHOR("Dyy"); 

+MODULE_DESCRIPTION("TouchScreen driver"); 

+MODULE_LICENSE("GPL");

+