830 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			830 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2007-2008 HTC Corporation.
 | |
|  *
 | |
|  * 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/input.h>
 | |
| #include <linux/device.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/jiffies.h>
 | |
| #include <linux/interrupt.h>
 | |
| #include <linux/i2c.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/hrtimer.h>
 | |
| #include <linux/elan_i2c.h>
 | |
| #include <linux/earlysuspend.h>
 | |
| #include <linux/gpio.h>
 | |
| 
 | |
| 
 | |
| static const char EKT8232NAME[]	= "elan-touch";
 | |
| 
 | |
| #define ELAN_TS_FUZZ 		0
 | |
| #define ELAN_TS_FLAT 		0
 | |
| #define IDX_PACKET_SIZE		9
 | |
| 
 | |
| enum {
 | |
| 	STATE_DEEP_SLEEP	= 0,
 | |
| 	STATE_NORMAL		= 1U,
 | |
| 	STATE_MASK		= 0x08,
 | |
| 	cmd_reponse_packet	= 0x52,
 | |
| 	read_cmd_packet		= 0x53,
 | |
| 	write_cmd_packet	= 0x54,
 | |
| 	hello_packet 		= 0x55,
 | |
| 	enable_int		= 0xa6,
 | |
| 	disable_int		= 0x56,
 | |
| 	idx_coordinate_packet 	= 0x5a,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	idx_finger_width = 7,
 | |
| 	idx_finger_state = 8,
 | |
| };
 | |
| 
 | |
| static struct workqueue_struct *elan_wq;
 | |
| 
 | |
| static struct ekt8232_data {
 | |
| 	int intr_gpio;
 | |
| 	int use_irq;
 | |
| 	/* delete when finish migration */
 | |
| 	int fw_ver;
 | |
| 	struct hrtimer timer;
 | |
| 	struct work_struct work;
 | |
| 	struct i2c_client *client;
 | |
| 	struct input_dev *input;
 | |
| 	wait_queue_head_t wait;
 | |
| 	int (*power)(int on);
 | |
| 	struct early_suspend early_suspend;
 | |
| } ekt_data;
 | |
| 
 | |
| #ifdef CONFIG_HAS_EARLYSUSPEND
 | |
| static void elan_ts_early_suspend(struct early_suspend *h);
 | |
| static void elan_ts_late_resume(struct early_suspend *h);
 | |
| #endif
 | |
| 
 | |
| static ssize_t touch_vendor_show(struct device *dev,
 | |
| 		struct device_attribute *attr, char *buf)
 | |
