Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 473f8cd8 authored by Mohan Pallaka's avatar Mohan Pallaka Committed by Sudhakar Manapati
Browse files

input: ft5x06_ts: Parse board specific parameters from pdata



To support all models supported by focaltech push necessary
parameters to platform data.

This patch is propagated from msm-3.4 kernel
(commit: 0dd986a8877f10650720bce8fefcaf9e0ff59dfe
input: ft5x06_ts: Parse board specific parameters from pdata)

Also fix the below checkpatch warnings on 3.18 Kernel.
WARNING: Possible unnecessary 'out of memory' message
+       if (!data) {
+               dev_err(&client->dev, "Not enough memory\n");

WARNING: Possible unnecessary 'out of memory' message
+       if (!data->ts_info) {
+               dev_err(&client->dev, "Not enough memory\n");

Change-Id: I00b0e8ba7cfc8d8fbd48aa910bd3d0010283ed00
Signed-off-by: default avatarMohan Pallaka <mpallaka@codeaurora.org>
Signed-off-by: default avatarSudhakar Manapati <smanap@codeaurora.org>
parent 88dd4c27
Loading
Loading
Loading
Loading
+39 −13
Original line number Diff line number Diff line
@@ -22,7 +22,11 @@ Required properties:
 - focaltech,reset-gpio	: reset gpio to control the reset of chip.
 - focaltech,display-coords : display coordinates in pixels. It is a four
				tuple consisting of min x, min y, max x and
				max y values.
				max y values
 - focaltech,name	: name of the controller
 - focaltech,group-id	: group id of this device
 - focaltech,hard-reset-delay-ms : hard reset delay in ms
 - focaltech,soft-reset-delay-ms : soft reset delay in ms

Optional properties:

@@ -32,22 +36,44 @@ Optional properties:
 - focaltech,i2c-pull-up : to specify pull up is required.
 - focaltech,no-force-update : to specify force update is allowed.
 - focaltech,button-map : button map of key codes. The number
				of key codes depend on panel.

				of key codes depend on panel
 - focaltech,fw-name	: specify the firmware file name
 - focaltech,fw-delay-aa-ms : specify the "aa" delay in ms for firmware upgrade
 - focaltech,fw-delay-55-ms : specify the "55" delay in ms for firmware upgrade
 - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
 - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
 - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
 - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
 - focaltech,fw-auto-cal	: specify whether calibration is needed after firmware upgrade
Example:
	i2c@f9924000 {
		ft5x06_ts@38 {
	i2c@f9923000{
		focaltech@38{
			compatible = "focaltech,5x06";
			reg = <0x38>;
			interrupt-parent = <&msmgpio>;
			interrupts = <61 0x2>;
			vdd-supply = <&pm8941_l22>;
			vcc_i2c-supply = <&pm8941_s3>;
			focaltech,reset-gpio = <&msmgpio 60 0x00>;
			focaltech,irq-gpio = <&msmgpio 61 0x00>;
			focaltech,panel-coords = <0 0 480 800>;
			interrupts = <1 0x2>;
			vdd-supply = <&pm8110_l19>;
			vcc_i2c-supply = <&pm8110_l14>;
			focaltech,name = "ft6x06";
			focaltech,family-id = <0x06>;
			focaltech,reset-gpio = <&msmgpio 0 0x00>;
			focaltech,irq-gpio = <&msmgpio 1 0x00>;
			focaltech,display-coords = <0 0 480 800>;
			focaltech,button-map= <158 102 139 217>;
			focaltech,family-id = <0x0a>;
			focaltech,panel-coords = <0 0 480 800>;
			focaltech,button-map= <139 102 158>;
			focaltech,no-force-update;
			focaltech,i2c-pull-up;
			focaltech,group-id = <1>;
			focaltech,hard-reset-delay = <20>;
			focaltech,soft-reset-delay = <150>;
			focaltech,num-max-touches = <2>;
			focaltech,fw-name = "ft_8610_qrd_fw.bin";
			focaltech,fw-delay-aa-ms = <100>;
			focaltech,fw-delay-55-ms = <30>;
			focaltech,fw-upgrade-id1 = <0x79>;
			focaltech,fw-upgrade-id2 = <0x08>;
			focaltech,fw-delay-readid-ms = <10>;
			focaltech,fw-delay-era-flsh-ms = <2000>;
			focaltech,fw-auto-cal;
		};
	};
+206 −207
Original line number Diff line number Diff line
@@ -41,22 +41,23 @@
#define FT_SUSPEND_LEVEL 1
#endif

#define CFG_MAX_TOUCH_POINTS	5
#define FT_DRIVER_VERSION	0x01

#define FT_STARTUP_DLY		150
#define FT_RESET_DLY		20
#define FT_META_REGS		3
#define FT_ONE_TCH_LEN		6
#define FT_TCH_LEN(x)		(FT_META_REGS + FT_ONE_TCH_LEN * x)

#define FT_PRESS		0x7F
#define FT_MAX_ID		0x0F
#define FT_TOUCH_STEP		6
#define FT_TOUCH_X_H_POS	3
#define FT_TOUCH_X_L_POS	4
#define FT_TOUCH_Y_H_POS	5
#define FT_TOUCH_Y_L_POS	6
#define FT_TD_STATUS		2
#define FT_TOUCH_EVENT_POS	3
#define FT_TOUCH_ID_POS		5

#define POINT_READ_BUF	(3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
#define FT_TOUCH_DOWN		0
#define FT_TOUCH_CONTACT	2

/* register address*/
#define FT_REG_DEV_MODE		0x00
@@ -104,55 +105,6 @@
#define FT_UPGRADE_AA		0xAA
#define FT_UPGRADE_55		0x55

/* upgrade config of FT5606 */
#define FT5606_UPGRADE_AA_DELAY		50
#define FT5606_UPGRADE_55_DELAY		10
#define FT5606_UPGRADE_ID_1		0x79
#define FT5606_UPGRADE_ID_2		0x06
#define FT5606_UPGRADE_READID_DELAY	100
#define FT5606_UPGRADE_EARSE_DELAY	2000

/* upgrade config of FT5316 */
#define FT5316_UPGRADE_AA_DELAY		50
#define FT5316_UPGRADE_55_DELAY		30
#define FT5316_UPGRADE_ID_1		0x79
#define FT5316_UPGRADE_ID_2		0x07
#define FT5316_UPGRADE_READID_DELAY	1
#define FT5316_UPGRADE_EARSE_DELAY	1500

/* upgrade config of FT5x06(x=2,3,4) */
#define FT5X06_UPGRADE_AA_DELAY		50
#define FT5X06_UPGRADE_55_DELAY		30
#define FT5X06_UPGRADE_ID_1		0x79
#define FT5X06_UPGRADE_ID_2		0x03
#define FT5X06_UPGRADE_READID_DELAY	1
#define FT5X06_UPGRADE_EARSE_DELAY	2000

/* upgrade config of FT6208 */
#define FT6208_UPGRADE_AA_DELAY		60
#define FT6208_UPGRADE_55_DELAY		10
#define FT6208_UPGRADE_ID_1		0x79
#define FT6208_UPGRADE_ID_2		0x05
#define FT6208_UPGRADE_READID_DELAY	10
#define FT6208_UPGRADE_EARSE_DELAY	2000

/*upgrade config of FT6x06*/
#define FT6X06_UPGRADE_AA_DELAY		100
#define FT6X06_UPGRADE_55_DELAY		30
#define FT6X06_UPGRADE_ID_1		0x79
#define FT6X06_UPGRADE_ID_2		0x08
#define FT6X06_UPGRADE_READID_DELAY	10
#define FT6X06_UPGRADE_EARSE_DELAY	2000

#define FT_UPGRADE_INFO(x, y)	do { \
		x->delay_55 = y##_UPGRADE_55_DELAY; \
		x->delay_aa = y##_UPGRADE_AA_DELAY; \
		x->upgrade_id_1 = y##_UPGRADE_ID_1; \
		x->upgrade_id_2 = y##_UPGRADE_ID_2; \
		x->delay_readid = y##_UPGRADE_READID_DELAY; \
		x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
		} while (0)

#define FT_FW_MIN_SIZE		8
#define FT_FW_MAX_SIZE		32768
#define FT_FW_FILE_VER(x)	((x)->data[(x)->size - 2])
@@ -180,39 +132,26 @@
#define FT_REG_CAL		0x00
#define FT_CAL_MASK		0x70

#define FT_INFO_MAX_LEN		200
#define FT_INFO_MAX_LEN		512

#define FT_STORE_TS_INFO(buf, id, fw_ver) \
#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_name, fw_ver) \
			snprintf(buf, FT_INFO_MAX_LEN, \
				"controller\t= focaltech\n" \
				"model\t\t= 0x%x\n" \
				"fw_ver\t\t= 0x%x\n", id, fw_ver)
				"name\t\t= %s\n" \
				"max_touches\t= %d\n" \
				"drv_ver\t\t= 0x%x\n" \
				"group_id\t= 0x%x\n" \
				"fw_name\t\t= %s\n" \
				"fw_ver\t\t= 0x%x\n", id, name, \
				max_tch, FT_DRIVER_VERSION, group_id, \
				fw_name, fw_ver)

#define FT_DEBUG_DIR_NAME	"ts_debug"

struct ts_event {
	u16 x[CFG_MAX_TOUCH_POINTS];	/* x coordinate */
	u16 y[CFG_MAX_TOUCH_POINTS];	/* y coordinate */
	/* touch event: 0 -- down; 1-- contact; 2 -- contact */
	u8 touch_event[CFG_MAX_TOUCH_POINTS];
	u8 finger_id[CFG_MAX_TOUCH_POINTS];	/* touch ID */
	u16 pressure;
	u8 touch_point;
};

struct upgrade_info {
	u16 delay_aa;		/* delay of write FT_UPGRADE_AA */
	u16 delay_55;		/* delay of write FT_UPGRADE_55 */
	u8 upgrade_id_1;	/* upgrade id 1 */
	u8 upgrade_id_2;	/* upgrade id 2 */
	u16 delay_readid;	/* delay of read id */
	u16 delay_earse_flash;	/* delay of earse flash */
};

struct ft5x06_ts_data {
	struct i2c_client *client;
	struct input_dev *input_dev;
	struct ts_event event;
	const struct ft5x06_ts_platform_data *pdata;
	struct regulator *vdd;
	struct regulator *vcc_i2c;
@@ -223,6 +162,8 @@ struct ft5x06_ts_data {
	u16 addr;
	bool suspended;
	char *ts_info;
	u8 *tch_data;
	u32 tch_data_len;
#if defined(CONFIG_FB)
	struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -305,89 +246,65 @@ static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
	return ft5x06_i2c_read(client, &addr, 1, val, 1);
}

static void ft5x06_report_value(struct ft5x06_ts_data *data)
static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
{
	struct ts_event *event = &data->event;
	int i;
	int fingerdown = 0;

	for (i = 0; i < event->touch_point; i++) {
		if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
			event->pressure = FT_PRESS;
			fingerdown++;
		} else {
			event->pressure = 0;
	struct ft5x06_ts_data *data = dev_id;
	struct input_dev *ip_dev;
	int rc, i;
	u32 id, x, y, pressure, status, num_touches;
	u8 reg = 0x00, *buf;
	bool update_input = false;

	if (!data) {
		pr_err("%s: Invalid data\n", __func__);
		return IRQ_HANDLED;
	}

		input_mt_slot(data->input_dev, event->finger_id[i]);
		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
					!!event->pressure);
	ip_dev = data->input_dev;
	buf = data->tch_data;

		if (event->pressure == FT_PRESS) {
			input_report_abs(data->input_dev, ABS_MT_POSITION_X,
					 event->x[i]);
			input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
					 event->y[i]);
			input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
					 event->pressure);
		}
	}

	input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
	input_sync(data->input_dev);
	rc = ft5x06_i2c_read(data->client, &reg, 1,
			buf, data->tch_data_len);
	if (rc < 0) {
		dev_err(&data->client->dev, "%s: read data fail\n", __func__);
		return IRQ_HANDLED;
	}

static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
{
	struct ts_event *event = &data->event;
	int num_points;
	int ret, i;
	u8 buf[POINT_READ_BUF] = { 0 };
	u8 pointid = FT_MAX_ID;

	ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
	if (ret < 0) {
		dev_err(&data->client->dev, "%s read touchdata failed.\n",
			__func__);
		return ret;
	}
	memset(event, 0, sizeof(struct ts_event));
	for (i = 0; i < data->pdata->num_max_touches; i++) {
		id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
		if (id >= FT_MAX_ID)
			break;

	event->touch_point = 0;
	num_points = buf[2] & FT_STATUS_NUM_TP_MASK;
		update_input = true;

	for (i = 0; i < num_points; i++) {
		pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
		if (pointid >= FT_MAX_ID)
			break;
		x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
			(buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
		y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
			(buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);

		event->touch_point++;
		status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;

		event->x[i] =
		    (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
		    8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
		event->y[i] =
		    (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
		    8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
		event->touch_event[i] =
		    buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
		event->finger_id[i] =
		    (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
	}
		num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;

	ft5x06_report_value(data);
		/* invalid combination */
		if (!num_touches && !status && !id)
			break;

	return 0;
		input_mt_slot(ip_dev, id);
		if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
			pressure = FT_PRESS;
			input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
			input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
			input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
			input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure);
		} else
			input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
	}

static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
{
	struct ft5x06_ts_data *data = dev_id;
	int rc;

	rc = ft5x06_handle_touchdata(data);
	if (rc)
		pr_err("%s: handling touchdata failed\n", __func__);
	if (update_input) {
		input_mt_report_pointer_emulation(ip_dev, false);
		input_sync(ip_dev);
	}

	return IRQ_HANDLED;
}
@@ -520,7 +437,7 @@ static int ft5x06_ts_suspend(struct device *dev)
	disable_irq(data->client->irq);

	/* release all touches */
	for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
	for (i = 0; i < data->pdata->num_max_touches; i++) {
		input_mt_slot(data->input_dev, i);
		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
	}
@@ -554,7 +471,7 @@ static int ft5x06_ts_suspend(struct device *dev)
pwr_off_fail:
	if (gpio_is_valid(data->pdata->reset_gpio)) {
		gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
		msleep(FT_RESET_DLY);
		msleep(data->pdata->hard_rst_dly);
		gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
	}
	enable_irq(data->client->irq);
@@ -567,7 +484,7 @@ static int ft5x06_ts_resume(struct device *dev)
	int err;

	if (!data->suspended) {
		dev_info(dev, "Already in awake state\n");
		dev_dbg(dev, "Already in awake state\n");
		return 0;
	}

@@ -587,11 +504,11 @@ static int ft5x06_ts_resume(struct device *dev)

	if (gpio_is_valid(data->pdata->reset_gpio)) {
		gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
		msleep(FT_RESET_DLY);
		msleep(data->pdata->hard_rst_dly);
		gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
	}

	msleep(FT_STARTUP_DLY);
	msleep(data->pdata->soft_rst_dly);

	enable_irq(data->client->irq);

@@ -650,16 +567,17 @@ static const struct dev_pm_ops ft5x06_ts_pm_ops = {

static int ft5x06_auto_cal(struct i2c_client *client)
{
	struct ft5x06_ts_data *data = i2c_get_clientdata(client);
	u8 temp = 0, i;

	/* set to factory mode */
	msleep(2 * FT_STARTUP_DLY);
	msleep(2 * data->pdata->soft_rst_dly);
	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
	msleep(FT_STARTUP_DLY);
	msleep(data->pdata->soft_rst_dly);

	/* start calibration */
	ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
	msleep(2 * FT_STARTUP_DLY);
	msleep(2 * data->pdata->soft_rst_dly);
	for (i = 0; i < FT_CAL_RETRY; i++) {
		ft5x0x_read_reg(client, FT_REG_CAL, &temp);
		/* return to normal mode, calibration finish */
@@ -668,36 +586,17 @@ static int ft5x06_auto_cal(struct i2c_client *client)
	}

	/*calibration OK */
	msleep(2 * FT_STARTUP_DLY);
	msleep(2 * data->pdata->soft_rst_dly);
	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
	msleep(FT_STARTUP_DLY);
	msleep(data->pdata->soft_rst_dly);

	/* store calibration data */
	ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
	msleep(2 * FT_STARTUP_DLY);
	msleep(2 * data->pdata->soft_rst_dly);

	/* set to normal mode */
	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
	msleep(2 * FT_STARTUP_DLY);

	return 0;
}

static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
{
	switch (family_id) {
	case FT5306I_ID:
		FT_UPGRADE_INFO(info, FT5X06);
		break;
	case FT5316_ID:
		FT_UPGRADE_INFO(info, FT5316);
		break;
	case FT6X06_ID:
		FT_UPGRADE_INFO(info, FT6X06);
		break;
	default:
		return -EINVAL;
	}
	msleep(2 * data->pdata->soft_rst_dly);

	return 0;
}
@@ -706,7 +605,7 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
			const u8 *data, u32 data_len)
{
	struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
	struct upgrade_info info;
	struct fw_upgrade_info info = ts_data->pdata->info;
	u8 reset_reg;
	u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
	u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
@@ -714,12 +613,6 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
	u32 pkt_num, pkt_len;
	u8 fw_ecc;

	rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
	if (rc < 0) {
		dev_err(&client->dev, "Cannot get upgrade information!\n");
		return -EINVAL;
	}

	for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
		/* reset - write 0xaa and 0x55 to reset register */
		if (ts_data->family_id == FT6X06_ID)
@@ -766,7 +659,7 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
	/* erase app and panel paramenter area */
	w_buf[0] = FT_ERASE_APP_REG;
	ft5x06_i2c_write(client, w_buf, 1);
	msleep(info.delay_earse_flash);
	msleep(info.delay_erase_flash);

	w_buf[0] = FT_ERASE_PANEL_REG;
	ft5x06_i2c_write(client, w_buf, 1);
@@ -841,7 +734,7 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
	/* reset */
	w_buf[0] = FT_REG_RESET_FW;
	ft5x06_i2c_write(client, w_buf, 1);
	msleep(FT_STARTUP_DLY);
	msleep(ts_data->pdata->soft_rst_dly);

	dev_info(&client->dev, "Firmware upgrade successful\n");

@@ -889,14 +782,16 @@ static int ft5x06_fw_upgrade(struct device *dev, bool force)
		rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
		if (rc < 0)
			dev_err(dev, "update failed (%d)\n", rc);
		else
		else if (data->pdata->info.auto_cal)
			ft5x06_auto_cal(data->client);
	} else {
		dev_err(dev, "FW format error\n");
		rc = -EIO;
	}

	FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
	FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
			data->pdata->num_max_touches, data->pdata->group_id,
			data->pdata->fw_name, FT_FW_FILE_VER(fw));
rel_fw:
	release_firmware(fw);
	return rc;
@@ -1180,6 +1075,13 @@ static int ft5x06_parse_dt(struct device *dev,
	u32 temp_val, num_buttons;
	u32 button_map[MAX_BUTTONS];

	pdata->name = "focaltech";
	rc = of_property_read_string(np, "focaltech,name", &pdata->name);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read name\n");
		return rc;
	}

	rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
	if (rc && (rc != -EINVAL))
		return rc;
@@ -1204,6 +1106,86 @@ static int ft5x06_parse_dt(struct device *dev,
	if (pdata->irq_gpio < 0)
		return pdata->irq_gpio;

	pdata->fw_name = "ft_fw.bin";
	rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw name\n");
		return rc;
	}

	rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
	if (!rc)
		pdata->group_id = temp_val;
	else
		return rc;

	rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
							&temp_val);
	if (!rc)
		pdata->hard_rst_dly = temp_val;
	else
		return rc;

	rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
							&temp_val);
	if (!rc)
		pdata->soft_rst_dly = temp_val;
	else
		return rc;

	rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
	if (!rc)
		pdata->num_max_touches = temp_val;
	else
		return rc;

	rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw delay aa\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.delay_aa =  temp_val;

	rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw delay 55\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.delay_55 =  temp_val;

	rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw upgrade id1\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.upgrade_id_1 =  temp_val;

	rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw upgrade id2\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.upgrade_id_2 =  temp_val;

	rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
							&temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw delay read id\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.delay_readid =  temp_val;

	rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
							&temp_val);
	if (rc && (rc != -EINVAL)) {
		dev_err(dev, "Unable to read fw delay erase flash\n");
		return rc;
	} else if (rc != -EINVAL)
		pdata->info.delay_erase_flash =  temp_val;

	pdata->info.auto_cal = of_property_read_bool(np,
					"focaltech,fw-auto-cal");

	rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
	if (!rc)
		pdata->family_id = temp_val;
