Input: adp5589 - make keypad support optional
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@metafoo.de> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com> Link: https://lore.kernel.org/r/20191023070541.13940-1-alexandru.ardelean@analog.com [dtor: dropped unnecessary changes related to passing pdata to various functions] Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
ee1b4b2e7c
commit
cb3efd5a38
|
@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
|
||||||
input_sync(kpad->input);
|
input_sync(kpad->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adp5589_probe(struct i2c_client *client,
|
static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
struct adp5589_kpad *kpad;
|
struct i2c_client *client = kpad->client;
|
||||||
const struct adp5589_kpad_platform_data *pdata =
|
const struct adp5589_kpad_platform_data *pdata =
|
||||||
dev_get_platdata(&client->dev);
|
dev_get_platdata(&client->dev);
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
unsigned int revid;
|
unsigned int i;
|
||||||
int ret, i;
|
|
||||||
int error;
|
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->keypad_en_mask & kpad->var->row_mask) &&
|
if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
|
||||||
(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
|
(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
|
||||||
!pdata->keymap) {
|
!pdata->keymap) {
|
||||||
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
|
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->keymapsize != kpad->var->keymapsize) {
|
if (pdata->keymapsize != kpad->var->keymapsize) {
|
||||||
dev_err(&client->dev, "invalid keymapsize\n");
|
dev_err(&client->dev, "invalid keymapsize\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pdata->gpimap && pdata->gpimapsize) {
|
if (!pdata->gpimap && pdata->gpimapsize) {
|
||||||
dev_err(&client->dev, "invalid gpimap from pdata\n");
|
dev_err(&client->dev, "invalid gpimap from pdata\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
|
if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
|
||||||
dev_err(&client->dev, "invalid gpimapsize\n");
|
dev_err(&client->dev, "invalid gpimapsize\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < pdata->gpimapsize; i++) {
|
for (i = 0; i < pdata->gpimapsize; i++) {
|
||||||
|
@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client,
|
||||||
if (pin < kpad->var->gpi_pin_base ||
|
if (pin < kpad->var->gpi_pin_base ||
|
||||||
pin > kpad->var->gpi_pin_end) {
|
pin > kpad->var->gpi_pin_end) {
|
||||||
dev_err(&client->dev, "invalid gpi pin data\n");
|
dev_err(&client->dev, "invalid gpi pin data\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
|
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
|
||||||
pdata->keypad_en_mask) {
|
pdata->keypad_en_mask) {
|
||||||
dev_err(&client->dev, "invalid gpi row/col data\n");
|
dev_err(&client->dev, "invalid gpi row/col data\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client->irq) {
|
if (!client->irq) {
|
||||||
dev_err(&client->dev, "no IRQ?\n");
|
dev_err(&client->dev, "no IRQ?\n");
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input = input_allocate_device();
|
input = input_allocate_device();
|
||||||
if (!input) {
|
if (!input)
|
||||||
error = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err_free_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
kpad->client = client;
|
|
||||||
kpad->input = input;
|
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->name = client->name;
|
||||||
input->phys = "adp5589-keys/input0";
|
input->phys = "adp5589-keys/input0";
|
||||||
input->dev.parent = &client->dev;
|
input->dev.parent = &client->dev;
|
||||||
|
@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
|
||||||
goto err_unreg_dev;
|
goto err_unreg_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (kpad->input) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(&client->dev, "no platform data?\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
|
||||||
|
if (!kpad)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
kpad->client = client;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = adp5589_read(client, ADP5589_5_ID);
|
||||||
|
if (ret < 0) {
|
||||||
|
error = ret;
|
||||||
|
goto err_free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
|
||||||
|
|
||||||
|
if (pdata->keymapsize) {
|
||||||
|
error = adp5589_keypad_add(kpad, revid);
|
||||||
|
if (error)
|
||||||
|
goto err_free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
error = adp5589_setup(kpad);
|
error = adp5589_setup(kpad);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_free_irq;
|
goto err_keypad_remove;
|
||||||
|
|
||||||
if (kpad->gpimapsize)
|
if (kpad->gpimapsize)
|
||||||
adp5589_report_switch_state(kpad);
|
adp5589_report_switch_state(kpad);
|
||||||
|
|
||||||
error = adp5589_gpio_add(kpad);
|
error = adp5589_gpio_add(kpad);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_free_irq;
|
goto err_keypad_remove;
|
||||||
|
|
||||||
device_init_wakeup(&client->dev, 1);
|
|
||||||
i2c_set_clientdata(client, kpad);
|
i2c_set_clientdata(client, kpad);
|
||||||
|
|
||||||
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free_irq:
|
err_keypad_remove:
|
||||||
free_irq(client->irq, kpad);
|
adp5589_keypad_remove(kpad);
|
||||||
err_unreg_dev:
|
|
||||||
input_unregister_device(input);
|
|
||||||
input = NULL;
|
|
||||||
err_free_input:
|
|
||||||
input_free_device(input);
|
|
||||||
err_free_mem:
|
err_free_mem:
|
||||||
kfree(kpad);
|
kfree(kpad);
|
||||||
|
|
||||||
|
@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
|
||||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||||
|
|
||||||
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||||
free_irq(client->irq, kpad);
|
adp5589_keypad_remove(kpad);
|
||||||
input_unregister_device(kpad->input);
|
|
||||||
adp5589_gpio_remove(kpad);
|
adp5589_gpio_remove(kpad);
|
||||||
kfree(kpad);
|
kfree(kpad);
|
||||||
|
|
||||||
|
@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
|
||||||
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||||
struct i2c_client *client = kpad->client;
|
struct i2c_client *client = kpad->client;
|
||||||
|
|
||||||
|
if (!kpad->input)
|
||||||
|
return 0;
|
||||||
|
|
||||||
disable_irq(client->irq);
|
disable_irq(client->irq);
|
||||||
|
|
||||||
if (device_may_wakeup(&client->dev))
|
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 adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||||
struct i2c_client *client = kpad->client;
|
struct i2c_client *client = kpad->client;
|
||||||
|
|
||||||
|
if (!kpad->input)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (device_may_wakeup(&client->dev))
|
if (device_may_wakeup(&client->dev))
|
||||||
disable_irq_wake(client->irq);
|
disable_irq_wake(client->irq);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue