Input: atmel_mxt_ts - move input device init into separate function
authorNick Dyer <nick.dyer@itdev.co.uk>
Wed, 23 Jul 2014 19:21:26 +0000 (12:21 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 23 Jul 2014 20:25:10 +0000 (13:25 -0700)
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>
drivers/input/touchscreen/atmel_mxt_ts.c

index 02c374d529675d82b9ee3b6197385644f364bcc2..a248414642d91873e09faed15f2feacdd61a1e26 100644 (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;
 }