Commit 7a53d609 authored by Nick Dyer's avatar Nick Dyer Committed by Dmitry Torokhov

Input: atmel_mxt_ts - move input device init into separate function

It is useful to initialise the input device later:
- Screen parameters may not be not known yet, for instance if waiting for
  firmware loader to return.
- Device may be in bootloader mode on probe (but could still be recovered by
  firmware download).

In addition, later devices have a different touchscreen object (T100) which
requires handling differently.

This also reduces the complexity of the probe function.
Signed-off-by: default avatarNick Dyer <nick.dyer@itdev.co.uk>
Acked-by: default avatarYufeng Shen <miletus@chromium.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent dd24dcf5
...@@ -1047,6 +1047,9 @@ static int mxt_get_object_table(struct mxt_data *data) ...@@ -1047,6 +1047,9 @@ static int mxt_get_object_table(struct mxt_data *data)
static void mxt_free_object_table(struct mxt_data *data) static void mxt_free_object_table(struct mxt_data *data)
{ {
input_unregister_device(data->input_dev);
data->input_dev = NULL;
kfree(data->object_table); kfree(data->object_table);
data->object_table = NULL; data->object_table = NULL;
data->T6_reportid = 0; data->T6_reportid = 0;
...@@ -1103,6 +1106,102 @@ static int mxt_read_t9_resolution(struct mxt_data *data) ...@@ -1103,6 +1106,102 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
return 0; return 0;
} }
static int mxt_input_open(struct input_dev *dev);
static void mxt_input_close(struct input_dev *dev);
static int mxt_initialize_t9_input_device(struct mxt_data *data)
{
struct device *dev = &data->client->dev;
const struct mxt_platform_data *pdata = data->pdata;
struct input_dev *input_dev;
int error;
unsigned int num_mt_slots;
unsigned int mt_flags = 0;
int i;
error = mxt_read_t9_resolution(data);
if (error)
dev_warn(dev, "Failed to initialize T9 resolution\n");
input_dev = input_allocate_device();
if (!input_dev) {
dev_err(dev, "Failed to allocate memory\n");
return -ENOMEM;
}
input_dev->name = "Atmel maXTouch Touchscreen";
input_dev->phys = data->phys;
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = dev;
input_dev->open = mxt_input_open;
input_dev->close = mxt_input_close;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
if (pdata->t19_num_keys) {
__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
for (i = 0; i < pdata->t19_num_keys; i++)
if (pdata->t19_keymap[i] != KEY_RESERVED)
input_set_capability(input_dev, EV_KEY,
pdata->t19_keymap[i]);
mt_flags |= INPUT_MT_POINTER;
input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_MT_POSITION_X,
MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
MXT_PIXELS_PER_MM);
input_dev->name = "Atmel maXTouch Touchpad";
}
/* For single touch */
input_set_abs_params(input_dev, ABS_X,
0, data->max_x, 0, 0);
input_set_abs_params(input_dev, ABS_Y,
0, data->max_y, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE,
0, 255, 0, 0);
/* For multi touch */
num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
if (error) {
dev_err(dev, "Error %d initialising slots\n", error);
goto err_free_mem;
}
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MXT_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, data->max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, data->max_y, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
0, 255, 0, 0);
input_set_drvdata(input_dev, data);
error = input_register_device(input_dev);
if (error) {
dev_err(dev, "Error %d registering input device\n", error);
goto err_free_mem;
}
data->input_dev = input_dev;
return 0;
err_free_mem:
input_free_device(input_dev);
return error;
}
static int mxt_initialize(struct mxt_data *data) static int mxt_initialize(struct mxt_data *data)
{ {
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
...@@ -1132,11 +1231,9 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -1132,11 +1231,9 @@ static int mxt_initialize(struct mxt_data *data)
goto err_free_object_table; goto err_free_object_table;
} }
error = mxt_read_t9_resolution(data); error = mxt_initialize_t9_input_device(data);
if (error) { if (error)
dev_err(&client->dev, "Failed to initialize T9 resolution\n");
goto err_free_object_table; goto err_free_object_table;
}
dev_info(&client->dev, dev_info(&client->dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
...@@ -1432,40 +1529,26 @@ static void mxt_input_close(struct input_dev *dev) ...@@ -1432,40 +1529,26 @@ static void mxt_input_close(struct input_dev *dev)
static int mxt_probe(struct i2c_client *client, static int mxt_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
struct mxt_data *data; struct mxt_data *data;
struct input_dev *input_dev; const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
int error; int error;
unsigned int num_mt_slots;
unsigned int mt_flags = 0;
int i;
if (!pdata) if (!pdata)
return -EINVAL; return -EINVAL;
data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
input_dev = input_allocate_device(); if (!data) {
if (!data || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n"); dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM; return -ENOMEM;
goto err_free_mem;
} }
input_dev->name = "Atmel maXTouch Touchscreen";
snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
client->adapter->nr, client->addr); client->adapter->nr, client->addr);
input_dev->phys = data->phys;
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->open = mxt_input_open;
input_dev->close = mxt_input_close;
data->client = client; data->client = client;
data->input_dev = input_dev;
data->pdata = pdata; data->pdata = pdata;
data->irq = client->irq; data->irq = client->irq;
i2c_set_clientdata(client, data);
init_completion(&data->bl_completion); init_completion(&data->bl_completion);
init_completion(&data->reset_completion); init_completion(&data->reset_completion);
...@@ -1481,84 +1564,24 @@ static int mxt_probe(struct i2c_client *client, ...@@ -1481,84 +1564,24 @@ static int mxt_probe(struct i2c_client *client,
disable_irq(client->irq); disable_irq(client->irq);
error = input_register_device(input_dev);
if (error) {
dev_err(&client->dev, "Error %d registering input device\n",
error);
goto err_free_irq;
}
error = mxt_initialize(data); error = mxt_initialize(data);
if (error) if (error)
goto err_unregister_device; goto err_free_irq;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
if (pdata->t19_num_keys) {
__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
for (i = 0; i < pdata->t19_num_keys; i++)
if (pdata->t19_keymap[i] != KEY_RESERVED)
input_set_capability(input_dev, EV_KEY,
pdata->t19_keymap[i]);
mt_flags |= INPUT_MT_POINTER;
input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_MT_POSITION_X,
MXT_PIXELS_PER_MM);
input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
MXT_PIXELS_PER_MM);
input_dev->name = "Atmel maXTouch Touchpad";
}
/* For single touch */
input_set_abs_params(input_dev, ABS_X,
0, data->max_x, 0, 0);
input_set_abs_params(input_dev, ABS_Y,
0, data->max_y, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE,
0, 255, 0, 0);
/* For multi touch */
num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
if (error)
goto err_free_object;
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MXT_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, data->max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, data->max_y, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
0, 255, 0, 0);
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
if (error) { if (error) {
dev_err(&client->dev, "Failure %d creating sysfs group\n", dev_err(&client->dev, "Failure %d creating sysfs group\n",
error); error);
goto err_unregister_device; goto err_free_object;
} }
return 0; return 0;
err_unregister_device:
input_unregister_device(input_dev);
input_dev = NULL;
err_free_object: err_free_object:
kfree(data->object_table); kfree(data->object_table);
err_free_irq: err_free_irq:
free_irq(client->irq, data); free_irq(client->irq, data);
err_free_mem: err_free_mem:
input_free_device(input_dev);
kfree(data); kfree(data);
return error; return error;
} }
......
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