| {
 | |
| 	ssize_t ret = 0;
 | |
| 
 | |
| 	sprintf(buf, "%s_%#x\n", EKT8232NAME, ekt_data.fw_ver);
 | |
| 	ret = strlen(buf) + 1;
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static DEVICE_ATTR(vendor, 0444, touch_vendor_show, NULL);
 | |
| 
 | |
| static struct kobject *android_touch_kobj;
 | |
| 
 | |
| static int touch_sysfs_init(void)
 | |
| {
 | |
| 	int ret ;
 | |
| 
 | |
| 	android_touch_kobj = kobject_create_and_add("android_touch", NULL) ;
 | |
| 	if (android_touch_kobj == NULL) {
 | |
| 		printk(KERN_INFO
 | |
| 		       "touch_sysfs_init: subsystem_register failed\n");
 | |
| 		ret = -ENOMEM;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	ret = sysfs_create_file(android_touch_kobj, &dev_attr_vendor.attr);
 | |
| 	if (ret) {
 | |
| 		printk(KERN_INFO
 | |
| 		       "touch_sysfs_init: sysfs_create_group failed\n");
 | |
| 		goto err4;
 | |
| 	}
 | |
| 
 | |
| 	return 0 ;
 | |
| err4:
 | |
| 	kobject_del(android_touch_kobj);
 | |
| err:
 | |
| 	return ret ;
 | |
| }
 | |
| 
 | |
| static int ekt8232_detect_int_level(void)
 | |
| {
 | |
| 	unsigned v;
 | |
| 	v = gpio_get_value(ekt_data.intr_gpio);
 | |
| 	/* printk("ekt8232_detect_int_level: v = %0x\n", v); */
 | |
| 	return v;
 | |
| }
 | |
| 
 | |
| static int __ekt8232_poll(struct i2c_client *client)
 | |
| {
 | |
| 	int status = 0, retry = 10;
 | |
| 
 | |
| 	do {
 | |
| 		status = ekt8232_detect_int_level();
 | |
| 		dev_dbg(&client->dev, "%s: status = %d\n", __func__, status);
 | |
| 		retry--;
 | |
| 		mdelay(20);
 | |
| 	} while (status == 1 && retry > 0);
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s: poll interrupt status %s\n",
 | |
| 			__func__, status == 1 ? "high" : "low");
 | |
| 	return (status == 0 ? 0 : -ETIMEDOUT);
 | |
| }
 | |
| 
 | |
| static int ekt8232_poll(struct i2c_client *client)
 | |
| {
 | |
| 	return __ekt8232_poll(client);
 | |
| }
 | |
| 
 | |
| static int ekt8232_get_data(struct i2c_client *client, uint8_t *cmd,
 | |
| 			    uint8_t *buf, size_t size, int sleep)
 | |
| {
 | |
| 	int rc;
 | |
| 	unsigned time_out = msecs_to_jiffies(10);
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s: enter.\n", __func__);
 | |
| 
 | |
| 	if (buf == NULL)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	if ((i2c_master_send(client, cmd, 4)) != 4) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: i2c_master_send failed\n", __func__);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	if (sleep == 1) {
 | |
| 		rc = wait_event_timeout(ekt_data.wait,
 | |
| 				i2c_master_recv(client, buf, size) == size &&
 | |
| 				buf[0] == cmd_reponse_packet, time_out);
 | |
| 		if (rc == 0) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: i2c_master_recv failed\n", __func__);
 | |
| 			return -ETIMEDOUT;
 | |
| 		}
 | |
| 	} else {
 | |
| 		rc = ekt8232_poll(client);
 | |
| 		if (rc < 0)
 | |
| 			return -EINVAL;
 | |
| 		else {
 | |
| 			if (i2c_master_recv(client, buf, size) != size ||
 | |
| 			    buf[0] != cmd_reponse_packet)
 | |
| 				return -EINVAL;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int __hello_packet_handler(struct i2c_client *client)
 | |
| {
 | |
| 	int rc;
 | |
| 	uint8_t buf_recv[4] = { 0 };
 | |
| 
 | |
| 	rc = ekt8232_poll(client);
 | |
| 	if (rc < 0) {
 | |
| 		dev_err(&client->dev, "%s: failed!\n", __func__);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	rc = i2c_master_recv(client, buf_recv, 4);
 | |
| 	if (rc != 4) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: get hello packet failed!, rc = %d\n",
 | |
| 			__func__, rc);
 | |
| 		return rc;
 | |
| 	} else {
 | |
| 		int i;
 | |
| 		dev_dbg(&client->dev,
 | |
| 			"dump hello packet: %0x, %0x, %0x, %0x\n",
 | |
| 			buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
 | |
| 
 | |
| 		for (i = 0; i < 4; i++)
 | |
| 			if (buf_recv[i] != hello_packet)
 | |
| 				return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int __fw_packet_handler(struct i2c_client *client)
 | |
| {
 | |
| 	int rc;
 | |
| 	int major, minor;
 | |
| 	uint8_t cmd[] = { read_cmd_packet, 0x00, 0x00, 0x01 };
 | |
| 	uint8_t buf_recv[4] = { 0 };
 | |
| 
 | |
| 	rc = ekt8232_get_data(client, cmd, buf_recv, 4, 0);
 | |
| 	if (rc < 0)
 | |
| 		return rc;
 | |
| 
 | |
| 	major = ((buf_recv[1] & 0x0f) << 4) | ((buf_recv[2] & 0xf0) >> 4);
 | |
| 	minor = ((buf_recv[2] & 0x0f) << 4) | ((buf_recv[3] & 0xf0) >> 4);
 | |
| 
 | |
| 	/* delete after migration */
 | |
| 	ekt_data.fw_ver = major << 8 | minor;
 | |
| 
 | |
| 	printk(KERN_INFO "%s: firmware version: 0x%x\n",
 | |
| 			__func__, ekt_data.fw_ver);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int __set_report_type(struct i2c_client *client)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static inline int ekt8232_parse_xy(uint8_t *data, uint16_t *x, uint16_t *y)
 | |
| {
 | |
| 	*x = (data[0] & 0xf0);
 | |
| 	*x <<= 4;
 | |
| 	*x |= data[1];
 | |
| 
 | |
| 	*y = (data[0] & 0x0f);
 | |
| 	*y <<= 8;
 | |
| 	*y |= data[2];
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*	ekt8232_ts_init -- hand shaking with touch panel
 | |
|  *
 | |
|  *	1. recv hello packet
 | |
|  *	2. check its' firmware version
 | |
|  *	3. set up sensitivity, report rate, ...
 | |
|  */
 | |
| static int ekt8232_ts_init(struct i2c_client *client)
 | |
| {
 | |
| 	int rc;
 | |
| 
 | |
| 	rc = __hello_packet_handler(client);
 | |
| 	if (rc < 0)
 | |
| 		goto hand_shake_failed;
 | |
| 	dev_dbg(&client->dev, "%s: hello packet got.\n", __func__);
 | |
| 
 | |
| 	rc = __fw_packet_handler(client);
 | |
| 	if (rc < 0)
 | |
| 		goto hand_shake_failed;
 | |
| 	dev_dbg(&client->dev, "%s: firmware checking done.\n", __func__);
 | |
| 
 | |
| 	rc = __set_report_type(client);
 | |
| 	if (rc < 0)
 | |
| 		goto hand_shake_failed;
 | |
| 	dev_dbg(&client->dev,
 | |
| 		"%s: channging operating mode done.\n", __func__);
 | |
| 
 | |
| 	if (ekt_data.fw_ver == 0x103) {
 | |
| 		uint8_t cmd[4] = {0x5c, 0x10, 0x00, 0x01};
 | |
| 		if ((i2c_master_send(client, cmd, 4)) != 4) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: set adc failed\n", __func__);
 | |
| 		}
 | |
| 		cmd[0] = 0x54;
 | |
| 		cmd[0] = 0x43;
 | |
| 		cmd[0] = 0x00;
 | |
| 		cmd[0] = 0x01;
 | |
| 		if ((i2c_master_send(client, cmd, 4)) != 4) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: set gain failed\n", __func__);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| hand_shake_failed:
 | |
| 	return rc;
 | |
| }
 | |
| 
 | |
| static int ekt8232_set_power_state(struct i2c_client *client, int state)
 | |
| {
 | |
| 	uint8_t cmd[] = {write_cmd_packet, 0x50, 0x00, 0x01};
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s: enter.\n", __func__);
 | |
| 
 | |
| 	cmd[1] |= (state << 3);
 | |
| 
 | |
| 	dev_dbg(&client->dev,
 | |
| 		"dump cmd: %02x, %02x, %02x, %02x\n",
 | |
| 		cmd[0], cmd[1], cmd[2], cmd[3]);
 | |
| 
 | |
| 	if ((i2c_master_send(client, cmd, sizeof(cmd))) != sizeof(cmd)) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: i2c_master_send failed\n", __func__);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ekt8232_get_power_state(struct i2c_client *client)
 | |
| {
 | |
| 	int rc = 0;
 | |
| 	uint8_t cmd[] = { read_cmd_packet, 0x50, 0x00, 0x01 };
 | |
| 	uint8_t buf[4], power_state;
 | |
| 
 | |
| 	rc = ekt8232_get_data(client, cmd, buf, 4, 0);
 | |
| 	if (rc)
 | |
| 		return rc;
 | |
| 	else {
 | |
| 		power_state = buf[1];
 | |
| 		dev_dbg(&client->dev, "dump repsponse: %0x\n", power_state);
 | |
| 
 | |
| 		power_state = (power_state & STATE_MASK) >> 3;
 | |
| 		dev_dbg(&client->dev, "power state = %s\n",
 | |
| 			power_state == STATE_DEEP_SLEEP ?
 | |
| 			"Deep Sleep" : "Normal/Idle");
 | |
| 		return power_state;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int ekt8232_recv_data(struct i2c_client *client, uint8_t *buf)
 | |
| {
 | |
| 	int rc, bytes_to_recv = IDX_PACKET_SIZE;
 | |
| 	int retry = 5;
 | |
| 
 | |
| 	if (ekt_data.fw_ver == 0x101)
 | |
| 		bytes_to_recv = 8;
 | |
| 
 | |
| 	if (buf == NULL)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	memset(buf, 0, bytes_to_recv);
 | |
| 	rc = i2c_master_recv(client, buf, bytes_to_recv);
 | |
| 
 | |
| 	if (rc != bytes_to_recv) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: i2c_master_recv error?! \n", __func__);
 | |
| 		/* power off level shift */
 | |
| 		ekt_data.power(0);
 | |
| 		msleep(5);
 | |
| 		/* power on level shift */
 | |
| 		ekt_data.power(1);
 | |
| 		/* re-initial */
 | |
| 		if (ekt_data.fw_ver > 0x101) {
 | |
| 			msleep(100);
 | |
| 			rc = ekt8232_ts_init(client);
 | |
| 		} else {
 | |
| 			do {
 | |
| 				rc = ekt8232_set_power_state(client,
 | |
| 							     STATE_NORMAL);
 | |
| 
 | |
| 				rc = ekt8232_get_power_state(client);
 | |
| 				if (rc != STATE_NORMAL)
 | |
| 					dev_err(&client->dev,
 | |
| 						"%s: wake up tp failed! \
 | |
| 						err = %d\n",
 | |
| 						__func__, rc);
 | |
| 				else
 | |
| 					break;
 | |
| 			} while (--retry);
 | |
| 		}
 | |
| 		if (ekt8232_detect_int_level() == 0)
 | |
| 			queue_work(elan_wq, &ekt_data.work);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	return rc;
 | |
| }
 | |
| 
 | |
| static inline void ekt8232_parse_width(uint8_t data, uint8_t *w1, uint8_t *w2)
 | |
| {
 | |
| 	*w1 = *w2 = 0;
 | |
| 	*w1 = (data & 0xf0) >> 4;
 | |
| 	*w2 = data & 0x0f;
 | |
| }
 | |
| 
 | |
| static void ekt8232_report_data(struct i2c_client *client, uint8_t *buf)
 | |
| {
 | |
| 	static unsigned report_time;
 | |
| 	unsigned report_time2;
 | |
| 
 | |
| 	switch (buf[0]) {
 | |
| 	case idx_coordinate_packet: {
 | |
| 		uint16_t x1, x2, y1, y2;
 | |
| 		uint8_t finger_stat, w1 = 1, w2 = 1;
 | |
| 
 | |
| 		ekt8232_parse_xy(&buf[1], &x1, &y1);
 | |
| 		if (ekt_data.fw_ver == 0x101) {
 | |
| 			finger_stat = buf[7] >> 1;
 | |
| 		} else {
 | |
| 			ekt8232_parse_width(buf[idx_finger_width], &w1, &w2);
 | |
| 			finger_stat = buf[idx_finger_state] >> 1;
 | |
| 		}
 | |
| 
 | |
| 		if (finger_stat != 0) {
 | |
| 			input_report_abs(ekt_data.input, ABS_X, x1);
 | |
| 			if (ekt_data.fw_ver == 0x101)
 | |
| 				input_report_abs(ekt_data.input, ABS_Y,
 | |
| 						 (544 - 1) - y1);
 | |
| 			else
 | |
| 				input_report_abs(ekt_data.input, ABS_Y, y1);
 | |
| 			/* only report finger width at y */
 | |
| 			input_report_abs(ekt_data.input, ABS_TOOL_WIDTH, w2);
 | |
| 		}
 | |
| 
 | |
| 		dev_dbg(&client->dev,
 | |
| 			"x1 = %d, y1 = %d, \
 | |
| 			 w1 = %d, w2 = %d, finger status = %d\n",
 | |
| 			x1, y1, w1, w2, finger_stat);
 | |
| 
 | |
| 		input_report_abs(ekt_data.input, ABS_PRESSURE, 100);
 | |
| 		input_report_key(ekt_data.input, BTN_TOUCH, finger_stat);
 | |
| 		input_report_key(ekt_data.input, BTN_2, finger_stat == 2);
 | |
| 
 | |
| 		if (finger_stat > 1) {
 | |
| 			ekt8232_parse_xy(&buf[4], &x2, &y2);
 | |
| 			dev_dbg(&client->dev, "x2 = %d, y2 = %d\n", x2, y2);
 | |
| 			input_report_abs(ekt_data.input, ABS_HAT0X, x2);
 | |
| 			input_report_abs(ekt_data.input, ABS_HAT0Y, y2);
 | |
| 		}
 | |
| 		input_sync(ekt_data.input);
 | |
| 		break;
 | |
| 	}
 | |
| 	default:
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: Unknown packet type: %0x\n", __func__, buf[0]);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	report_time2 = jiffies;
 | |
| 	dev_dbg(&client->dev,
 | |
| 		"report time = %d\n",
 | |
| 		jiffies_to_msecs(report_time2 - report_time));
 | |
| 
 | |
| 	report_time = report_time2;
 | |
| 
 | |
| }
 | |
| 
 | |
| static void ekt8232_work_func(struct work_struct *work)
 | |
| {
 | |
| 	int rc;
 | |
| 	uint8_t buf[IDX_PACKET_SIZE] = { 0 };
 | |
| 	struct i2c_client *client = ekt_data.client;
 | |
| 
 | |
| 	/* dev_dbg(&client->dev, "%s: enter. \n", __func__); */
 | |
| 
 | |
| 	/* this means that we have already serviced it */
 | |
| 	if (ekt8232_detect_int_level())
 | |
| 		return;
 | |
| 
 | |
| 	rc = ekt8232_recv_data(client, buf);
 | |
| 	if (rc < 0)
 | |
| 		return;
 | |
| 
 | |
| 	ekt8232_report_data(client, buf);
 | |
| }
 | |
| 
 | |
| static irqreturn_t ekt8232_ts_interrupt(int irq, void *dev_id)
 | |
| {
 | |
| 	/* the queue_work has spin_lock protection */
 | |
| 	/* disable_irq(irq); */
 | |
| 	queue_work(elan_wq, &ekt_data.work);
 | |
| 
 | |
| 	return IRQ_HANDLED;
 | |
| }
 | |
| 
 | |
| static enum hrtimer_restart ekt8232_ts_timer_func(struct hrtimer *timer)
 | |
| {
 | |
| 	queue_work(elan_wq, &ekt_data.work);
 | |
| 	hrtimer_start(&ekt_data.timer,
 | |
| 		      ktime_set(0, 12500000),
 | |
| 		      HRTIMER_MODE_REL);
 | |
| 
 | |
| 	return HRTIMER_NORESTART;
 | |
| }
 | |
| 
 | |
| static int ekt8232_register_interrupt(struct i2c_client *client)
 | |
| {
 | |
| 	int err = 0;
 | |
| 
 | |
| 	if (client->irq) {
 | |
| 		ekt_data.use_irq = 1;
 | |
| 
 | |
| 		err = request_irq(client->irq, ekt8232_ts_interrupt, 0,
 | |
| 				  EKT8232NAME, &ekt_data);
 | |
| 		if (err < 0) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s(%s): Can't allocate irq %d\n",
 | |
| 				__FILE__, __func__, client->irq);
 | |
| 			ekt_data.use_irq = 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (!ekt_data.use_irq) {
 | |
| 		hrtimer_init(&ekt_data.timer,
 | |
| 			     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 | |
| 		ekt_data.timer.function = ekt8232_ts_timer_func;
 | |
| 		hrtimer_start(&ekt_data.timer, ktime_set(1, 0),
 | |
| 			      HRTIMER_MODE_REL);
 | |
| 	}
 | |
| 
 | |
| 	dev_dbg(&client->dev,
 | |
| 		"elan starts in %s mode.\n",
 | |
| 		ekt_data.use_irq == 1 ? "interrupt":"polling");
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ekt8232_probe(
 | |
| 	struct i2c_client *client, const struct i2c_device_id *id)
 | |
| {
 | |
| 	int err = 0;
 | |
| 	struct elan_i2c_platform_data *pdata;
 | |
| 	int x_max, y_max;
 | |
| 	uint8_t x_resolution_cmd[] = { read_cmd_packet, 0x60, 0x00, 0x01 };
 | |
| 	uint8_t y_resolution_cmd[] = { read_cmd_packet, 0x63, 0x00, 0x01 };
 | |
| 	uint8_t buf_recv[4] = { 0 };
 | |
| 
 | |
| 	elan_wq = create_singlethread_workqueue("elan_wq");
 | |
| 	if (!elan_wq) {
 | |
| 		err = -ENOMEM;
 | |
| 		goto fail;
 | |
| 	}
 | |
| 
 | |
| 	printk(KERN_INFO "ekt8232_probe enter.\n");
 | |
| 	dev_dbg(&client->dev, "ekt8232_probe enter.\n");
 | |
| 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"No supported i2c func what we need?!!\n");
 | |
| 		err = -ENOTSUPP;
 | |
| 		goto fail;
 | |
| 	}
 | |
| 
 | |
| 	ekt_data.client = client;
 | |
| 	strlcpy(client->name, EKT8232NAME, I2C_NAME_SIZE);
 | |
| 	i2c_set_clientdata(client, &ekt_data);
 | |
| 	INIT_WORK(&ekt_data.work, ekt8232_work_func);
 | |
| 	init_waitqueue_head(&ekt_data.wait);
 | |
| 
 | |
| 	ekt_data.input = input_allocate_device();
 | |
| 	if (ekt_data.input == NULL) {
 | |
| 		err = -ENOMEM;
 | |
| 		goto fail;
 | |
| 	}
 | |
| 
 | |
| 	pdata = client->dev.platform_data;
 | |
| 	if (likely(pdata != NULL)) {
 | |
| 		ekt_data.intr_gpio =
 | |
| 			((struct elan_i2c_platform_data *)pdata)->intr_gpio;
 | |
| 		ekt_data.power =
 | |
| 			((struct elan_i2c_platform_data *)pdata)->power;
 | |
| 		ekt_data.power(1);
 | |
| 		dev_info(&client->dev, "touch panel is powered on. \n");
 | |
| 		mdelay(500);	/* elan will be ready after about 500 ms */
 | |
| 	} else {
 | |
| 		dev_err(&client->dev, "without platform data??!!\n");
 | |
| 	}
 | |
| 
 | |
| 	err = ekt8232_ts_init(client);
 | |
| 	if (err < 0) {
 | |
| 		printk(KERN_INFO "looks like it's not Elan, so..i'll quit\n");
 | |
| 		err = -ENODEV;
 | |
| 		goto fail;
 | |
| 	}
 | |
| 
 | |
| 	if (pdata) {
 | |
| 		while (pdata->version > ekt_data.fw_ver) {
 | |
| 			printk(KERN_INFO "ekt8232_probe: old tp detected, "
 | |
| 					"panel version = 0x%x\n",
 | |
| 					ekt_data.fw_ver);
 | |
| 			pdata++;
 | |
| 		}
 | |
| 	}
 | |
| 	printk(KERN_INFO "ekt8232_register_input\n");
 | |
| 
 | |
| 	ekt_data.input->name = EKT8232NAME;
 | |
| 	ekt_data.input->id.bustype = BUS_I2C;
 | |
| 	set_bit(EV_SYN, ekt_data.input->evbit);
 | |
| 	set_bit(EV_KEY, ekt_data.input->evbit);
 | |
| 	set_bit(BTN_TOUCH, ekt_data.input->keybit);
 | |
| 	set_bit(BTN_2, ekt_data.input->keybit);
 | |
| 	set_bit(EV_ABS, ekt_data.input->evbit);
 | |
| 
 | |
| 	if (ekt_data.fw_ver >= 0x104) {
 | |
| 		err = ekt8232_get_data(ekt_data.client, x_resolution_cmd,
 | |
| 				       buf_recv, 4, 0);
 | |
| 		if (err < 0) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: get x resolution failed, err = %d\n",
 | |
| 				__func__, err);
 | |
| 			goto fail;
 | |
| 		}
 | |
| 
 | |
| 		x_max = ((buf_recv[3] & 0xf0) << 4) | ((buf_recv[2] & 0xff));
 | |
| 		printk(KERN_INFO "ekt8232_probe: x_max: %d\n", x_max);
 | |
| 
 | |
| 		err = ekt8232_get_data(ekt_data.client, y_resolution_cmd,
 | |
| 				      buf_recv, 4, 0);
 | |
| 		if (err < 0) {
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: get y resolution failed, err = %d\n",
 | |
| 				__func__, err);
 | |
| 			goto fail;
 | |
| 		}
 | |
| 
 | |
| 		y_max = ((buf_recv[3] & 0xf0) << 4) | ((buf_recv[2] & 0xff));
 | |
| 		printk(KERN_INFO "ekt8232_probe: y_max: %d\n", y_max);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_X,
 | |
| 				     pdata->abs_x_min, x_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_Y,
 | |
| 				     pdata->abs_y_min, y_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_HAT0X,
 | |
| 				     pdata->abs_x_min, x_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_HAT0Y,
 | |
| 				     pdata->abs_y_min, y_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 	} else {
 | |
| 		input_set_abs_params(ekt_data.input, ABS_X,
 | |
| 				     pdata->abs_x_min,  pdata->abs_x_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_Y,
 | |
| 				     pdata->abs_y_min,  pdata->abs_y_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_HAT0X,
 | |
| 				     pdata->abs_x_min,  pdata->abs_x_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_HAT0Y,
 | |
| 				     pdata->abs_y_min,  pdata->abs_y_max,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_PRESSURE, 0, 255,
 | |
| 				     ELAN_TS_FUZZ, ELAN_TS_FLAT);
 | |
| 		input_set_abs_params(ekt_data.input, ABS_TOOL_WIDTH, 1, 8,
 | |
| 				     1, ELAN_TS_FLAT);
 | |
| 	}
 | |
| 
 | |
| 	err = input_register_device(ekt_data.input);
 | |
| 	if (err < 0) {
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: input_register_device failed, err = %d\n",
 | |
| 			__func__, err);
 | |
| 		goto fail;
 | |
| 	}
 | |
| 
 | |
| 	ekt8232_register_interrupt(ekt_data.client);
 | |
| 
 | |
| 	/* checking the interrupt to avoid missing any interrupt */
 | |
| 	if (ekt8232_detect_int_level() == 0)
 | |
| 		ekt8232_ts_interrupt(client->irq, NULL);
 | |
| #ifdef CONFIG_HAS_EARLYSUSPEND
 | |
| 	ekt_data.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
 | |
| 	ekt_data.early_suspend.suspend = elan_ts_early_suspend;
 | |
| 	ekt_data.early_suspend.resume = elan_ts_late_resume;
 | |
| 	register_early_suspend(&ekt_data.early_suspend);
 | |
| #endif
 | |
| 	touch_sysfs_init();
 | |
| 	return 0;
 | |
| 
 | |
| fail:
 | |
| 	input_free_device(ekt_data.input);
 | |
| 	if (elan_wq)
 | |
| 		destroy_workqueue(elan_wq);
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| static int ekt8232_remove(struct i2c_client *client)
 | |
| {
 | |
| 	struct ekt8232_data *tp = i2c_get_clientdata(client);
 | |
| 
 | |
| 	if (elan_wq)
 | |
| 		destroy_workqueue(elan_wq);
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s: enter.\n", __func__);
 | |
| 
 | |
| 	input_unregister_device(tp->input);
 | |
| 
 | |
| 	if (ekt_data.use_irq)
 | |
| 		free_irq(client->irq, tp);
 | |
| 	else
 | |
| 		hrtimer_cancel(&ekt_data.timer);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ekt8232_suspend(struct i2c_client *client, pm_message_t mesg)
 | |
| {
 | |
| 	uint8_t cmd[4];
 | |
| 	int rc = 0;
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s: enter. irq = %d\n", __func__, client->irq);
 | |
| 
 | |
| 	cancel_work_sync(&ekt_data.work);
 | |
| 
 | |
| 	rc = ekt8232_set_power_state(client, STATE_DEEP_SLEEP);
 | |
| /*
 | |
| 	rc = ekt8232_get_power_state(client);
 | |
| 	if (rc < 0 || rc != STATE_DEEP_SLEEP)
 | |
| 		dev_err(&client->dev,
 | |
| 			"%s: put tp into sleep failed, err = %d!\n",
 | |
| 			__func__, rc);
 | |
| */
 | |
| 	/* disable tp interrupt */
 | |
| 	if (ekt_data.fw_ver > 0x101) {
 | |
| 		memset(cmd, disable_int, 4);
 | |
| 		if ((i2c_master_send(client, cmd, sizeof(cmd))) != sizeof(cmd))
 | |
| 			dev_err(&client->dev,
 | |
| 				"%s: tp disable interrupt failed\n", __func__);
 | |
| 	}
 | |
| 
 | |
| 	/* power off level shift */
 | |
| 	ekt_data.power(0);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ekt8232_resume(struct i2c_client *client)
 | |
| {
 | |
| 	int rc = 0, retry = 5;
 | |
| 
 | |
| 	dev_dbg(&client->dev,
 | |
| 		"%s: enter. irq = %d\n", __func__, client->irq);
 | |
| 
 | |
| 	disable_irq(client->irq);
 | |
| 
 | |
| 	/* power on level shift */
 | |
| 	ekt_data.power(1);
 | |
| 
 | |
| 	/* re-initial */
 | |
| 	if (ekt_data.fw_ver > 0x101) {
 | |
| 		msleep(500);
 | |
| 		rc = ekt8232_ts_init(client);
 | |
| 	} else {
 | |
| 		do {
 | |
| 			rc = ekt8232_set_power_state(client, STATE_NORMAL);
 | |
| 			rc = ekt8232_get_power_state(client);
 | |
| 			if (rc != STATE_NORMAL)
 | |
| 				dev_err(&client->dev,
 | |
| 					"%s: wake up tp failed! err = %d\n",
 | |
| 					__func__, rc);
 | |
| 			else
 | |
| 				break;
 | |
| 		} while (--retry);
 | |
| 	}
 | |
| 
 | |
| 	enable_irq(client->irq);
 | |
| 
 | |
| 	if (ekt8232_detect_int_level() == 0)
 | |
| 		ekt8232_ts_interrupt(client->irq, NULL);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef CONFIG_HAS_EARLYSUSPEND
 | |
| static void elan_ts_early_suspend(struct early_suspend *h)
 | |
| {
 | |
| 	struct i2c_client *client = ekt_data.client;
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s enter.\n", __func__);
 | |
| 	ekt8232_suspend(client, PMSG_SUSPEND);
 | |
| }
 | |
| 
 | |
| static void elan_ts_late_resume(struct early_suspend *h)
 | |
| {
 | |
| 	struct i2c_client *client = ekt_data.client;
 | |
| 
 | |
| 	dev_dbg(&client->dev, "%s enter.\n", __func__);
 | |
| 	ekt8232_resume(client);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* -------------------------------------------------------------------- */
 | |
| static const struct i2c_device_id ekt8232_ts_id[] = {
 | |
| 	{ ELAN_8232_I2C_NAME, 0 },
 | |
| 	{ }
 | |
| };
 | |
| 
 | |
| static struct i2c_driver ekt8232_driver = {
 | |
| 	.probe		= ekt8232_probe,
 | |
| 	.remove		= ekt8232_remove,
 | |
| #ifndef CONFIG_HAS_EARLYSUSPEND
 | |
| 	.suspend	= ekt8232_suspend,
 | |
| 	.resume		= ekt8232_resume,
 | |
| #endif
 | |
| 	.id_table	= ekt8232_ts_id,
 | |
| 	.driver		= {
 | |
| 		.name = ELAN_8232_I2C_NAME,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static int __init ekt8232_init(void)
 | |
| {
 | |
| 	return i2c_add_driver(&ekt8232_driver);
 | |
| }
 | |
| 
 | |
| static void __exit ekt8232_exit(void)
 | |
| {
 | |
| 	i2c_del_driver(&ekt8232_driver);
 | |
| }
 | |
| 
 | |
| module_init(ekt8232_init);
 | |
| module_exit(ekt8232_exit);
 | |
| 
 | |
| MODULE_AUTHOR("Shan-Fu Chiou <sfchiou@gmail.com>, "
 | |
| 	      "Jay Tu <jay_tu@htc.com>");
 | |
| MODULE_DESCRIPTION("ELAN ekt8232 driver");
 | |
| MODULE_LICENSE("GPL");
 |