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: Nick Dyer <nick.dyer@itdev.co.uk>
Acked-by: Yufeng Shen <miletus@chromium.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
Nick Dyer 2014-07-23 12:21:26 -07:00 committed by Dmitry Torokhov
parent dd24dcf566
commit 7a53d60926
1 changed files with 107 additions and 84 deletions

View File

@ -1047,6 +1047,9 @@ static int mxt_get_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);
data->object_table = NULL;
data->T6_reportid = 0;
@ -1103,6 +1106,102 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
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)
{
struct i2c_client *client = data->client;
@ -1132,11 +1231,9 @@ static int mxt_initialize(struct mxt_data *data)
goto err_free_object_table;
}
error = mxt_read_t9_resolution(data);
if (error) {
dev_err(&client->dev, "Failed to initialize T9 resolution\n");
error = mxt_initialize_t9_input_device(data);
if (error)
goto err_free_object_table;
}
dev_info(&client->dev,
"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)
static int mxt_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
struct mxt_data *data;
struct input_dev *input_dev;
const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
int error;
unsigned int num_mt_slots;
unsigned int mt_flags = 0;
int i;
if (!pdata)
return -EINVAL;
data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
input_dev = input_allocate_device();
if (!data || !input_dev) {
if (!data) {
dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM;
goto err_free_mem;
return -ENOMEM;
}
input_dev->name = "Atmel maXTouch Touchscreen";
snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
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->input_dev = input_dev;
data->pdata = pdata;
data->irq = client->irq;
i2c_set_clientdata(client, data);
init_completion(&data->bl_completion);
init_completion(&data->reset_completion);
@ -1481,84 +1564,24 @@ static int mxt_probe(struct i2c_client *client,
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);
if (error)
goto err_unregister_device;
__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);
goto err_free_irq;
error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
if (error) {
dev_err(&client->dev, "Failure %d creating sysfs group\n",
error);
goto err_unregister_device;
goto err_free_object;
}
return 0;
err_unregister_device:
input_unregister_device(input_dev);
input_dev = NULL;
err_free_object:
kfree(data->object_table);
err_free_irq:
free_irq(client->irq, data);
err_free_mem:
input_free_device(input_dev);
kfree(data);
return error;
}