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");
 |