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.d...@itdev.co.uk>
---
 drivers/input/touchscreen/atmel_mxt_ts.c |  104 ++++++++++++++++++++++++------
 include/linux/i2c/atmel_mxt_ts.h         |    1 +
 2 files changed, 86 insertions(+), 19 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c 
b/drivers/input/touchscreen/atmel_mxt_ts.c
index 9aa3a26..9a5ac2c 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -28,7 +28,6 @@
 #include <linux/gpio.h>
 
 /* Configuration file */
-#define MXT_CFG_NAME           "maxtouch.cfg"
 #define MXT_CFG_MAGIC          "OBP_RAW V1"
 
 /* Registers */
@@ -246,6 +245,7 @@ struct mxt_data {
        struct regulator *reg_vdd;
        struct regulator *reg_avdd;
        char *fw_name;
+       char *cfg_name;
 
        /* Cached parameters from object table */
        u16 T5_address;
@@ -1372,10 +1372,15 @@ static int mxt_check_reg_init(struct mxt_data *data)
        u8 val;
        u16 reg;
 
-       ret = request_firmware(&cfg, MXT_CFG_NAME, dev);
+       if (!data->cfg_name) {
+               dev_dbg(dev, "Skipping cfg download\n");
+               return 0;
+       }
+
+       ret = request_firmware(&cfg, data->cfg_name, dev);
        if (ret < 0) {
                dev_err(dev, "Failure to request config file %s\n",
-                       MXT_CFG_NAME);
+                       data->cfg_name);
                return 0;
        }
 
@@ -1673,6 +1678,14 @@ static int mxt_acquire_irq(struct mxt_data *data)
        return 0;
 }
 
+static void mxt_free_input_device(struct mxt_data *data)
+{
+       if (data->input_dev) {
+               input_unregister_device(data->input_dev);
+               data->input_dev = NULL;
+       }
+}
+
 static void mxt_free_object_table(struct mxt_data *data)
 {
        kfree(data->raw_info_block);
@@ -1682,10 +1695,7 @@ static void mxt_free_object_table(struct mxt_data *data)
        kfree(data->msg_buf);
        data->msg_buf = NULL;
 
-       if (data->input_dev) {
-               input_unregister_device(data->input_dev);
-               data->input_dev = NULL;
-       }
+       mxt_free_input_device(data);
 
        data->enable_reporting = false;
        data->T5_address = 0;
@@ -2181,6 +2191,7 @@ err_free_mem:
 }
 
 static int mxt_initialize_t9_input_device(struct mxt_data *data);
+static int mxt_configure_objects(struct mxt_data *data);
 
 static int mxt_initialize(struct mxt_data *data)
 {
@@ -2224,16 +2235,28 @@ retry_bootloader:
 
        error = mxt_check_retrigen(data);
        if (error)
-               goto err_free_object_table;
+               return error;
 
        error = mxt_acquire_irq(data);
        if (error)
-               goto err_free_object_table;
+               return error;
+
+       error = mxt_configure_objects(data);
+       if (error)
+               return error;
+
+       return 0;
+}
+
+static int mxt_configure_objects(struct mxt_data *data)
+{
+       struct i2c_client *client = data->client;
+       int error;
 
        error = mxt_init_t7_power_cfg(data);
        if (error) {
                dev_err(&client->dev, "Failed to initialize power cfg\n");
-               goto err_free_object_table;
+               return error;
        }
 
        /* Check register init values */
@@ -2241,28 +2264,23 @@ retry_bootloader:
        if (error) {
                dev_err(&client->dev, "Error %d initialising configuration\n",
                        error);
-               goto err_free_object_table;
+               return error;
        }
 
        if (data->T9_reportid_min) {
                error = mxt_initialize_t9_input_device(data);
                if (error)
-                       goto err_free_object_table;
+                       return error;
        } else if (data->T100_reportid_min) {
                error = mxt_initialize_t100_input_device(data);
                if (error)
-                       goto err_free_object_table;
+                       return error;
        } else {
                dev_warn(&client->dev, "No touch object detected\n");
        }
 
        data->enable_reporting = true;
-
        return 0;
-
-err_free_object_table:
-       mxt_free_object_table(data);
-       return error;
 }
 
 /* Firmware Version is returned as Major.Minor.Build */
@@ -2550,16 +2568,57 @@ static ssize_t mxt_update_fw_store(struct device *dev,
        return count;
 }
 
+static ssize_t mxt_update_cfg_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct mxt_data *data = dev_get_drvdata(dev);
+       int ret;
+
+       if (data->in_bootloader) {
+               dev_err(dev, "Not in appmode\n");
+               return -EINVAL;
+       }
+
+       ret = mxt_update_file_name(dev, &data->cfg_name, buf, count);
+       if (ret)
+               return ret;
+
+       data->enable_reporting = false;
+       mxt_free_input_device(data);
+
+       if (data->suspended) {
+               if (data->use_regulator)
+                       mxt_regulator_enable(data);
+               else
+                       mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+
+               mxt_acquire_irq(data);
+
+               data->suspended = false;
+       }
+
+       ret = mxt_configure_objects(data);
+       if (ret)
+               goto out;
+
+       ret = count;
+out:
+       return ret;
+}
+
 static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
 static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
 static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
 static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+static DEVICE_ATTR(update_cfg, S_IWUSR, NULL, mxt_update_cfg_store);
 
 static struct attribute *mxt_attrs[] = {
        &dev_attr_fw_version.attr,
        &dev_attr_hw_version.attr,
        &dev_attr_object.attr,
        &dev_attr_update_fw.attr,
+       &dev_attr_update_cfg.attr,
        NULL
 };
 
@@ -2644,8 +2703,15 @@ static int mxt_handle_pdata(struct mxt_data *data)
        data->pdata = dev_get_platdata(&data->client->dev);
 
        /* Use provided platform data if present */
-       if (data->pdata)
+       if (data->pdata) {
+               if (data->pdata->cfg_name)
+                       mxt_update_file_name(&data->client->dev,
+                                            &data->cfg_name,
+                                            data->pdata->cfg_name,
+                                            strlen(data->pdata->cfg_name));
+
                return 0;
+       }
 
        data->pdata = kzalloc(sizeof(*data->pdata), GFP_KERNEL);
        if (!data->pdata) {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index a01f2e8..3422bd0 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -23,6 +23,7 @@ struct mxt_platform_data {
        int t15_num_keys;
        const unsigned int *t15_keymap;
        unsigned long gpio_reset;
+       const char *cfg_name;
 };
 
 #endif /* __LINUX_ATMEL_MXT_TS_H */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to