@@ -1244,7 +1226,7 @@ static int ft5x06_ts_probe(struct i2c_client *client,
	struct dentry *temp;
	u8 reg_value;
	u8 reg_addr;
	int err;
	int err, len;

	if (client->dev.of_node) {
		pdata = devm_kzalloc(&client->dev,
@@ -1253,8 +1235,10 @@ static int ft5x06_ts_probe(struct i2c_client *client,
			return -ENOMEM;

		err = ft5x06_parse_dt(&client->dev, pdata);
		if (err)
		if (err) {
			dev_err(&client->dev, "DT parsing failed\n");
			return err;
		}
	} else
		pdata = client->dev.platform_data;

@@ -1268,15 +1252,31 @@ static int ft5x06_ts_probe(struct i2c_client *client,
		return -ENODEV;
	}

	data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
	data = devm_kzalloc(&client->dev,
			sizeof(struct ft5x06_ts_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	if (pdata->fw_name) {
		len = strlen(pdata->fw_name);
		if (len > FT_FW_NAME_MAX_LEN - 1) {
			dev_err(&client->dev, "Invalid firmware name\n");
			return -EINVAL;
		}

		strlcpy(data->fw_name, pdata->fw_name, len + 1);
	}

	data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
	data->tch_data = devm_kzalloc(&client->dev,
				data->tch_data_len, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	input_dev = input_allocate_device();
	if (!input_dev) {
		err = -ENOMEM;
		dev_err(&client->dev, "failed to allocate input device\n");
		goto free_mem;
		return -ENOMEM;
	}

	data->input_dev = input_dev;
@@ -1295,12 +1295,12 @@ static int ft5x06_ts_probe(struct i2c_client *client,
	__set_bit(BTN_TOUCH, input_dev->keybit);
	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);

	input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
	input_mt_init_slots(input_dev, pdata->num_max_touches);
	input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
			     pdata->x_max, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
			     pdata->y_max, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);

	err = input_register_device(input_dev);
	if (err) {
@@ -1363,12 +1363,12 @@ static int ft5x06_ts_probe(struct i2c_client *client,
				"set_direction for reset gpio failed\n");
			goto free_reset_gpio;
		}
		msleep(FT_RESET_DLY);
		msleep(data->pdata->hard_rst_dly);
		gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
	}

	/* make sure CTP already finish startup process */
	msleep(FT_STARTUP_DLY);
	msleep(data->pdata->soft_rst_dly);

	/* check the controller id */
	reg_addr = FT_REG_ID;
@@ -1452,7 +1452,8 @@ static int ft5x06_ts_probe(struct i2c_client *client,
		goto free_debug_dir;
	}

	data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
	data->ts_info = devm_kzalloc(&client->dev,
				FT_INFO_MAX_LEN, GFP_KERNEL);
	if (!data->ts_info)
		goto free_debug_dir;

@@ -1478,7 +1479,9 @@ static int ft5x06_ts_probe(struct i2c_client *client,

	dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);

	FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
	FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
			data->pdata->num_max_touches, data->pdata->group_id,
			data->pdata->fw_name, reg_value);

#if defined(CONFIG_FB)
	data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1529,8 +1532,6 @@ unreg_inputdev:
	input_dev = NULL;
free_inputdev:
	input_free_device(input_dev);
free_mem:
	kfree(data);
	return err;
}

@@ -1568,8 +1569,6 @@ static int ft5x06_ts_remove(struct i2c_client *client)
		ft5x06_power_init(data, false);

	input_unregister_device(data->input_dev);
	kfree(data->ts_info);
	kfree(data);

	return 0;
}
+17 −0
Original line number Diff line number Diff line
@@ -23,7 +23,20 @@
#define FT5X36_ID		0x14
#define FT6X06_ID		0x06

struct fw_upgrade_info {
	bool auto_cal;
	u16 delay_aa;
	u16 delay_55;
	u8 upgrade_id_1;
	u8 upgrade_id_2;
	u16 delay_readid;
	u16 delay_erase_flash;
};

struct ft5x06_ts_platform_data {
	struct fw_upgrade_info info;
	const char *name;
	const char *fw_name;
	u32 irqflags;
	u32 irq_gpio;
	u32 irq_gpio_flags;
@@ -38,6 +51,10 @@ struct ft5x06_ts_platform_data {
	u32 panel_miny;
	u32 panel_maxx;
	u32 panel_maxy;
	u32 group_id;
	u32 hard_rst_dly;
	u32 soft_rst_dly;
	u32 num_max_touches;
	bool no_force_update;
	bool i2c_pull_up;
	int (*power_init)(bool);