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.18 kernel
'commit 473f8cd84f93 ("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: Mohan Pallaka <mpallaka@codeaurora.org>
Signed-off-by: Sudhakar Manapati <smanap@codeaurora.org>
This commit is contained in:
Mohan Pallaka 2013-08-13 16:11:47 +05:30 committed by Abinaya P
parent cb040c2f61
commit 72436be454
3 changed files with 270 additions and 228 deletions

View file

@ -22,7 +22,11 @@ Required properties:
- focaltech,reset-gpio : reset gpio to control the reset of chip. - focaltech,reset-gpio : reset gpio to control the reset of chip.
- focaltech,display-coords : display coordinates in pixels. It is a four - focaltech,display-coords : display coordinates in pixels. It is a four
tuple consisting of min x, min y, max x and 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: Optional properties:
@ -32,22 +36,44 @@ Optional properties:
- focaltech,i2c-pull-up : to specify pull up is required. - focaltech,i2c-pull-up : to specify pull up is required.
- focaltech,no-force-update : to specify force update is allowed. - focaltech,no-force-update : to specify force update is allowed.
- focaltech,button-map : button map of key codes. The number - 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: Example:
i2c@f9924000 { i2c@f9923000{
ft5x06_ts@38 { focaltech@38{
compatible = "focaltech,5x06"; compatible = "focaltech,5x06";
reg = <0x38>; reg = <0x38>;
interrupt-parent = <&msmgpio>; interrupt-parent = <&msmgpio>;
interrupts = <61 0x2>; interrupts = <1 0x2>;
vdd-supply = <&pm8941_l22>; vdd-supply = <&pm8110_l19>;
vcc_i2c-supply = <&pm8941_s3>; vcc_i2c-supply = <&pm8110_l14>;
focaltech,reset-gpio = <&msmgpio 60 0x00>; focaltech,name = "ft6x06";
focaltech,irq-gpio = <&msmgpio 61 0x00>; focaltech,family-id = <0x06>;
focaltech,panel-coords = <0 0 480 800>; focaltech,reset-gpio = <&msmgpio 0 0x00>;
focaltech,irq-gpio = <&msmgpio 1 0x00>;
focaltech,display-coords = <0 0 480 800>; focaltech,display-coords = <0 0 480 800>;
focaltech,button-map= <158 102 139 217>; focaltech,panel-coords = <0 0 480 800>;
focaltech,family-id = <0x0a>; 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;
}; };
}; };

View file

