[PATCH v11 20/56] Input: atmel_mxt_ts - handle cfg filename via pdata/sysfs

Jiada Wang
2020-05-08T05:58:21Z

From: Nick Dyer <nick.dyer@itdev.co.uk>

There may be multiple maXTouch chips on a single device which will require
different configuration files. Add a platform data value for the
configuration filename.

Add sysfs entry to write configuration file if the platform data is not
set.

Split out the object initialisation code from mxt_initialize() into
mxt_configure_objects() to allow this.

Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk>
Acked-by: Yufeng Shen <miletus@chromium.org>
(cherry picked from ndyer/linux/for-upstream commit 71a2a4d1954460b949a16b607f72bafab294ca79)
[gdavis: Resolve forward port conflicts due to applying upstream
commit 96a938aa214e ("Input: atmel_mxt_ts - remove platform
data support").]
Signed-off-by: George G. Davis <george_davis@mentor.com>
[gdavis: Squash fix from Vladimir Zapolskiy:
- Input: atmel_mxt_ts - fix error paths in mxt_configure_objects()]
Signed-off-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
[jiada: Separate Documentation/ portion change to another commit
Rename mxt_update_cfg_store to update_cfg_store
Replace DEVICE_ATTR with DEVICE_ATTR_WO
Allow to fallback to legacy cfg name "maxtouch.cfg",
if atmel,cfg_name isn't specified in device-tree]
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
drivers/input/touchscreen/atmel_mxt_ts.c | 85 ++++++++++++++++++++++--
1 file changed, 79 insertions(+), 6 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 720574417219..503e70603a67 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -335,6 +335,8 @@ struct mxt_data {
struct regulator *reg_vdd;
struct regulator *reg_avdd;
char *fw_name;
+ char *cfg_name;
+ const char *pcfg_name;

/* Cached parameters from object table */
u16 T5_address;
@@ -377,6 +379,9 @@ struct mxt_data {

/* Indicates whether device is in suspend */
bool suspended;
+
+ /* Indicates whether device is updating configuration */
+ bool updating_config;
};

struct mxt_vb2_buffer {
@@ -2578,8 +2583,11 @@ static int mxt_initialize(struct mxt_data *data)
if (error)
return error;

- error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
- &client->dev, GFP_KERNEL, data,
+ error = request_firmware_nowait(THIS_MODULE, true,
+ data->cfg_name ?
+ data->cfg_name : MXT_CFG_NAME,
+ &client->dev,
+ GFP_KERNEL, data,
mxt_config_cb);
if (error) {
dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
@@ -3081,19 +3089,21 @@ static int mxt_configure_objects(struct mxt_data *data,
error = mxt_init_t7_power_cfg(data);
if (error) {
dev_err(dev, "Failed to initialize power cfg\n");
- return error;
+ goto err_free_object_table;
}

if (cfg) {
error = mxt_update_cfg(data, cfg);
- if (error)
+ if (error) {
dev_warn(dev, "Error %d updating config\n", error);
+ goto err_free_object_table;
+ }
}

if (data->multitouch) {
error = mxt_initialize_input_device(data);
if (error)
- return error;
+ goto err_free_object_table;
} else {
dev_warn(dev, "No touch object detected\n");
}
@@ -3101,6 +3111,10 @@ static int mxt_configure_objects(struct mxt_data *data,
mxt_debug_init(data);

return 0;
+
+err_free_object_table:
+ mxt_free_object_table(data);
+ return error;
}

/* Firmware Version is returned as Major.Minor.Build */
@@ -3392,6 +3406,55 @@ static ssize_t update_fw_store(struct device *dev,
return count;
}

+static ssize_t update_cfg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ const struct firmware *cfg;
+ int ret;
+
+ ret = mxt_update_file_name(dev, &data->cfg_name, buf, count);
+ if (ret)
+ return ret;
+
+ ret = request_firmware(&cfg, data->cfg_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Failure to request config file %s\n",
+ data->cfg_name);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ data->updating_config = true;
+
+ mxt_free_input_device(data);
+
+ if (data->suspended) {
+ if (data->suspend_mode == MXT_SUSPEND_REGULATOR) {
+ enable_irq(data->irq);
+ mxt_regulator_enable(data);
+ } else if (data->suspend_mode == MXT_SUSPEND_DEEP_SLEEP) {
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+ mxt_acquire_irq(data);
+ }
+
+ data->suspended = false;
+ }
+
+ ret = mxt_configure_objects(data, cfg);
+ if (ret)
+ goto release;
+
+ ret = count;
+
+release:
+ release_firmware(cfg);
+out:
+ data->updating_config = false;
+ return ret;
+}
+
static DEVICE_ATTR_WO(update_fw);

static struct attribute *mxt_fw_attrs[] = {
@@ -3406,11 +3469,13 @@ static const struct attribute_group mxt_fw_attr_group = {
static DEVICE_ATTR_RO(fw_version);
static DEVICE_ATTR_RO(hw_version);
static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+static DEVICE_ATTR_WO(update_cfg);

static struct attribute *mxt_attrs[] = {
&dev_attr_fw_version.attr,
&dev_attr_hw_version.attr,
&dev_attr_object.attr,
+ &dev_attr_update_cfg.attr,
NULL
};

@@ -3511,7 +3576,7 @@ static int mxt_stop(struct mxt_data *data)
{
int ret;

- if (data->suspended || data->in_bootloader)
+ if (data->suspended || data->in_bootloader || data->updating_config)
return 0;

switch (data->suspend_mode) {
@@ -3580,6 +3645,8 @@ static int mxt_parse_device_properties(struct mxt_data *data)
int n_keys;
int error;

+ device_property_read_string(dev, "atmel,cfg_name", &data->pcfg_name);
+
if (device_property_present(dev, keymap_property)) {
n_keys = device_property_count_u32(dev, keymap_property);
if (n_keys <= 0) {
@@ -3705,6 +3772,12 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (error)
return error;

+ if (data->pcfg_name)
+ mxt_update_file_name(&data->client->dev,
+ &data->cfg_name,
+ data->pcfg_name,
+ strlen(data->pcfg_name));
+
data->reset_gpio = devm_gpiod_get_optional(&client->dev,
"reset", GPIOD_OUT_LOW);
if (IS_ERR(data->reset_gpio)) {
--
2.17.1