diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index c6dfd0af6365..03b85711cb70 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -99,9 +99,13 @@ #define MXT_T6_STATUS_COMSERR (1 << 2) /* MXT_GEN_POWER_T7 field */ -#define MXT_POWER_IDLEACQINT 0 -#define MXT_POWER_ACTVACQINT 1 -#define MXT_POWER_ACTV2IDLETO 2 +struct t7_config { + u8 idle; + u8 active; +} __packed; + +#define MXT_POWER_CFG_RUN 0 +#define MXT_POWER_CFG_DEEPSLEEP 1 /* MXT_GEN_ACQUIRE_T8 field */ #define MXT_ACQUIRE_CHRGTIME 0 @@ -113,7 +117,6 @@ #define MXT_ACQUIRE_ATCHCALSTHR 7 /* MXT_TOUCH_MULTI_T9 field */ -#define MXT_TOUCH_CTRL 0 #define MXT_T9_ORIENT 9 #define MXT_T9_RANGE 18 @@ -253,6 +256,7 @@ struct mxt_data { bool update_input; u8 last_message_count; u8 num_touchids; + struct t7_config t7_cfg; /* Cached parameters from object table */ u16 T5_address; @@ -668,20 +672,6 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg) data->t6_status = status; } -static int mxt_write_object(struct mxt_data *data, - u8 type, u8 offset, u8 val) -{ - struct mxt_object *object; - u16 reg; - - object = mxt_get_object(data, type); - if (!object || offset >= mxt_obj_size(object)) - return -EINVAL; - - reg = object->start_address; - return mxt_write_reg(data->client, reg + offset, val); -} - static void mxt_input_button(struct mxt_data *data, u8 *message) { struct input_dev *input = data->input_dev; @@ -1712,6 +1702,60 @@ err_free_object_table: return error; } +static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) +{ + struct device *dev = &data->client->dev; + int error; + struct t7_config *new_config; + struct t7_config deepsleep = { .active = 0, .idle = 0 }; + + if (sleep == MXT_POWER_CFG_DEEPSLEEP) + new_config = &deepsleep; + else + new_config = &data->t7_cfg; + + error = __mxt_write_reg(data->client, data->T7_address, + sizeof(data->t7_cfg), new_config); + if (error) + return error; + + dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n", + new_config->active, new_config->idle); + + return 0; +} + +static int mxt_init_t7_power_cfg(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + int error; + bool retry = false; + +recheck: + error = __mxt_read_reg(data->client, data->T7_address, + sizeof(data->t7_cfg), &data->t7_cfg); + if (error) + return error; + + if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) { + if (!retry) { + dev_dbg(dev, "T7 cfg zero, resetting\n"); + mxt_soft_reset(data); + retry = true; + goto recheck; + } else { + dev_dbg(dev, "T7 cfg zero after reset, overriding\n"); + data->t7_cfg.active = 20; + data->t7_cfg.idle = 100; + return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + } + } + + dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n", + data->t7_cfg.active, data->t7_cfg.idle); + return 0; +} + static int mxt_configure_objects(struct mxt_data *data, const struct firmware *cfg) { @@ -1725,6 +1769,12 @@ static int mxt_configure_objects(struct mxt_data *data, dev_warn(dev, "Error %d updating config\n", error); } + error = mxt_init_t7_power_cfg(data); + if (error) { + dev_err(dev, "Failed to initialize power cfg\n"); + return error; + } + error = mxt_initialize_t9_input_device(data); if (error) return error; @@ -2001,16 +2051,15 @@ static const struct attribute_group mxt_attr_group = { static void mxt_start(struct mxt_data *data) { - /* Touch enable */ - mxt_write_object(data, - MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + + /* Recalibrate since chip has been in deep sleep */ + mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); } static void mxt_stop(struct mxt_data *data) { - /* Touch disable */ - mxt_write_object(data, - MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); } static int mxt_input_open(struct input_dev *dev) @@ -2175,8 +2224,6 @@ static int mxt_resume(struct device *dev) struct mxt_data *data = i2c_get_clientdata(client); struct input_dev *input_dev = data->input_dev; - mxt_soft_reset(data); - mutex_lock(&input_dev->mutex); if (input_dev->users)