@ -41,22 +41,23 @@
#define FT_SUSPEND_LEVEL 1 #define FT_SUSPEND_LEVEL 1
#endif #endif
#define CFG_MAX_TOUCH_POINTS 5 #define FT_DRIVER_VERSION 0x01
#define FT_STARTUP_DLY 150 #define FT_META_REGS 3
#define FT_RESET_DLY 20 #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_PRESS 0x7F
#define FT_MAX_ID 0x0F #define FT_MAX_ID 0x0F
#define FT_TOUCH_STEP 6
#define FT_TOUCH_X_H_POS 3 #define FT_TOUCH_X_H_POS 3
#define FT_TOUCH_X_L_POS 4 #define FT_TOUCH_X_L_POS 4
#define FT_TOUCH_Y_H_POS 5 #define FT_TOUCH_Y_H_POS 5
#define FT_TOUCH_Y_L_POS 6 #define FT_TOUCH_Y_L_POS 6
#define FT_TD_STATUS 2
#define FT_TOUCH_EVENT_POS 3 #define FT_TOUCH_EVENT_POS 3
#define FT_TOUCH_ID_POS 5 #define FT_TOUCH_ID_POS 5
#define FT_TOUCH_DOWN 0
#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS) #define FT_TOUCH_CONTACT 2
/* register address*/ /* register address*/
#define FT_REG_DEV_MODE 0x00 #define FT_REG_DEV_MODE 0x00
@ -104,55 +105,6 @@
#define FT_UPGRADE_AA 0xAA #define FT_UPGRADE_AA 0xAA
#define FT_UPGRADE_55 0x55 #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_MIN_SIZE 8
#define FT_FW_MAX_SIZE 32768 #define FT_FW_MAX_SIZE 32768
#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2]) #define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
@ -180,39 +132,26 @@
#define FT_REG_CAL 0x00 #define FT_REG_CAL 0x00
#define FT_CAL_MASK 0x70 #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, \ snprintf(buf, FT_INFO_MAX_LEN, \
"controller\t= focaltech\n" \ "controller\t= focaltech\n" \
"model\t\t= 0x%x\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" #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 ft5x06_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input_dev; struct input_dev *input_dev;
struct ts_event event;
const struct ft5x06_ts_platform_data *pdata; const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd; struct regulator *vdd;
struct regulator *vcc_i2c; struct regulator *vcc_i2c;
@ -223,6 +162,8 @@ struct ft5x06_ts_data {
u16 addr; u16 addr;
bool suspended; bool suspended;
char *ts_info; char *ts_info;
u8 *tch_data;
u32 tch_data_len;
#if defined(CONFIG_FB) #if defined(CONFIG_FB)
struct notifier_block fb_notif; struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND) #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); return ft5x06_i2c_read(client, &addr, 1, val, 1);
} }
static void ft5x06_report_value(struct ft5x06_ts_data *data)
{
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;
}
input_mt_slot(data->input_dev, event->finger_id[i]);
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
!!event->pressure);
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);
}
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));
event->touch_point = 0;
num_points = buf[2] & FT_STATUS_NUM_TP_MASK;
for (i = 0; i < num_points; i++) {
pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
if (pointid >= FT_MAX_ID)
break;
event->touch_point++;
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;
}
ft5x06_report_value(data);
return 0;
}
static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id) static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
{ {
struct ft5x06_ts_data *data = dev_id; struct ft5x06_ts_data *data = dev_id;
int rc; struct input_dev *ip_dev;
int rc, i;
u32 id, x, y, pressure, status, num_touches;
u8 reg = 0x00, *buf;
bool update_input = false;
rc = ft5x06_handle_touchdata(data); if (!data) {
if (rc) pr_err("%s: Invalid data\n", __func__);
pr_err("%s: handling touchdata failed\n", __func__); return IRQ_HANDLED;
}
ip_dev = data->input_dev;
buf = data->tch_data;
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;
}
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;
update_input = true;
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]);
status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
/* invalid combination */
if (!num_touches && !status && !id)
break;
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);
}
if (update_input) {
input_mt_report_pointer_emulation(ip_dev, false);
input_sync(ip_dev);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -520,7 +437,7 @@ static int ft5x06_ts_suspend(struct device *dev)
disable_irq(data->client->irq); disable_irq(data->client->irq);
/* release all touches */ /* 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_slot(data->input_dev, i);
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); 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: pwr_off_fail:
if (gpio_is_valid(data->pdata->reset_gpio)) { if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0); 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); gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
} }
enable_irq(data->client->irq); enable_irq(data->client->irq);
@ -567,7 +484,7 @@ static int ft5x06_ts_resume(struct device *dev)
int err; int err;
if (!data->suspended) { if (!data->suspended) {
dev_info(dev, "Already in awake state\n"); dev_dbg(dev, "Already in awake state\n");
return 0; return 0;
} }
@ -587,11 +504,11 @@ static int ft5x06_ts_resume(struct device *dev)
if (gpio_is_valid(data->pdata->reset_gpio)) { if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0); 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); gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
} }
msleep(FT_STARTUP_DLY); msleep(data->pdata->soft_rst_dly);
enable_irq(data->client->irq); 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) static int ft5x06_auto_cal(struct i2c_client *client)
{ {
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
u8 temp = 0, i; u8 temp = 0, i;
/* set to factory mode */ /* 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); ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
msleep(FT_STARTUP_DLY); msleep(data->pdata->soft_rst_dly);
/* start calibration */ /* start calibration */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START); 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++) { for (i = 0; i < FT_CAL_RETRY; i++) {
ft5x0x_read_reg(client, FT_REG_CAL, &temp); ft5x0x_read_reg(client, FT_REG_CAL, &temp);
/* return to normal mode, calibration finish */ /* return to normal mode, calibration finish */
@ -667,37 +585,18 @@ static int ft5x06_auto_cal(struct i2c_client *client)
break; break;
} }
/* calibration OK */ /*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); ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
msleep(FT_STARTUP_DLY); msleep(data->pdata->soft_rst_dly);
/* store calibration data */ /* store calibration data */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE); 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 */ /* set to normal mode */
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE); ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
msleep(2 * FT_STARTUP_DLY); msleep(2 * data->pdata->soft_rst_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;
}
return 0; return 0;
} }
@ -706,7 +605,7 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
const u8 *data, u32 data_len) const u8 *data, u32 data_len)
{ {
struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client); 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 reset_reg;
u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; 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]; 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; u32 pkt_num, pkt_len;
u8 fw_ecc; 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++) { for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
/* reset - write 0xaa and 0x55 to reset register */ /* reset - write 0xaa and 0x55 to reset register */
if (ts_data->family_id == FT6X06_ID) 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 */ /* erase app and panel paramenter area */
w_buf[0] = FT_ERASE_APP_REG; w_buf[0] = FT_ERASE_APP_REG;
ft5x06_i2c_write(client, w_buf, 1); ft5x06_i2c_write(client, w_buf, 1);
msleep(info.delay_earse_flash); msleep(info.delay_erase_flash);
w_buf[0] = FT_ERASE_PANEL_REG; w_buf[0] = FT_ERASE_PANEL_REG;
ft5x06_i2c_write(client, w_buf, 1); ft5x06_i2c_write(client, w_buf, 1);
@ -841,7 +734,7 @@ static int ft5x06_fw_upgrade_start(struct i2c_client *client,
/* reset */ /* reset */
w_buf[0] = FT_REG_RESET_FW; w_buf[0] = FT_REG_RESET_FW;
ft5x06_i2c_write(client, w_buf, 1); 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"); 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); rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
if (rc < 0) if (rc < 0)
dev_err(dev, "update failed (%d)\n", rc); dev_err(dev, "update failed (%d)\n", rc);
else else if (data->pdata->info.auto_cal)
ft5x06_auto_cal(data->client); ft5x06_auto_cal(data->client);
} else { } else {
dev_err(dev, "FW format error\n"); dev_err(dev, "FW format error\n");
rc = -EIO; 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: rel_fw:
release_firmware(fw); release_firmware(fw);
return rc; return rc;
@ -1180,6 +1075,13 @@ static int ft5x06_parse_dt(struct device *dev,
u32 temp_val, num_buttons; u32 temp_val, num_buttons;
u32 button_map[MAX_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); rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
if (rc && (rc != -EINVAL)) if (rc && (rc != -EINVAL))
return rc; return rc;
@ -1204,6 +1106,86 @@ static int ft5x06_parse_dt(struct device *dev,
if (pdata->irq_gpio < 0) if (pdata->irq_gpio < 0)
return pdata->irq_gpio; 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); rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
if (!rc) if (!rc)
pdata->family_id = temp_val; pdata->family_id = temp_val;
@ -1244,7 +1226,7 @@ static int ft5x06_ts_probe(struct i2c_client *client,
struct dentry *temp; struct dentry *temp;
u8 reg_value; u8 reg_value;
u8 reg_addr; u8 reg_addr;
int err; int err, len;
if (client->dev.of_node) { if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev, pdata = devm_kzalloc(&client->dev,
@ -1253,8 +1235,10 @@ static int ft5x06_ts_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
err = ft5x06_parse_dt(&client->dev, pdata); err = ft5x06_parse_dt(&client->dev, pdata);
if (err) if (err) {
dev_err(&client->dev, "DT parsing failed\n");
return err; return err;
}
} else } else
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
@ -1268,15 +1252,31 @@ static int ft5x06_ts_probe(struct i2c_client *client,
return -ENODEV; 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) if (!data)
return -ENOMEM; return -ENOMEM;
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev) {
err = -ENOMEM;
dev_err(&client->dev, "failed to allocate input device\n"); dev_err(&client->dev, "failed to allocate input device\n");
goto free_mem; return -ENOMEM;
} }
data->input_dev = input_dev; 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(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit); __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, input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0); pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0); 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); err = input_register_device(input_dev);
if (err) { if (err) {
@ -1363,12 +1363,12 @@ static int ft5x06_ts_probe(struct i2c_client *client,
"set_direction for reset gpio failed\n"); "set_direction for reset gpio failed\n");
goto free_reset_gpio; goto free_reset_gpio;
} }
msleep(FT_RESET_DLY); msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1); gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
} }
/* make sure CTP already finish startup process */ /* make sure CTP already finish startup process */
msleep(FT_STARTUP_DLY); msleep(data->pdata->soft_rst_dly);
/* check the controller id */ /* check the controller id */
reg_addr = FT_REG_ID; reg_addr = FT_REG_ID;
@ -1452,7 +1452,8 @@ static int ft5x06_ts_probe(struct i2c_client *client,
goto free_debug_dir; 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) if (!data->ts_info)
goto free_debug_dir; 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); 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) #if defined(CONFIG_FB)
data->fb_notif.notifier_call = fb_notifier_callback; data->fb_notif.notifier_call = fb_notifier_callback;
@ -1529,8 +1532,6 @@ unreg_inputdev:
input_dev = NULL; input_dev = NULL;
free_inputdev: free_inputdev:
input_free_device(input_dev); input_free_device(input_dev);
free_mem:
kfree(data);
return err; return err;
} }
@ -1568,8 +1569,6 @@ static int ft5x06_ts_remove(struct i2c_client *client)
ft5x06_power_init(data, false); ft5x06_power_init(data, false);
input_unregister_device(data->input_dev); input_unregister_device(data->input_dev);
kfree(data->ts_info);
kfree(data);
return 0; return 0;
} }

View file

@ -23,7 +23,20 @@
#define FT5X36_ID 0x14 #define FT5X36_ID 0x14
#define FT6X06_ID 0x06 #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 ft5x06_ts_platform_data {
struct fw_upgrade_info info;
const char *name;
const char *fw_name;
u32 irqflags; u32 irqflags;
u32 irq_gpio; u32 irq_gpio;
u32 irq_gpio_flags; u32 irq_gpio_flags;
@ -38,6 +51,10 @@ struct ft5x06_ts_platform_data {
u32 panel_miny; u32 panel_miny;
u32 panel_maxx; u32 panel_maxx;
u32 panel_maxy; u32 panel_maxy;
u32 group_id;
u32 hard_rst_dly;
u32 soft_rst_dly;
u32 num_max_touches;
bool no_force_update; bool no_force_update;
bool i2c_pull_up; bool i2c_pull_up;
int (*power_init)(bool); int (*power_init)(bool);