Commit 9d469d03 authored by Nick Dyer's avatar Nick Dyer Committed by Dmitry Torokhov

Input: atmel_mxt_ts - use deep sleep mode when stopped

By writing zero to both the active and idle cycle times the maXTouch device
is put into a deep sleep mode when it consumes minimal power. It is
unnecessary to change the configuration of any other objects (for example
to disable T9 touchscreen).

It is counterproductive to reset the chip on resume, it will result in a
long delay. However it is necessary to issue a calibrate command after the
chip has spent any time in deep sleep.

This patch also deals with the situation where the power configuration is
zero on probe, which would mean that the device never wakes up to execute
commands.
Signed-off-by: default avatarNick Dyer <nick.dyer@itdev.co.uk>
Acked-by: default avatarBenson Leung <bleung@chromium.org>
Acked-by: default avatarYufeng Shen <miletus@chromium.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent f048615e
...@@ -99,9 +99,13 @@ ...@@ -99,9 +99,13 @@
#define MXT_T6_STATUS_COMSERR (1 << 2) #define MXT_T6_STATUS_COMSERR (1 << 2)
/* MXT_GEN_POWER_T7 field */ /* MXT_GEN_POWER_T7 field */
#define MXT_POWER_IDLEACQINT 0 struct t7_config {
#define MXT_POWER_ACTVACQINT 1 u8 idle;
#define MXT_POWER_ACTV2IDLETO 2 u8 active;
} __packed;
#define MXT_POWER_CFG_RUN 0
#define MXT_POWER_CFG_DEEPSLEEP 1
/* MXT_GEN_ACQUIRE_T8 field */ /* MXT_GEN_ACQUIRE_T8 field */
#define MXT_ACQUIRE_CHRGTIME 0 #define MXT_ACQUIRE_CHRGTIME 0
...@@ -113,7 +117,6 @@ ...@@ -113,7 +117,6 @@
#define MXT_ACQUIRE_ATCHCALSTHR 7 #define MXT_ACQUIRE_ATCHCALSTHR 7
/* MXT_TOUCH_MULTI_T9 field */ /* MXT_TOUCH_MULTI_T9 field */
#define MXT_TOUCH_CTRL 0
#define MXT_T9_ORIENT 9 #define MXT_T9_ORIENT 9
#define MXT_T9_RANGE 18 #define MXT_T9_RANGE 18
...@@ -253,6 +256,7 @@ struct mxt_data { ...@@ -253,6 +256,7 @@ struct mxt_data {
bool update_input; bool update_input;
u8 last_message_count; u8 last_message_count;
u8 num_touchids; u8 num_touchids;
struct t7_config t7_cfg;
/* Cached parameters from object table */ /* Cached parameters from object table */
u16 T5_address; u16 T5_address;
...@@ -668,20 +672,6 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg) ...@@ -668,20 +672,6 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
data->t6_status = status; 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) static void mxt_input_button(struct mxt_data *data, u8 *message)
{ {
struct input_dev *input = data->input_dev; struct input_dev *input = data->input_dev;
...@@ -1712,6 +1702,60 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -1712,6 +1702,60 @@ static int mxt_initialize(struct mxt_data *data)
return error; 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, static int mxt_configure_objects(struct mxt_data *data,
const struct firmware *cfg) const struct firmware *cfg)
{ {
...@@ -1725,6 +1769,12 @@ static int mxt_configure_objects(struct mxt_data *data, ...@@ -1725,6 +1769,12 @@ static int mxt_configure_objects(struct mxt_data *data,
dev_warn(dev, "Error %d updating config\n", error); 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); error = mxt_initialize_t9_input_device(data);
if (error) if (error)
return error; return error;
...@@ -2001,16 +2051,15 @@ static const struct attribute_group mxt_attr_group = { ...@@ -2001,16 +2051,15 @@ static const struct attribute_group mxt_attr_group = {
static void mxt_start(struct mxt_data *data) static void mxt_start(struct mxt_data *data)
{ {
/* Touch enable */ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
mxt_write_object(data,
MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); /* 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) static void mxt_stop(struct mxt_data *data)
{ {
/* Touch disable */ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
mxt_write_object(data,
MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
} }
static int mxt_input_open(struct input_dev *dev) static int mxt_input_open(struct input_dev *dev)
...@@ -2175,8 +2224,6 @@ static int mxt_resume(struct device *dev) ...@@ -2175,8 +2224,6 @@ static int mxt_resume(struct device *dev)
struct mxt_data *data = i2c_get_clientdata(client); struct mxt_data *data = i2c_get_clientdata(client);
struct input_dev *input_dev = data->input_dev; struct input_dev *input_dev = data->input_dev;
mxt_soft_reset(data);
mutex_lock(&input_dev->mutex); mutex_lock(&input_dev->mutex);
if (input_dev->users) if (input_dev->users)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment