input: ft5x06_ts: add proximity feature support
Focaltech's CTP FT6436 is able to behave like a proximity sensor. Enable the driver support this new feature. Also cleared the chekpatch warning on 3.18 kernel. Change-Id: I7a6ec3a387536c512637b0bd8dab95e7cceca212 Signed-off-by: Mao Li <maol@codeaurora.org> Signed-off-by: Sudhakar Manapati <smanap@codeaurora.org> Signed-off-by: Abinaya P <abinayap@codeaurora.org>
This commit is contained in:
parent
49aaf48f47
commit
fd296540ae
4 changed files with 266 additions and 7 deletions
|
@ -65,6 +65,11 @@ Optional properties:
|
||||||
- focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade
|
- focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade
|
||||||
- focaltech,fw-vkey-support : specify if virtual keys are supported through firmware
|
- focaltech,fw-vkey-support : specify if virtual keys are supported through firmware
|
||||||
- focaltech,ignore-id-check : specify ignore family-id check
|
- focaltech,ignore-id-check : specify ignore family-id check
|
||||||
|
- focaltech,panel-coords : panel coordinates for the chip in pixels.
|
||||||
|
It is a four tuple consisting of min x,
|
||||||
|
min y, max x and max y values
|
||||||
|
- focaltech,fw-name : specify the firmware file name
|
||||||
|
- focaltech,psensor-support : specify whether support the proximity sensor
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
i2c@f9923000{
|
i2c@f9923000{
|
||||||
|
@ -100,5 +105,6 @@ Example:
|
||||||
focaltech,fw-delay-readid-ms = <10>;
|
focaltech,fw-delay-readid-ms = <10>;
|
||||||
focaltech,fw-delay-era-flsh-ms = <2000>;
|
focaltech,fw-delay-era-flsh-ms = <2000>;
|
||||||
focaltech,fw-auto-cal;
|
focaltech,fw-auto-cal;
|
||||||
|
focaltech,psensor-support;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1110,6 +1110,15 @@ config TOUCHSCREEN_COLIBRI_VF50
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called colibri_vf50_ts.
|
module will be called colibri_vf50_ts.
|
||||||
|
|
||||||
|
config TOUCHSCREEN_FT5X06_PSENSOR
|
||||||
|
tristate "FocalTech proximity feature support"
|
||||||
|
depends on TOUCHSCREEN_FT5X06 && SENSORS
|
||||||
|
help
|
||||||
|
Say Y here if you want to support ft5x06's proximity
|
||||||
|
feature.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
config TOUCHSCREEN_MSTAR21XX
|
config TOUCHSCREEN_MSTAR21XX
|
||||||
tristate "Mstar touchscreens"
|
tristate "Mstar touchscreens"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/sensors.h>
|
||||||
#include <linux/input/ft5x06_ts.h>
|
#include <linux/input/ft5x06_ts.h>
|
||||||
|
|
||||||
#if defined(CONFIG_FB)
|
#if defined(CONFIG_FB)
|
||||||
|
@ -73,7 +74,20 @@
|
||||||
#define FT_REG_FW_MIN_VER 0xB2
|
#define FT_REG_FW_MIN_VER 0xB2
|
||||||
#define FT_REG_FW_SUB_MIN_VER 0xB3
|
#define FT_REG_FW_SUB_MIN_VER 0xB3
|
||||||
|
|
||||||
/* power register bits */
|
/* psensor register address*/
|
||||||
|
#define FT_REG_PSENSOR_ENABLE 0xB0
|
||||||
|
#define FT_REG_PSENSOR_STATUS 0x01
|
||||||
|
|
||||||
|
/* psensor register bits*/
|
||||||
|
#define FT_PSENSOR_ENABLE_MASK 0x01
|
||||||
|
#define FT_PSENSOR_STATUS_NEAR 0xC0
|
||||||
|
#define FT_PSENSOR_STATUS_FAR 0xE0
|
||||||
|
#define FT_PSENSOR_FAR_TO_NEAR 0
|
||||||
|
#define FT_PSENSOR_NEAR_TO_FAR 1
|
||||||
|
#define FT_PSENSOR_ORIGINAL_STATE_FAR 1
|
||||||
|
#define FT_PSENSOR_WAKEUP_TIMEOUT 100
|
||||||
|
|
||||||
|
/* power register bits*/
|
||||||
#define FT_PMODE_ACTIVE 0x00
|
#define FT_PMODE_ACTIVE 0x00
|
||||||
#define FT_PMODE_MONITOR 0x01
|
#define FT_PMODE_MONITOR 0x01
|
||||||
#define FT_PMODE_STANDBY 0x02
|
#define FT_PMODE_STANDBY 0x02
|
||||||
|
@ -207,6 +221,7 @@ struct ft5x06_ts_data {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct input_dev *input_dev;
|
struct input_dev *input_dev;
|
||||||
const struct ft5x06_ts_platform_data *pdata;
|
const struct ft5x06_ts_platform_data *pdata;
|
||||||
|
struct ft5x06_psensor_platform_data *psensor_pdata;
|
||||||
struct regulator *vdd;
|
struct regulator *vdd;
|
||||||
struct regulator *vcc_i2c;
|
struct regulator *vcc_i2c;
|
||||||
char fw_name[FT_FW_NAME_MAX_LEN];
|
char fw_name[FT_FW_NAME_MAX_LEN];
|
||||||
|
@ -231,6 +246,29 @@ struct ft5x06_ts_data {
|
||||||
struct pinctrl_state *pinctrl_state_release;
|
struct pinctrl_state *pinctrl_state_release;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct sensors_classdev __maybe_unused sensors_proximity_cdev = {
|
||||||
|
.name = "ft5x06-proximity",
|
||||||
|
.vendor = "FocalTech",
|
||||||
|
.version = 1,
|
||||||
|
.handle = SENSORS_PROXIMITY_HANDLE,
|
||||||
|
.type = SENSOR_TYPE_PROXIMITY,
|
||||||
|
.max_range = "5.0",
|
||||||
|
.resolution = "5.0",
|
||||||
|
.sensor_power = "0.1",
|
||||||
|
.min_delay = 0,
|
||||||
|
.fifo_reserved_event_count = 0,
|
||||||
|
.fifo_max_event_count = 0,
|
||||||
|
.enabled = 0,
|
||||||
|
.delay_msec = 200,
|
||||||
|
.sensors_enable = NULL,
|
||||||
|
.sensors_poll_delay = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool ft5x06_psensor_support_enabled(void)
|
||||||
|
{
|
||||||
|
return config_enabled(CONFIG_TOUCHSCREEN_FT5X06_PSENSOR);
|
||||||
|
}
|
||||||
|
|
||||||
static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
|
static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
|
||||||
int writelen, char *readbuf, int readlen)
|
int writelen, char *readbuf, int readlen)
|
||||||
{
|
{
|
||||||
|
@ -306,6 +344,84 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_TOUCHSCREEN_FT5X06_PSENSOR
|
||||||
|
static void ft5x06_psensor_enable(struct ft5x06_ts_data *data, int enable)
|
||||||
|
{
|
||||||
|
u8 state;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (data->client == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ft5x0x_read_reg(data->client, FT_REG_PSENSOR_ENABLE, &state);
|
||||||
|
if (enable)
|
||||||
|
state |= FT_PSENSOR_ENABLE_MASK;
|
||||||
|
else
|
||||||
|
state &= ~FT_PSENSOR_ENABLE_MASK;
|
||||||
|
|
||||||
|
ret = ft5x0x_write_reg(data->client, FT_REG_PSENSOR_ENABLE, state);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"write psensor switch command failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ft5x06_psensor_enable_set(struct sensors_classdev *sensors_cdev,
|
||||||
|
unsigned int enable)
|
||||||
|
{
|
||||||
|
struct ft5x06_psensor_platform_data *psensor_pdata =
|
||||||
|
container_of(sensors_cdev,
|
||||||
|
struct ft5x06_psensor_platform_data, ps_cdev);
|
||||||
|
struct ft5x06_ts_data *data = psensor_pdata->data;
|
||||||
|
struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev;
|
||||||
|
|
||||||
|
mutex_lock(&input_dev->mutex);
|
||||||
|
ft5x06_psensor_enable(data, enable);
|
||||||
|
psensor_pdata->tp_psensor_data = FT_PSENSOR_ORIGINAL_STATE_FAR;
|
||||||
|
if (enable)
|
||||||
|
psensor_pdata->tp_psensor_opened = 1;
|
||||||
|
else
|
||||||
|
psensor_pdata->tp_psensor_opened = 0;
|
||||||
|
mutex_unlock(&input_dev->mutex);
|
||||||
|
return enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ft5x06_read_tp_psensor_data(struct ft5x06_ts_data *data)
|
||||||
|
{
|
||||||
|
u8 psensor_status;
|
||||||
|
char tmp;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ft5x0x_read_reg(data->client,
|
||||||
|
FT_REG_PSENSOR_STATUS, &psensor_status);
|
||||||
|
|
||||||
|
tmp = data->psensor_pdata->tp_psensor_data;
|
||||||
|
if (psensor_status == FT_PSENSOR_STATUS_NEAR)
|
||||||
|
data->psensor_pdata->tp_psensor_data =
|
||||||
|
FT_PSENSOR_FAR_TO_NEAR;
|
||||||
|
else if (psensor_status == FT_PSENSOR_STATUS_FAR)
|
||||||
|
data->psensor_pdata->tp_psensor_data =
|
||||||
|
FT_PSENSOR_NEAR_TO_FAR;
|
||||||
|
|
||||||
|
if (tmp != data->psensor_pdata->tp_psensor_data) {
|
||||||
|
dev_info(&data->client->dev,
|
||||||
|
"%s sensor data changed\n", __func__);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int ft5x06_psensor_enable_set(struct sensors_classdev *sensors_cdev,
|
||||||
|
unsigned int enable)
|
||||||
|
{
|
||||||
|
return enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ft5x06_read_tp_psensor_data(struct ft5x06_ts_data *data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ft5x06_update_fw_vendor_id(struct ft5x06_ts_data *data)
|
static void ft5x06_update_fw_vendor_id(struct ft5x06_ts_data *data)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = data->client;
|
struct i2c_client *client = data->client;
|
||||||
|
@ -349,7 +465,7 @@ static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
|
||||||
struct input_dev *ip_dev;
|
struct input_dev *ip_dev;
|
||||||
int rc, i;
|
int rc, i;
|
||||||
u32 id, x, y, status, num_touches;
|
u32 id, x, y, status, num_touches;
|
||||||
u8 reg = 0x00, *buf;
|
u8 reg, *buf;
|
||||||
bool update_input = false;
|
bool update_input = false;
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
@ -360,8 +476,31 @@ static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
|
||||||
ip_dev = data->input_dev;
|
ip_dev = data->input_dev;
|
||||||
buf = data->tch_data;
|
buf = data->tch_data;
|
||||||
|
|
||||||
rc = ft5x06_i2c_read(data->client, ®, 1,
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support &&
|
||||||
buf, data->tch_data_len);
|
data->psensor_pdata->tp_psensor_opened) {
|
||||||
|
rc = ft5x06_read_tp_psensor_data(data);
|
||||||
|
if (rc) {
|
||||||
|
if (data->suspended)
|
||||||
|
pm_wakeup_event(&data->client->dev,
|
||||||
|
FT_PSENSOR_WAKEUP_TIMEOUT);
|
||||||
|
input_report_abs(data->psensor_pdata->input_psensor_dev,
|
||||||
|
ABS_DISTANCE,
|
||||||
|
data->psensor_pdata->tp_psensor_data);
|
||||||
|
input_sync(data->psensor_pdata->input_psensor_dev);
|
||||||
|
if (data->suspended)
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
if (data->suspended)
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read touch data start from register FT_REG_DEV_MODE.
|
||||||
|
* The touch x/y value start from FT_TOUCH_X_H/L_POS and
|
||||||
|
* FT_TOUCH_Y_H/L_POS in buf.
|
||||||
|
*/
|
||||||
|
reg = FT_REG_DEV_MODE;
|
||||||
|
rc = ft5x06_i2c_read(data->client, ®, 1, buf, data->tch_data_len);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dev_err(&data->client->dev, "%s: read data fail\n", __func__);
|
dev_err(&data->client->dev, "%s: read data fail\n", __func__);
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
@ -661,6 +800,16 @@ static int ft5x06_ts_suspend(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support &&
|
||||||
|
device_may_wakeup(dev) &&
|
||||||
|
data->psensor_pdata->tp_psensor_opened) {
|
||||||
|
err = enable_irq_wake(data->client->irq);
|
||||||
|
if (err)
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"%s: set_irq_wake failed\n", __func__);
|
||||||
|
data->suspended = true;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
disable_irq(data->client->irq);
|
disable_irq(data->client->irq);
|
||||||
|
|
||||||
/* release all touches */
|
/* release all touches */
|
||||||
|
@ -745,6 +894,18 @@ static int ft5x06_ts_resume(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support &&
|
||||||
|
device_may_wakeup(dev) &&
|
||||||
|
data->psensor_pdata->tp_psensor_opened) {
|
||||||
|
err = disable_irq_wake(data->client->irq);
|
||||||
|
if (err)
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"%s: disable_irq_wake failed\n",
|
||||||
|
__func__);
|
||||||
|
data->suspended = false;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (data->pdata->power_on) {
|
if (data->pdata->power_on) {
|
||||||
err = data->pdata->power_on(true);
|
err = data->pdata->power_on(true);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -1588,6 +1749,8 @@ static int ft5x06_parse_dt(struct device *dev,
|
||||||
pdata->ignore_id_check = of_property_read_bool(np,
|
pdata->ignore_id_check = of_property_read_bool(np,
|
||||||
"focaltech,ignore-id-check");
|
"focaltech,ignore-id-check");
|
||||||
|
|
||||||
|
pdata->psensor_support = of_property_read_bool(np,
|
||||||
|
"focaltech,psensor-support");
|
||||||
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;
|
||||||
|
@ -1623,8 +1786,10 @@ static int ft5x06_ts_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct ft5x06_ts_platform_data *pdata;
|
struct ft5x06_ts_platform_data *pdata;
|
||||||
|
struct ft5x06_psensor_platform_data *psensor_pdata;
|
||||||
struct ft5x06_ts_data *data;
|
struct ft5x06_ts_data *data;
|
||||||
struct input_dev *input_dev;
|
struct input_dev *input_dev;
|
||||||
|
struct input_dev *psensor_input_dev;
|
||||||
struct dentry *temp;
|
struct dentry *temp;
|
||||||
u8 reg_value;
|
u8 reg_value;
|
||||||
u8 reg_addr;
|
u8 reg_addr;
|
||||||
|
@ -1781,17 +1946,61 @@ static int ft5x06_ts_probe(struct i2c_client *client,
|
||||||
|
|
||||||
err = request_threaded_irq(client->irq, NULL,
|
err = request_threaded_irq(client->irq, NULL,
|
||||||
ft5x06_ts_interrupt,
|
ft5x06_ts_interrupt,
|
||||||
pdata->irqflags | IRQF_ONESHOT,
|
IRQF_ONESHOT,
|
||||||
client->dev.driver->name, data);
|
client->dev.driver->name, data);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&client->dev, "request irq failed\n");
|
dev_err(&client->dev, "request irq failed\n");
|
||||||
goto free_gpio;
|
goto free_gpio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support) {
|
||||||
|
device_init_wakeup(&client->dev, 1);
|
||||||
|
psensor_pdata = devm_kzalloc(&client->dev,
|
||||||
|
sizeof(struct ft5x06_psensor_platform_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!psensor_pdata) {
|
||||||
|
dev_err(&client->dev, "Failed to allocate memory\n");
|
||||||
|
goto irq_free;
|
||||||
|
}
|
||||||
|
data->psensor_pdata = psensor_pdata;
|
||||||
|
|
||||||
|
psensor_input_dev = input_allocate_device();
|
||||||
|
if (!psensor_input_dev) {
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"Failed to allocate device\n");
|
||||||
|
goto free_psensor_pdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_bit(EV_ABS, psensor_input_dev->evbit);
|
||||||
|
input_set_abs_params(psensor_input_dev,
|
||||||
|
ABS_DISTANCE, 0, 1, 0, 0);
|
||||||
|
psensor_input_dev->name = "proximity";
|
||||||
|
psensor_input_dev->id.bustype = BUS_I2C;
|
||||||
|
psensor_input_dev->dev.parent = &data->client->dev;
|
||||||
|
data->psensor_pdata->input_psensor_dev = psensor_input_dev;
|
||||||
|
|
||||||
|
err = input_register_device(psensor_input_dev);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"Unable to register device, err=%d\n", err);
|
||||||
|
goto free_psensor_input_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
psensor_pdata->ps_cdev = sensors_proximity_cdev;
|
||||||
|
psensor_pdata->ps_cdev.sensors_enable =
|
||||||
|
ft5x06_psensor_enable_set;
|
||||||
|
psensor_pdata->data = data;
|
||||||
|
|
||||||
|
err = sensors_classdev_register(&client->dev,
|
||||||
|
&psensor_pdata->ps_cdev);
|
||||||
|
if (err)
|
||||||
|
goto unregister_psensor_input_device;
|
||||||
|
}
|
||||||
|
|
||||||
err = device_create_file(&client->dev, &dev_attr_fw_name);
|
err = device_create_file(&client->dev, &dev_attr_fw_name);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&client->dev, "sys file creation failed\n");
|
dev_err(&client->dev, "sys file creation failed\n");
|
||||||
goto irq_free;
|
goto free_psensor_class_sysfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = device_create_file(&client->dev, &dev_attr_update_fw);
|
err = device_create_file(&client->dev, &dev_attr_update_fw);
|
||||||
|
@ -1900,7 +2109,23 @@ free_update_fw_sys:
|
||||||
device_remove_file(&client->dev, &dev_attr_update_fw);
|
device_remove_file(&client->dev, &dev_attr_update_fw);
|
||||||
free_fw_name_sys:
|
free_fw_name_sys:
|
||||||
device_remove_file(&client->dev, &dev_attr_fw_name);
|
device_remove_file(&client->dev, &dev_attr_fw_name);
|
||||||
|
free_psensor_class_sysfs:
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support)
|
||||||
|
sensors_classdev_unregister(&psensor_pdata->ps_cdev);
|
||||||
|
unregister_psensor_input_device:
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support)
|
||||||
|
input_unregister_device(data->psensor_pdata->input_psensor_dev);
|
||||||
|
free_psensor_input_dev:
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support)
|
||||||
|
input_free_device(data->psensor_pdata->input_psensor_dev);
|
||||||
|
free_psensor_pdata:
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support) {
|
||||||
|
devm_kfree(&client->dev, psensor_pdata);
|
||||||
|
data->psensor_pdata = NULL;
|
||||||
|
}
|
||||||
irq_free:
|
irq_free:
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support)
|
||||||
|
device_init_wakeup(&client->dev, 0);
|
||||||
free_irq(client->irq, data);
|
free_irq(client->irq, data);
|
||||||
free_gpio:
|
free_gpio:
|
||||||
if (gpio_is_valid(pdata->reset_gpio))
|
if (gpio_is_valid(pdata->reset_gpio))
|
||||||
|
@ -1930,9 +2155,9 @@ pwr_deinit:
|
||||||
ft5x06_power_init(data, false);
|
ft5x06_power_init(data, false);
|
||||||
unreg_inputdev:
|
unreg_inputdev:
|
||||||
input_unregister_device(input_dev);
|
input_unregister_device(input_dev);
|
||||||
input_dev = NULL;
|
|
||||||
free_inputdev:
|
free_inputdev:
|
||||||
input_free_device(input_dev);
|
input_free_device(input_dev);
|
||||||
|
input_dev = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1941,6 +2166,16 @@ static int ft5x06_ts_remove(struct i2c_client *client)
|
||||||
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
|
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (ft5x06_psensor_support_enabled() && data->pdata->psensor_support) {
|
||||||
|
|
||||||
|
device_init_wakeup(&client->dev, 0);
|
||||||
|
sensors_classdev_unregister(&data->psensor_pdata->ps_cdev);
|
||||||
|
input_unregister_device(data->psensor_pdata->input_psensor_dev);
|
||||||
|
input_free_device(data->psensor_pdata->input_psensor_dev);
|
||||||
|
devm_kfree(&client->dev, data->psensor_pdata);
|
||||||
|
data->psensor_pdata = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
debugfs_remove_recursive(data->dir);
|
debugfs_remove_recursive(data->dir);
|
||||||
device_remove_file(&client->dev, &dev_attr_force_update_fw);
|
device_remove_file(&client->dev, &dev_attr_force_update_fw);
|
||||||
device_remove_file(&client->dev, &dev_attr_update_fw);
|
device_remove_file(&client->dev, &dev_attr_update_fw);
|
||||||
|
|
|
@ -34,6 +34,14 @@ struct fw_upgrade_info {
|
||||||
u16 delay_erase_flash;
|
u16 delay_erase_flash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ft5x06_psensor_platform_data {
|
||||||
|
struct input_dev *input_psensor_dev;
|
||||||
|
struct sensors_classdev ps_cdev;
|
||||||
|
int tp_psensor_opened;
|
||||||
|
char tp_psensor_data; /* 0 near, 1 far */
|
||||||
|
struct ft5x06_ts_data *data;
|
||||||
|
};
|
||||||
|
|
||||||
struct ft5x06_ts_platform_data {
|
struct ft5x06_ts_platform_data {
|
||||||
struct fw_upgrade_info info;
|
struct fw_upgrade_info info;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -60,6 +68,7 @@ struct ft5x06_ts_platform_data {
|
||||||
bool no_force_update;
|
bool no_force_update;
|
||||||
bool i2c_pull_up;
|
bool i2c_pull_up;
|
||||||
bool ignore_id_check;
|
bool ignore_id_check;
|
||||||
|
bool psensor_support;
|
||||||
int (*power_init)(bool);
|
int (*power_init)(bool);
|
||||||
int (*power_on)(bool);
|
int (*power_on)(bool);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue