From: Lars-Peter Clausen <lars@xxxxxxxxxx> On some platforms the adp5589 is used in GPIO only mode. On these platforms we do not want to register a input device, so make that optional and only create the input device if a keymap is supplied. Signed-off-by: Lars-Peter Clausen <lars@xxxxxxxxxx> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@xxxxxxxxxx> --- drivers/input/keyboard/adp5589-keys.c | 197 +++++++++++++++----------- 1 file changed, 111 insertions(+), 86 deletions(-) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 4f96a4a99e5b..08bfa8b213e8 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -495,10 +495,10 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, return n_unused; } -static int adp5589_gpio_add(struct adp5589_kpad *kpad) +static int adp5589_gpio_add(struct adp5589_kpad *kpad, + const struct adp5589_kpad_platform_data *pdata) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int i, error; @@ -550,10 +550,10 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad) return 0; } -static void adp5589_gpio_remove(struct adp5589_kpad *kpad) +static void adp5589_gpio_remove(struct adp5589_kpad *kpad, + const struct adp5589_kpad_platform_data *pdata) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int error; @@ -571,12 +571,14 @@ static void adp5589_gpio_remove(struct adp5589_kpad *kpad) gpiochip_remove(&kpad->gc); } #else -static inline int adp5589_gpio_add(struct adp5589_kpad *kpad) +static inline int adp5589_gpio_add(struct adp5589_kpad *kpad, + struct const adp5589_kpad_platform_data *pdata) { return 0; } -static inline void adp5589_gpio_remove(struct adp5589_kpad *kpad) +static inline void adp5589_gpio_remove(struct adp5589_kpad *kpad, + struct const adp5589_kpad_platform_data *pdata) { } #endif @@ -652,11 +654,10 @@ static int adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key) return -EINVAL; } -static int adp5589_setup(struct adp5589_kpad *kpad) +static int adp5589_setup(struct adp5589_kpad *kpad, + const struct adp5589_kpad_platform_data *pdata) { struct i2c_client *client = kpad->client; - const struct adp5589_kpad_platform_data *pdata = - dev_get_platdata(&client->dev); u8 (*reg) (u8) = kpad->var->reg; unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; unsigned char pull_mask = 0; @@ -857,70 +858,37 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad) input_sync(kpad->input); } -static int adp5589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid, + const struct adp5589_kpad_platform_data *pdata) { - struct adp5589_kpad *kpad; - const struct adp5589_kpad_platform_data *pdata = - dev_get_platdata(&client->dev); + struct i2c_client *client = kpad->client; struct input_dev *input; - unsigned int revid; - int ret, i; + unsigned int i; int error; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); - return -EIO; - } - - if (!pdata) { - dev_err(&client->dev, "no platform data?\n"); - return -EINVAL; - } - - kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); - if (!kpad) - return -ENOMEM; - - switch (id->driver_data) { - case ADP5585_02: - kpad->support_row5 = true; - /* fall through */ - case ADP5585_01: - kpad->is_adp5585 = true; - kpad->var = &const_adp5585; - break; - case ADP5589: - kpad->support_row5 = true; - kpad->var = &const_adp5589; - break; - } + if (pdata->keymapsize == 0) + return 0; if (!((pdata->keypad_en_mask & kpad->var->row_mask) && (pdata->keypad_en_mask >> kpad->var->col_shift)) || !pdata->keymap) { dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (pdata->keymapsize != kpad->var->keymapsize) { dev_err(&client->dev, "invalid keymapsize\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (!pdata->gpimap && pdata->gpimapsize) { dev_err(&client->dev, "invalid gpimap from pdata\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (pdata->gpimapsize > kpad->var->gpimapsize_max) { dev_err(&client->dev, "invalid gpimapsize\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } for (i = 0; i < pdata->gpimapsize; i++) { @@ -929,41 +897,27 @@ static int adp5589_probe(struct i2c_client *client, if (pin < kpad->var->gpi_pin_base || pin > kpad->var->gpi_pin_end) { dev_err(&client->dev, "invalid gpi pin data\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if ((1 << (pin - kpad->var->gpi_pin_row_base)) & pdata->keypad_en_mask) { dev_err(&client->dev, "invalid gpi row/col data\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } } if (!client->irq) { dev_err(&client->dev, "no IRQ?\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_free_mem; - } + if (!input) + return -ENOMEM; - kpad->client = client; kpad->input = input; - ret = adp5589_read(client, ADP5589_5_ID); - if (ret < 0) { - error = ret; - goto err_free_input; - } - - revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; - input->name = client->name; input->phys = "adp5589-keys/input0"; input->dev.parent = &client->dev; @@ -1015,30 +969,94 @@ static int adp5589_probe(struct i2c_client *client, goto err_unreg_dev; } - error = adp5589_setup(kpad); + device_init_wakeup(&client->dev, 1); + + return 0; + +err_unreg_dev: + input_unregister_device(input); + input = NULL; +err_free_input: + input_free_device(input); + + return error; +} + +static void adp5589_keypad_remove(struct adp5589_kpad *kpad, + const struct adp5589_kpad_platform_data *pdata) +{ + if (!kpad->input) + return; + + free_irq(kpad->client->irq, kpad); + input_unregister_device(kpad->input); +} + +static int adp5589_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adp5589_kpad *kpad; + const struct adp5589_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); + unsigned int revid; + int error, ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + + kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); + if (!kpad) + return -ENOMEM; + + kpad->client = client; + + switch (id->driver_data) { + case ADP5585_02: + kpad->support_row5 = true; + case ADP5585_01: + kpad->is_adp5585 = true; + kpad->var = &const_adp5585; + break; + case ADP5589: + kpad->support_row5 = true; + kpad->var = &const_adp5589; + break; + } + + ret = adp5589_read(client, ADP5589_5_ID); + if (ret < 0) { + error = ret; + goto err_free_mem; + } + + revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; + + error = adp5589_keypad_add(kpad, revid, pdata); if (error) - goto err_free_irq; + goto err_free_mem; + + error = adp5589_setup(kpad, pdata); + if (error) + goto err_keypad_remove; if (kpad->gpimapsize) adp5589_report_switch_state(kpad); - error = adp5589_gpio_add(kpad); + error = adp5589_gpio_add(kpad, pdata); if (error) - goto err_free_irq; + goto err_keypad_remove; - device_init_wakeup(&client->dev, 1); i2c_set_clientdata(client, kpad); dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); return 0; -err_free_irq: - free_irq(client->irq, kpad); -err_unreg_dev: - input_unregister_device(input); - input = NULL; -err_free_input: - input_free_device(input); +err_keypad_remove: + adp5589_keypad_remove(kpad, pdata); err_free_mem: kfree(kpad); @@ -1048,11 +1066,12 @@ static int adp5589_probe(struct i2c_client *client, static int adp5589_remove(struct i2c_client *client) { struct adp5589_kpad *kpad = i2c_get_clientdata(client); + const struct adp5589_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); - free_irq(client->irq, kpad); - input_unregister_device(kpad->input); - adp5589_gpio_remove(kpad); + adp5589_keypad_remove(kpad, pdata); + adp5589_gpio_remove(kpad, pdata); kfree(kpad); return 0; @@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev) struct adp5589_kpad *kpad = dev_get_drvdata(dev); struct i2c_client *client = kpad->client; + if (!kpad->input) + return 0; + disable_irq(client->irq); if (device_may_wakeup(&client->dev)) @@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev) struct adp5589_kpad *kpad = dev_get_drvdata(dev); struct i2c_client *client = kpad->client; + if (!kpad->input) + return 0; + if (device_may_wakeup(&client->dev)) disable_irq_wake(client->irq); -- 2.20.1