From 71a2a4d1954460b949a16b607f72bafab294ca79 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Tue, 5 Mar 2013 15:57:05 +0000 Subject: [PATCH] Input: atmel_mxt_ts - handle cfg filename via pdata/sysfs 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 Acked-by: Yufeng Shen --- .../bindings/input/atmel,maxtouch.txt | 3 + drivers/input/touchscreen/atmel_mxt_ts.c | 95 ++++++++++++++++--- include/linux/platform_data/atmel_mxt_ts.h | 1 + 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt index 3b94a43f251647..56dc8561d00ccb 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt @@ -30,6 +30,9 @@ Optional properties for main touchpad device: - atmel,reset-gpio: Configure RESET GPIO. Required for regulator support. +- atmel,cfg_name: Provide name of configuration file in OBP_RAW format. This + will be downloaded from the firmware loader on probe to the device. + Example: touch@4b { diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index c0ac9ce1044ce9..010ea112b533ee 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -34,7 +34,6 @@ #include /* Configuration file */ -#define MXT_CFG_NAME "maxtouch.cfg" #define MXT_CFG_MAGIC "OBP_RAW V1" /* Registers */ @@ -279,6 +278,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; @@ -316,6 +316,9 @@ struct mxt_data { /* Indicates whether device is in suspend */ bool suspended; + + /* Indicates whether device is updating configuration */ + bool updating_config; }; static size_t mxt_obj_size(const struct mxt_object *obj) @@ -2477,13 +2480,19 @@ static int mxt_initialize(struct mxt_data *data) if (error) goto err_free_object_table; - error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, - &client->dev, GFP_KERNEL, data, - mxt_config_cb); - if (error) { - dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", - error); - goto err_free_object_table; + if (data->cfg_name) { + error = request_firmware_nowait(THIS_MODULE, true, + data->cfg_name, &data->client->dev, + GFP_KERNEL, data, mxt_config_cb); + if (error) { + dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", + error); + goto err_free_object_table; + } + } else { + error = mxt_configure_objects(data, NULL); + if (error) + goto err_free_object_table; } return 0; @@ -2556,7 +2565,7 @@ 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) { @@ -2568,12 +2577,16 @@ static int mxt_configure_objects(struct mxt_data *data, 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"); } return 0; + +err_free_object_table: + mxt_free_object_table(data); + return error; } /* Firmware Version is returned as Major.Minor.Build */ @@ -2866,6 +2879,56 @@ 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); + const struct mxt_platform_data *pdata = data->pdata; + 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 (pdata->suspend_mode == MXT_SUSPEND_REGULATOR) { + enable_irq(data->irq); + mxt_regulator_enable(data); + } else if (pdata->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(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_fw_attrs[] = { @@ -2880,11 +2943,13 @@ static const struct attribute_group mxt_fw_attr_group = { 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_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_cfg.attr, NULL }; @@ -2985,7 +3050,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->pdata->suspend_mode) { @@ -3062,6 +3127,8 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) pdata->gpio_reset = of_get_named_gpio_flags(np, "atmel,reset-gpio", 0, NULL); + of_property_read_string(np, "atmel,cfg_name", &pdata->cfg_name); + if (of_find_property(np, "linux,gpio-keymap", &proplen)) { pdata->t19_num_keys = proplen / sizeof(u32); @@ -3275,6 +3342,12 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) data->irq = client->irq; i2c_set_clientdata(client, data); + if (data->pdata->cfg_name) + mxt_update_file_name(&data->client->dev, + &data->cfg_name, + data->pdata->cfg_name, + strlen(data->pdata->cfg_name)); + init_completion(&data->bl_completion); init_completion(&data->reset_completion); init_completion(&data->crc_completion); diff --git a/include/linux/platform_data/atmel_mxt_ts.h b/include/linux/platform_data/atmel_mxt_ts.h index 44392016ed864d..e831120580add4 100644 --- a/include/linux/platform_data/atmel_mxt_ts.h +++ b/include/linux/platform_data/atmel_mxt_ts.h @@ -25,6 +25,7 @@ struct mxt_platform_data { int t15_num_keys; const unsigned int *t15_keymap; unsigned long gpio_reset; + const char *cfg_name; }; #endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */