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, ®addr, 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");
+