diff options
author | Robert Collins <rcollins@nvidia.com> | 2011-09-21 15:51:37 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:50:12 -0800 |
commit | 9142901aa27a58a5c492f0f7428b65056fd377ab (patch) | |
tree | 1276633a5a420be26a5f4d4748e7daec8a4addfc /drivers/input/touchscreen/atmel_mxt_ts.c | |
parent | 760c58bf5cd0d0e4a1c2ec889e91baa9d3922a05 (diff) |
input: touch: atmel_mxt_ts: Updated to new Atmel touch driver.
Updated to new Atmel touch driver. Added sysfs interface to
allow Config-UI applications to run.
Primary changes:
* Add sysfs interface to allow user applications access to the
touchscreen controller register interface. Required by
Config-UI utility.
* Fixed bug in stop/start functions that would prevent TS
from working with encrypted filesystems.
* Fix logic error that could cause a deadlock condition during
LP0 resume.
Change-Id: If25260e60843e3c3bb3a9818ed9146ea78c39902
Reviewed-on: http://git-master/r/65004
Reviewed-by: Robert Collins <rcollins@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: R9bde02eeeae3a899e18d17b5ff26cac371729cb0
Diffstat (limited to 'drivers/input/touchscreen/atmel_mxt_ts.c')
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 482 |
1 files changed, 339 insertions, 143 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 775b3c2cc2a0..89ffc1225405 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -22,9 +22,13 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/slab.h> +#if defined(CONFIG_HAS_EARLYSUSPEND) +#include <linux/earlysuspend.h> +#endif /* Family ID */ #define MXT224_ID 0x80 +#define MXT768E_ID 0xA1 #define MXT1386_ID 0xA0 /* Version */ @@ -183,12 +187,13 @@ #define MXT_BACKUP_VALUE 0x55 #define MXT_BACKUP_TIME 200 /* msec */ #define MXT224_RESET_TIME 65 /* msec */ +#define MXT768E_RESET_TIME 250 /* msec */ #define MXT1386_RESET_TIME 200 /* msec */ #define MXT_RESET_TIME 200 /* msec */ #define MXT_RESET_NOCHGREAD 400 /* msec */ #define MXT_RESET_TIME 200 /* msec */ -#define MXT_WAKEUP_TIME 25 +#define MXT_WAKEUP_TIME 25 /* msec */ #define MXT_FWRESET_TIME 175 /* msec */ @@ -242,11 +247,12 @@ struct mxt_info { struct mxt_object { u8 type; u16 start_address; - u8 size; - u8 instances; + u16 size; + u16 instances; u8 num_report_ids; /* to map object and message */ + u8 min_reportid; u8 max_reportid; }; @@ -282,6 +288,9 @@ struct mxt_data { u8 idle_cycle_time; u8 is_stopped; struct mutex access_mutex; + unsigned int driver_paused; + struct bin_attribute mem_access_attr; + int debug_enabled; }; @@ -425,41 +434,39 @@ static int mxt_fw_write(struct i2c_client *client, static int __mxt_read_reg(struct i2c_client *client, u16 reg, u16 len, void *val) { - struct i2c_msg xfer[2]; u8 buf[2]; int retval = 0; struct mxt_data *data = i2c_get_clientdata(client); - if ((data->last_address == reg) && (reg == data->msg_address)) { - mutex_lock(&data->access_mutex); - if (i2c_master_recv(client, val, len) != len) { - dev_err(&client->dev, - "%s: Failure reading maxTouch device\n", - __func__); - retval = -EIO; - } - goto mxt_read_exit; - } - buf[0] = reg & 0xff; buf[1] = (reg >> 8) & 0xff; - /* Write register */ - xfer[0].addr = client->addr; - xfer[0].flags = 0; - xfer[0].len = 2; - xfer[0].buf = buf; + mutex_lock(&data->access_mutex); - /* Read data */ - xfer[1].addr = client->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = len; - xfer[1].buf = val; + if ((data->last_address != reg) || (reg != data->msg_address)) { + if (i2c_master_send(client, (u8 *)buf, 2) != 2) { + dev_dbg(&client->dev, "i2c retry\n"); + msleep(MXT_WAKEUP_TIME); - mutex_lock(&data->access_mutex); - if (i2c_transfer(client->adapter, xfer, 2) != 2) { - dev_err(&client->dev, "%s: i2c transfer failed\n", __func__); - retval = -EIO; + if (i2c_master_send(client, (u8 *)buf, 2) != 2) { + dev_err(&client->dev, "%s: i2c send failed\n", + __func__); + retval = -EIO; + goto mxt_read_exit; + } + } + } + + if (i2c_master_recv(client, (u8 *)val, len) != len) { + dev_dbg(&client->dev, "i2c retry\n"); + msleep(MXT_WAKEUP_TIME); + + if (i2c_master_recv(client, (u8 *)val, len) != len) { + dev_err(&client->dev, "%s: i2c recv failed\n", + __func__); + retval = -EIO; + goto mxt_read_exit; + } } data->last_address = reg; @@ -486,9 +493,14 @@ static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) mutex_lock(&data->access_mutex); if (i2c_master_send(client, buf, 3) != 3) { - dev_err(&client->dev, "%s: i2c send failed\n", __func__); - retval = -EIO; - goto mxt_write_exit; + dev_dbg(&client->dev, "i2c retry\n"); + msleep(MXT_WAKEUP_TIME); + + if (i2c_master_send(client, buf, 3) != 3) { + dev_err(&client->dev, "%s: i2c send failed\n", __func__); + retval = -EIO; + goto mxt_write_exit; + } } data->last_address = reg + 1; @@ -516,7 +528,7 @@ mxt_get_object(struct mxt_data *data, u8 type) return object; } - dev_err(&data->client->dev, "Invalid object type\n"); + dev_err(&data->client->dev, "Invalid object type T%d\n", type); return NULL; } @@ -658,34 +670,34 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) { struct mxt_data *data = dev_id; struct mxt_message message; - struct mxt_object *object; + struct mxt_object *touch_object; struct device *dev = &data->client->dev; - int id; + int touchid; u8 reportid; - u8 max_reportid; - u8 min_reportid; do { if (mxt_read_message(data, &message)) { dev_err(dev, "Failed to read message\n"); goto end; } + reportid = message.reportid; - /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */ - object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); - if (!object) + touch_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); + if (!touch_object) goto end; - max_reportid = object->max_reportid; - min_reportid = max_reportid - object->num_report_ids + 1; - id = reportid - min_reportid; + if (data->debug_enabled) + print_hex_dump(KERN_DEBUG, "MXT MSG:", DUMP_PREFIX_NONE, + 16, 1, &message, sizeof(struct mxt_message), false); - if (reportid >= min_reportid && reportid <= max_reportid) - mxt_input_touchevent(data, &message, id); - else + if (reportid >= touch_object->min_reportid + && reportid <= touch_object->max_reportid) { + touchid = reportid - touch_object->min_reportid; + mxt_input_touchevent(data, &message, touchid); + } else if (reportid != MXT_RPTID_NOMSG) mxt_dump_message(dev, &message); - } while (reportid != 0xff); + } while (reportid != MXT_RPTID_NOMSG); end: return IRQ_HANDLED; @@ -703,7 +715,7 @@ static int mxt_make_highchg(struct mxt_data *data) error = mxt_read_message(data, &message); if (error) return error; - } while (message.reportid != 0xff && --count); + } while (message.reportid != MXT_RPTID_NOMSG && --count); if (!count) { dev_err(dev, "CHG pin isn't cleared\n"); @@ -721,7 +733,7 @@ static int mxt_check_reg_init(struct mxt_data *data) struct mxt_message message; struct device *dev = &data->client->dev; int index = 0; - int timeout_counter; + int timeout_counter = 0; int i, j, config_offset; int error; unsigned long current_crc; @@ -776,7 +788,7 @@ static int mxt_check_reg_init(struct mxt_data *data) continue; dev_info(dev, "Writing object type %d, config offset %d", data->object_table[i].type, index); for (j = 0; - j < (object->size + 1) * (object->instances + 1); + j < object->size * object->instances; j++) { config_offset = index + j; if (config_offset > pdata->config_length) { @@ -787,7 +799,7 @@ static int mxt_check_reg_init(struct mxt_data *data) mxt_write_object(data, object->type, j, pdata->config[config_offset]); } - index += (object->size + 1) * (object->instances + 1); + index += object->size * object->instances; } dev_info(dev, "Config written!"); @@ -806,9 +818,9 @@ static int mxt_check_reg_init(struct mxt_data *data) &command_register); if (error) return error; - msleep(2); + msleep(10); } while ((command_register != 0) && (timeout_counter++ <= 100)); - if (timeout_counter >= 100) { + if (timeout_counter > 100) { dev_err(&client->dev, "No response after backup!\n"); return -EIO; } @@ -828,6 +840,9 @@ static int mxt_check_reg_init(struct mxt_data *data) case MXT224_ID: msleep(MXT224_RESET_TIME); break; + case MXT768E_ID: + msleep(MXT768E_RESET_TIME); + break; case MXT1386_ID: msleep(MXT1386_RESET_TIME); break; @@ -836,8 +851,8 @@ static int mxt_check_reg_init(struct mxt_data *data) } timeout_counter = 0; while ((timeout_counter++ <= 100) && data->pdata->read_chg()) - msleep(2); - if (timeout_counter >= 100) { + msleep(10); + if (timeout_counter > 100) { dev_err(&client->dev, "No response after reset!\n"); return -EIO; } @@ -853,7 +868,76 @@ static void mxt_handle_pdata(struct mxt_data *data) if (pdata->read_chg != NULL) data->read_chg = pdata->read_chg; +} + +static int mxt_set_power_cfg(struct mxt_data *data, u8 sleep) +{ + struct device *dev = &data->client->dev; + int error; + u8 actv_cycle_time = 0; + u8 idle_cycle_time = 0; + + if (!sleep) { + actv_cycle_time = data->actv_cycle_time; + idle_cycle_time = data->idle_cycle_time; + } + + error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, + actv_cycle_time); + if (error) + goto i2c_error; + + error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, + idle_cycle_time); + if (error) + goto i2c_error; + + dev_dbg(dev, "%s: Set ACTV %d, IDLE %d", __func__, + actv_cycle_time, idle_cycle_time); + data->is_stopped = sleep; + + return 0; + +i2c_error: + dev_err(dev, "Failed to set power cfg"); + return error; +} + +static int mxt_init_power_cfg(struct mxt_data *data) +{ + const struct mxt_platform_data *pdata = data->pdata; + struct device *dev = &data->client->dev; + int error; + + if (pdata->actv_cycle_time > 0 && pdata->idle_cycle_time > 0) { + data->actv_cycle_time = pdata->actv_cycle_time; + data->idle_cycle_time = pdata->idle_cycle_time; + } else { + error = mxt_read_object(data, MXT_GEN_POWER_T7, + MXT_POWER_ACTVACQINT, + &data->actv_cycle_time); + + if (error) + return error; + + error = mxt_read_object(data, MXT_GEN_POWER_T7, + MXT_POWER_IDLEACQINT, + &data->idle_cycle_time); + + if (error) + return error; + } + + /* On init, power up */ + error = mxt_set_power_cfg(data, 0); + if (error) + return error; + + dev_info(dev, "Initialised power cfg: ACTV %d, IDLE %d", + data->actv_cycle_time, data->idle_cycle_time); + + return 0; } static int mxt_get_info(struct mxt_data *data) @@ -863,6 +947,9 @@ static int mxt_get_info(struct mxt_data *data) int error; u8 val; + /* force send of address pointer on first read during probe */ + data->last_address = -1; + error = mxt_read_reg(client, MXT_FAMILY_ID, &val); if (error) return error; @@ -893,6 +980,7 @@ static int mxt_get_info(struct mxt_data *data) static int mxt_get_object_table(struct mxt_data *data) { + struct device *dev = &data->client->dev; int error; int i; u16 reg; @@ -909,14 +997,15 @@ static int mxt_get_object_table(struct mxt_data *data) object->type = buf[0]; object->start_address = (buf[2] << 8) | buf[1]; - object->size = buf[3]; - object->instances = buf[4]; + object->size = buf[3] + 1; + object->instances = buf[4] + 1; object->num_report_ids = buf[5]; if (object->num_report_ids) { - reportid += object->num_report_ids * - (object->instances + 1); + reportid += object->num_report_ids * object->instances; object->max_reportid = reportid; + object->min_reportid = object->max_reportid - + object->instances * object->num_report_ids + 1; } /* Store message window address so we don't have to @@ -924,6 +1013,11 @@ static int mxt_get_object_table(struct mxt_data *data) if (object->type == MXT_GEN_MESSAGE_T5) data->msg_address = object->start_address; + dev_dbg(dev, "T%d, start:%d size:%d instances:%d " + "min_reportid:%d max_reportid:%d\n", + object->type, object->start_address, object->size, + object->instances, + object->min_reportid, object->max_reportid); } return 0; @@ -934,8 +1028,6 @@ static int mxt_initialize(struct mxt_data *data) struct i2c_client *client = data->client; struct mxt_info *info = &data->info; int error; - u8 idle_cycle_time; - u8 actv_cycle_time; error = mxt_get_info(data); if (error) @@ -951,31 +1043,25 @@ static int mxt_initialize(struct mxt_data *data) /* Get object table information */ error = mxt_get_object_table(data); - if (error) + if (error) { + dev_err(&client->dev, "Failed to read object table\n"); return error; + } /* Load initial touch chip configuration */ error = mxt_check_reg_init(data); - if (error) + if (error) { + dev_err(&client->dev, "Failed to initialize configuration\n"); return error; + } mxt_handle_pdata(data); - /* Read current cycle times */ - error = mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, - &idle_cycle_time); - if (error) - return error; - error = mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, - &actv_cycle_time); - if (error) + error = mxt_init_power_cfg(data); + if (error) { + dev_err(&client->dev, "Failed to initialize power cfg\n"); return error; - - dev_info(&client->dev, "in mxt_initialize(), Active Cycle Time: %d Idle Cycle Time: %d\n", - actv_cycle_time, idle_cycle_time); - - data->actv_cycle_time = actv_cycle_time; - data->idle_cycle_time = idle_cycle_time; + } dev_info(&client->dev, "Family ID: %d Variant ID: %d Version: %d Build: %d\n", @@ -1017,26 +1103,35 @@ static ssize_t mxt_object_show(struct device *dev, for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; - count += sprintf(buf + count, - "Object Table Element %d(Type %d)\n", + count += snprintf(buf + count, PAGE_SIZE - count, + "Object[%d] (Type %d)\n", i + 1, object->type); + if (count >= PAGE_SIZE) + return PAGE_SIZE - 1; if (!mxt_object_readable(object->type)) { - count += sprintf(buf + count, "\n"); + count += snprintf(buf + count, PAGE_SIZE - count, + "\n"); + if (count >= PAGE_SIZE) + return PAGE_SIZE - 1; continue; } - for (j = 0; j < object->size + 1; j++) { + for (j = 0; j < object->size; j++) { error = mxt_read_object(data, object->type, j, &val); if (error) return error; - count += sprintf(buf + count, - " Byte %d: 0x%x (%d)\n", j, val, val); + count += snprintf(buf + count, PAGE_SIZE - count, + "\t[%2d]: %02x (%d)\n", j, val, val); + if (count >= PAGE_SIZE) + return PAGE_SIZE - 1; } - count += sprintf(buf + count, "\n"); + count += snprintf(buf + count, PAGE_SIZE - count, "\n"); + if (count >= PAGE_SIZE) + return PAGE_SIZE - 1; } return count; @@ -1147,12 +1242,144 @@ static ssize_t mxt_update_fw_store(struct device *dev, return count; } +static ssize_t mxt_pause_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int count = 0; + + count += sprintf(buf + count, "%d", data->driver_paused); + count += sprintf(buf + count, "\n"); + + return count; +} + +static ssize_t mxt_pause_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + data->driver_paused = i; + + dev_dbg(dev, "%s\n", i ? "paused" : "unpaused"); + } else { + dev_dbg(dev, "pause_driver write error\n"); + } + return count; +} + +static ssize_t mxt_debug_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int count = 0; + + count += sprintf(buf + count, "%d", data->debug_enabled); + count += sprintf(buf + count, "\n"); + + return count; +} + +static ssize_t mxt_debug_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + data->debug_enabled = i; + + dev_dbg(dev, "%s\n", i ? "debug enabled" : "debug disabled"); + } else { + dev_dbg(dev, "debug_enabled write error\n"); + } + return count; +} + +static ssize_t mxt_mem_access_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct mxt_data *data = dev_get_drvdata(dev); + int ret = 0; + + if (off >= 32768) + return -EIO; + + if (off + count > 32768) + count = 32768 - off; + + if (count > 256) + count = 256; + + if (count > 0) + ret = __mxt_read_reg(data->client, off, count, buf); + + return ret == 0 ? count : ret; +} + +int mxt_write_block(struct i2c_client *client, u16 addr, u16 length, u8 *value) +{ + int i; + struct { + __le16 le_addr; + u8 data[256]; + } i2c_block_transfer; + + struct mxt_data *mxt; + + if (length > 256) + return -EINVAL; + + i2c_get_clientdata(client); + + for (i = 0; i < length; i++) + i2c_block_transfer.data[i] = *value++; + + i2c_block_transfer.le_addr = cpu_to_le16(addr); + + i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2); + + if (i == (length + 2)) + return 0; + else + return -EIO; +} + +static ssize_t mxt_mem_access_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct mxt_data *data = dev_get_drvdata(dev); + int ret = 0; + + if (off >= 32768) + return -EIO; + + if (off + count > 32768) + count = 32768 - off; + + if (count > 256) + count = 256; + + if (count > 0) + ret = mxt_write_block(data->client, off, count, buf); + + return ret == 0 ? count : 0; +} + static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); +static DEVICE_ATTR(pause_driver, 0664, mxt_pause_show, mxt_pause_store); +static DEVICE_ATTR(debug_enable, 0664, mxt_debug_enable_show, mxt_debug_enable_store); static struct attribute *mxt_attrs[] = { &dev_attr_object.attr, &dev_attr_update_fw.attr, + &dev_attr_pause_driver.attr, + &dev_attr_debug_enable.attr, NULL }; @@ -1168,74 +1395,29 @@ static void mxt_start(struct mxt_data *data) if (data->is_stopped == 0) return; - dev_info(dev, "in MXT_START(), idle time: %d %d", data->idle_cycle_time, data->actv_cycle_time); - /* Restore the cycle time settings to wake from sleep */ - error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, - data->actv_cycle_time); - if (error) - dev_info(dev, "\n\nResume failed!"); - error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, - data->idle_cycle_time); - if (error) - dev_info(dev, "\n\nResume failed!"); + error = mxt_set_power_cfg(data, 0); - dev_info(dev, "Restored ACTV %d, IDLE %d", data->actv_cycle_time, - data->idle_cycle_time); - data->is_stopped = 0; + if (!error) + dev_dbg(dev, "MXT started\n"); } static void mxt_stop(struct mxt_data *data) { - u8 actv_cycle_time; - u8 idle_cycle_time; int error; struct device *dev = &data->client->dev; if (data->is_stopped) return; + error = mxt_set_power_cfg(data, 1); - error = mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, - &actv_cycle_time); - if (error) - goto i2c_error; - - data->actv_cycle_time = actv_cycle_time; - - error = mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, - &idle_cycle_time); - if (error) - goto i2c_error; - - data->idle_cycle_time = idle_cycle_time; - - /* Set to deep sleep mode for maximum power savings */ - error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, 0); - if (error) - goto i2c_error; - - error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, 0); - if (error) - goto i2c_error; - - dev_info(dev, "MXT Suspended, saved ACTV %d and IDLE %d", - actv_cycle_time, idle_cycle_time); - data->is_stopped = 1; - return; - -i2c_error: - dev_info(dev, "MXT Suspend failed!"); - + if (!error) + dev_dbg(dev, "MXT suspended\n"); } static int mxt_input_open(struct input_dev *dev) { struct mxt_data *data = input_get_drvdata(dev); - u8 n; - - /* A dummy read to wake up the chip */ - mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, &n); - msleep(MXT_WAKEUP_TIME); mxt_start(data); @@ -1321,16 +1503,34 @@ static int __devinit mxt_probe(struct i2c_client *client, } error = mxt_make_highchg(data); - if (error) + if (error) { + dev_err(&client->dev, "Failed to make high CHG\n"); goto err_free_irq; + } error = input_register_device(input_dev); - if (error) + if (error) { + dev_err(&client->dev, "Failed to register input device\n"); goto err_free_irq; + } error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); - if (error) + if (error) { + dev_err(&client->dev, "Failed to create sysfs group\n"); goto err_unregister_device; + } + + sysfs_bin_attr_init(&data->mem_access_attr); + data->mem_access_attr.attr.name = "mem_access"; + data->mem_access_attr.attr.mode = S_IRUGO | S_IWUGO; + data->mem_access_attr.read = mxt_mem_access_read; + data->mem_access_attr.write = mxt_mem_access_write; + data->mem_access_attr.size = 65535; + + if (sysfs_create_bin_file(&client->dev.kobj, &data->mem_access_attr) < 0) { + dev_err(&client->dev, "Failed to create %s\n", data->mem_access_attr.attr.name); + goto err_unregister_device; + } return 0; @@ -1351,6 +1551,7 @@ static int __devexit mxt_remove(struct i2c_client *client) { struct mxt_data *data = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &data->mem_access_attr); sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); free_irq(data->irq, data); input_unregister_device(data->input_dev); @@ -1389,11 +1590,6 @@ static int mxt_resume(struct device *dev) u8 reportid; u8 max_reportid; u8 min_reportid; - u8 n; - - /* A dummy read to wake up the chip */ - mxt_read_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, &n); - msleep(MXT_WAKEUP_TIME); mutex_lock(&input_dev->mutex); |