diff options
Diffstat (limited to 'drivers/input/keyboard')
30 files changed, 493 insertions, 202 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index cbd75cf44739..97acd6524ad7 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -666,6 +666,17 @@ config KEYBOARD_TC3589X To compile this driver as a module, choose M here: the module will be called tc3589x-keypad. +config KEYBOARD_TM2_TOUCHKEY + tristate "TM2 touchkey support" + depends on I2C + depends on LEDS_CLASS + help + Say Y here to enable device driver for tm2-touchkey with + LED control for the Exynos5433 TM2 board. + + To compile this driver as a module, choose M here. + module will be called tm2-touchkey. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index d9f4cfcf3410..7d9acff819a7 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o +obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c index f8cf2ccacefd..c255af21e71a 100644 --- a/drivers/input/keyboard/adc-keys.c +++ b/drivers/input/keyboard/adc-keys.c @@ -148,8 +148,6 @@ static int adc_keys_probe(struct platform_device *pdev) if (error) return error; - platform_set_drvdata(pdev, st); - poll_dev = devm_input_allocate_polled_device(dev); if (!poll_dev) { dev_err(dev, "failed to allocate input device\n"); diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index db1004dad108..f0b9b37bde58 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -107,8 +107,6 @@ static int adp5520_keys_probe(struct platform_device *pdev) input->phys = "adp5520-keys/input0"; input->dev.parent = &pdev->dev; - input_set_drvdata(input, dev); - input->id.bustype = BUS_I2C; input->id.vendor = 0x0001; input->id.product = 0x5520; diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c index 86a8b723ae15..e1cf63ee148f 100644 --- a/drivers/input/keyboard/bcm-keypad.c +++ b/drivers/input/keyboard/bcm-keypad.c @@ -213,7 +213,7 @@ static int bcm_kp_matrix_key_parse_dt(struct bcm_kp *kp) /* Initialize the KPCR Keypad Configuration Register */ kp->kpcr = KPCR_STATUSFILTERENABLE | KPCR_COLFILTERENABLE; - error = matrix_keypad_parse_of_params(dev, &kp->n_rows, &kp->n_cols); + error = matrix_keypad_parse_properties(dev, &kp->n_rows, &kp->n_cols); if (error) { dev_err(dev, "failed to parse kp params\n"); return error; @@ -352,8 +352,6 @@ static int bcm_kp_probe(struct platform_device *pdev) kp->input_dev = input_dev; - platform_set_drvdata(pdev, kp); - error = bcm_kp_matrix_key_parse_dt(kp); if (error) return error; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 81b07dddae86..39bcbc38997f 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -268,8 +268,6 @@ static int bfin_kpad_probe(struct platform_device *pdev) input->phys = "bf54x-keys/input0"; input->dev.parent = &pdev->dev; - input_set_drvdata(input, bf54x_kpad); - input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 4401be225d64..1a1eacae3ea1 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -392,7 +392,6 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client, return error; dev_info(dev, "CAP11XX detected, revision 0x%02x\n", rev); - i2c_set_clientdata(i2c_client, priv); node = dev->of_node; if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) { diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 604c7ade8df2..6a250d65f8fe 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -535,7 +535,7 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) const char *phys; int err; - err = matrix_keypad_parse_of_params(dev, &ckdev->rows, &ckdev->cols); + err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols); if (err) return err; diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index f363d1d2907a..b20a5d044caa 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -172,7 +172,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev) struct input_dev *key_dev; struct resource *res, *mem; struct device *dev = &pdev->dev; - struct davinci_ks_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct davinci_ks_platform_data *pdata = dev_get_platdata(dev); int error, i; if (pdata->device_enable) { @@ -255,7 +255,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev) key_dev->name = "davinci_keyscan"; key_dev->phys = "davinci_keyscan/input0"; - key_dev->dev.parent = &pdev->dev; + key_dev->dev.parent = dev; key_dev->id.bustype = BUS_HOST; key_dev->id.vendor = 0x0001; key_dev->id.product = 0x0001; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 582462d0af75..9c92cdf196e3 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -36,6 +36,8 @@ struct gpio_button_data { struct input_dev *input; struct gpio_desc *gpiod; + unsigned short *code; + struct timer_list release_timer; unsigned int release_delay; /* in msecs, for IRQ-only buttons */ @@ -52,6 +54,7 @@ struct gpio_keys_drvdata { const struct gpio_keys_platform_data *pdata; struct input_dev *input; struct mutex disable_lock; + unsigned short *keymap; struct gpio_button_data data[0]; }; @@ -203,7 +206,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, if (only_disabled && !bdata->disabled) continue; - __set_bit(bdata->button->code, bits); + __set_bit(*bdata->code, bits); } ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); @@ -254,7 +257,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, if (bdata->button->type != type) continue; - if (test_bit(bdata->button->code, bits) && + if (test_bit(*bdata->code, bits) && !bdata->button->can_disable) { error = -EINVAL; goto out; @@ -269,7 +272,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, if (bdata->button->type != type) continue; - if (test_bit(bdata->button->code, bits)) + if (test_bit(*bdata->code, bits)) gpio_keys_disable_button(bdata); else gpio_keys_enable_button(bdata); @@ -371,7 +374,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) if (state) input_event(input, type, button->code, button->value); } else { - input_event(input, type, button->code, state); + input_event(input, type, *bdata->code, state); } input_sync(input); } @@ -411,7 +414,7 @@ static void gpio_keys_irq_timer(unsigned long _data) spin_lock_irqsave(&bdata->lock, flags); if (bdata->key_pressed) { - input_event(input, EV_KEY, bdata->button->code, 0); + input_event(input, EV_KEY, *bdata->code, 0); input_sync(input); bdata->key_pressed = false; } @@ -421,7 +424,6 @@ static void gpio_keys_irq_timer(unsigned long _data) static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; - const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned long flags; @@ -433,11 +435,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) if (bdata->button->wakeup) pm_wakeup_event(bdata->input->dev.parent, 0); - input_event(input, EV_KEY, button->code, 1); + input_event(input, EV_KEY, *bdata->code, 1); input_sync(input); if (!bdata->release_delay) { - input_event(input, EV_KEY, button->code, 0); + input_event(input, EV_KEY, *bdata->code, 0); input_sync(input); goto out; } @@ -465,12 +467,14 @@ static void gpio_keys_quiesce_key(void *data) static int gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, - struct gpio_button_data *bdata, + struct gpio_keys_drvdata *ddata, const struct gpio_keys_button *button, + int idx, struct fwnode_handle *child) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; + struct gpio_button_data *bdata = &ddata->data[idx]; irq_handler_t isr; unsigned long irqflags; int irq; @@ -514,8 +518,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, if (button->active_low) flags |= GPIOF_ACTIVE_LOW; - error = devm_gpio_request_one(&pdev->dev, button->gpio, flags, - desc); + error = devm_gpio_request_one(dev, button->gpio, flags, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); @@ -577,16 +580,17 @@ static int gpio_keys_setup_key(struct platform_device *pdev, irqflags = 0; } - input_set_capability(input, button->type ?: EV_KEY, button->code); + bdata->code = &ddata->keymap[idx]; + *bdata->code = button->code; + input_set_capability(input, button->type ?: EV_KEY, *bdata->code); /* * Install custom action to cancel release timer and * workqueue item. */ - error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); + error = devm_add_action(dev, gpio_keys_quiesce_key, bdata); if (error) { - dev_err(&pdev->dev, - "failed to register quiesce action, error: %d\n", + dev_err(dev, "failed to register quiesce action, error: %d\n", error); return error; } @@ -598,8 +602,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, if (!button->can_disable) irqflags |= IRQF_SHARED; - error = devm_request_any_context_irq(&pdev->dev, bdata->irq, - isr, irqflags, desc, bdata); + error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags, + desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); @@ -750,6 +754,12 @@ static int gpio_keys_probe(struct platform_device *pdev) return -ENOMEM; } + ddata->keymap = devm_kcalloc(dev, + pdata->nbuttons, sizeof(ddata->keymap[0]), + GFP_KERNEL); + if (!ddata->keymap) + return -ENOMEM; + input = devm_input_allocate_device(dev); if (!input) { dev_err(dev, "failed to allocate input device\n"); @@ -765,7 +775,7 @@ static int gpio_keys_probe(struct platform_device *pdev) input->name = pdata->name ? : pdev->name; input->phys = "gpio-keys/input0"; - input->dev.parent = &pdev->dev; + input->dev.parent = dev; input->open = gpio_keys_open; input->close = gpio_keys_close; @@ -774,25 +784,29 @@ static int gpio_keys_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0100; + input->keycode = ddata->keymap; + input->keycodesize = sizeof(ddata->keymap[0]); + input->keycodemax = pdata->nbuttons; + /* Enable auto repeat feature of Linux input subsystem */ if (pdata->rep) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { const struct gpio_keys_button *button = &pdata->buttons[i]; - struct gpio_button_data *bdata = &ddata->data[i]; if (!dev_get_platdata(dev)) { - child = device_get_next_child_node(&pdev->dev, child); + child = device_get_next_child_node(dev, child); if (!child) { - dev_err(&pdev->dev, + dev_err(dev, "missing child device node for entry %d\n", i); return -EINVAL; } } - error = gpio_keys_setup_key(pdev, input, bdata, button, child); + error = gpio_keys_setup_key(pdev, input, ddata, + button, i, child); if (error) { fwnode_handle_put(child); return error; @@ -804,7 +818,7 @@ static int gpio_keys_probe(struct platform_device *pdev) fwnode_handle_put(child); - error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); + error = sysfs_create_group(&dev->kobj, &gpio_keys_attr_group); if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); @@ -818,12 +832,12 @@ static int gpio_keys_probe(struct platform_device *pdev) goto err_remove_group; } - device_init_wakeup(&pdev->dev, wakeup); + device_init_wakeup(dev, wakeup); return 0; err_remove_group: - sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); + sysfs_remove_group(&dev->kobj, &gpio_keys_attr_group); return error; } @@ -831,8 +845,6 @@ static int gpio_keys_remove(struct platform_device *pdev) { sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); - device_init_wakeup(&pdev->dev, 0); - return 0; } diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index bed4f2086158..4fce43a6a0e0 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -252,13 +252,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) size = sizeof(struct gpio_keys_polled_dev) + pdata->nbuttons * sizeof(struct gpio_keys_button_data); - bdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + bdev = devm_kzalloc(dev, size, GFP_KERNEL); if (!bdev) { dev_err(dev, "no memory for private data\n"); return -ENOMEM; } - poll_dev = devm_input_allocate_polled_device(&pdev->dev); + poll_dev = devm_input_allocate_polled_device(dev); if (!poll_dev) { dev_err(dev, "no memory for polled device\n"); return -ENOMEM; @@ -332,7 +332,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) if (button->active_low) flags |= GPIOF_ACTIVE_LOW; - error = devm_gpio_request_one(&pdev->dev, button->gpio, + error = devm_gpio_request_one(dev, button->gpio, flags, button->desc ? : DRV_NAME); if (error) { dev_err(dev, @@ -365,7 +365,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) bdev->poll_dev = poll_dev; bdev->dev = dev; bdev->pdata = pdata; - platform_set_drvdata(pdev, bdev); error = input_register_polled_device(poll_dev); if (error) { diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 80c81278ad2c..0116ac99f44c 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -197,8 +197,6 @@ static int jornada680kbd_probe(struct platform_device *pdev) return -ENOMEM; } - platform_set_drvdata(pdev, jornadakbd); - jornadakbd->poll_dev = poll_dev; memcpy(jornadakbd->keymap, jornada_scancodes, diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index 632523d4f5dc..1dd57ac0e7a2 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -145,7 +145,7 @@ static int lpc32xx_parse_dt(struct device *dev, u32 rows = 0, columns = 0; int err; - err = matrix_keypad_parse_of_params(dev, &rows, &columns); + err = matrix_keypad_parse_properties(dev, &rows, &columns); if (err) return err; if (rows != columns) { diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index 5aa2361aef95..78e3567ec18c 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c @@ -196,7 +196,6 @@ static int probe_maple_kbd(struct device *dev) __clear_bit(KEY_RESERVED, idev->keybit); input_set_capability(idev, EV_MSC, MSC_SCAN); - input_set_drvdata(idev, kbd); error = input_register_device(idev); if (error) diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 7f12b6579f82..18839cd5f76e 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -545,8 +545,6 @@ static int matrix_keypad_remove(struct platform_device *pdev) { struct matrix_keypad *keypad = platform_get_drvdata(pdev); - device_init_wakeup(&pdev->dev, 0); - matrix_keypad_free_gpio(keypad); input_unregister_device(keypad->input_dev); kfree(keypad); diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 5091133b7b8e..cd44d22d8770 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -241,7 +241,6 @@ static int max7359_probe(struct i2c_client *client, /* Initialize MAX7359 */ max7359_initialize(client); - i2c_set_clientdata(client, keypad); device_init_wakeup(&client->dev, 1); return 0; diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 0fd612dd76ed..884a74d8a7ed 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -12,14 +12,16 @@ * */ -#include <linux/module.h> -#include <linux/input.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/delay.h> #include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/input.h> #include <linux/interrupt.h> -#include <linux/i2c/mpr121_touchkey.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/property.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> /* Register definitions */ #define ELE_TOUCH_STATUS_0_ADDR 0x0 @@ -59,10 +61,9 @@ struct mpr121_touchkey { struct i2c_client *client; struct input_dev *input_dev; - unsigned int key_val; unsigned int statusbits; unsigned int keycount; - u16 keycodes[MPR121_MAX_KEY_COUNT]; + u32 keycodes[MPR121_MAX_KEY_COUNT]; }; struct mpr121_init_register { @@ -82,12 +83,49 @@ static const struct mpr121_init_register init_reg_table[] = { { AUTO_CONFIG_CTRL_ADDR, 0x0b }, }; +static void mpr121_vdd_supply_disable(void *data) +{ + struct regulator *vdd_supply = data; + + regulator_disable(vdd_supply); +} + +static struct regulator *mpr121_vdd_supply_init(struct device *dev) +{ + struct regulator *vdd_supply; + int err; + + vdd_supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(vdd_supply)) { + dev_err(dev, "failed to get vdd regulator: %ld\n", + PTR_ERR(vdd_supply)); + return vdd_supply; + } + + err = regulator_enable(vdd_supply); + if (err) { + dev_err(dev, "failed to enable vdd regulator: %d\n", err); + return ERR_PTR(err); + } + + err = devm_add_action(dev, mpr121_vdd_supply_disable, vdd_supply); + if (err) { + regulator_disable(vdd_supply); + dev_err(dev, "failed to add disable regulator action: %d\n", + err); + return ERR_PTR(err); + } + + return vdd_supply; +} + static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) { struct mpr121_touchkey *mpr121 = dev_id; struct i2c_client *client = mpr121->client; struct input_dev *input = mpr121->input_dev; - unsigned int key_num, key_val, pressed; + unsigned long bit_changed; + unsigned int key_num; int reg; reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); @@ -105,26 +143,29 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) reg &= TOUCH_STATUS_MASK; /* use old press bit to figure out which bit changed */ - key_num = ffs(reg ^ mpr121->statusbits) - 1; - pressed = reg & (1 << key_num); + bit_changed = reg ^ mpr121->statusbits; mpr121->statusbits = reg; + for_each_set_bit(key_num, &bit_changed, mpr121->keycount) { + unsigned int key_val, pressed; - key_val = mpr121->keycodes[key_num]; + pressed = reg & BIT(key_num); + key_val = mpr121->keycodes[key_num]; - input_event(input, EV_MSC, MSC_SCAN, key_num); - input_report_key(input, key_val, pressed); - input_sync(input); + input_event(input, EV_MSC, MSC_SCAN, key_num); + input_report_key(input, key_val, pressed); - dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, - pressed ? "pressed" : "released"); + dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, + pressed ? "pressed" : "released"); + + } + input_sync(input); out: return IRQ_HANDLED; } -static int mpr121_phys_init(const struct mpr121_platform_data *pdata, - struct mpr121_touchkey *mpr121, - struct i2c_client *client) +static int mpr121_phys_init(struct mpr121_touchkey *mpr121, + struct i2c_client *client, int vdd_uv) { const struct mpr121_init_register *reg; unsigned char usl, lsl, tl, eleconf; @@ -154,9 +195,9 @@ static int mpr121_phys_init(const struct mpr121_platform_data *pdata, /* * Capacitance on sensing input varies and needs to be compensated. * The internal MPR121-auto-configuration can do this if it's - * registers are set properly (based on pdata->vdd_uv). + * registers are set properly (based on vdd_uv). */ - vdd = pdata->vdd_uv / 1000; + vdd = vdd_uv / 1000; usl = ((vdd - 700) * 256) / vdd; lsl = (usl * 65) / 100; tl = (usl * 90) / 100; @@ -187,72 +228,77 @@ err_i2c_write: static int mpr_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct mpr121_platform_data *pdata = - dev_get_platdata(&client->dev); + struct device *dev = &client->dev; + struct regulator *vdd_supply; + int vdd_uv; struct mpr121_touchkey *mpr121; struct input_dev *input_dev; int error; int i; - if (!pdata) { - dev_err(&client->dev, "no platform data defined\n"); - return -EINVAL; - } - - if (!pdata->keymap || !pdata->keymap_size) { - dev_err(&client->dev, "missing keymap data\n"); + if (!client->irq) { + dev_err(dev, "irq number should not be zero\n"); return -EINVAL; } - if (pdata->keymap_size > MPR121_MAX_KEY_COUNT) { - dev_err(&client->dev, "too many keys defined\n"); - return -EINVAL; - } + vdd_supply = mpr121_vdd_supply_init(dev); + if (IS_ERR(vdd_supply)) + return PTR_ERR(vdd_supply); - if (!client->irq) { - dev_err(&client->dev, "irq number should not be zero\n"); - return -EINVAL; - } + vdd_uv = regulator_get_voltage(vdd_supply); - mpr121 = devm_kzalloc(&client->dev, sizeof(*mpr121), - GFP_KERNEL); + mpr121 = devm_kzalloc(dev, sizeof(*mpr121), GFP_KERNEL); if (!mpr121) return -ENOMEM; - input_dev = devm_input_allocate_device(&client->dev); + input_dev = devm_input_allocate_device(dev); if (!input_dev) return -ENOMEM; mpr121->client = client; mpr121->input_dev = input_dev; - mpr121->keycount = pdata->keymap_size; + mpr121->keycount = device_property_read_u32_array(dev, "linux,keycodes", + NULL, 0); + if (mpr121->keycount > MPR121_MAX_KEY_COUNT) { + dev_err(dev, "too many keys defined (%d)\n", mpr121->keycount); + return -EINVAL; + } + + error = device_property_read_u32_array(dev, "linux,keycodes", + mpr121->keycodes, + mpr121->keycount); + if (error) { + dev_err(dev, + "failed to read linux,keycode property: %d\n", error); + return error; + } input_dev->name = "Freescale MPR121 Touchkey"; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_dev->dev.parent = dev; + if (device_property_read_bool(dev, "autorepeat")) + __set_bit(EV_REP, input_dev->evbit); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_dev->keycode = mpr121->keycodes; input_dev->keycodesize = sizeof(mpr121->keycodes[0]); input_dev->keycodemax = mpr121->keycount; - for (i = 0; i < pdata->keymap_size; i++) { - input_set_capability(input_dev, EV_KEY, pdata->keymap[i]); - mpr121->keycodes[i] = pdata->keymap[i]; - } + for (i = 0; i < mpr121->keycount; i++) + input_set_capability(input_dev, EV_KEY, mpr121->keycodes[i]); - error = mpr121_phys_init(pdata, mpr121, client); + error = mpr121_phys_init(mpr121, client, vdd_uv); if (error) { - dev_err(&client->dev, "Failed to init register\n"); + dev_err(dev, "Failed to init register\n"); return error; } - error = devm_request_threaded_irq(&client->dev, client->irq, NULL, - mpr_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, mpr121); + error = devm_request_threaded_irq(dev, client->irq, NULL, + mpr_touchkey_interrupt, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev->driver->name, mpr121); if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); + dev_err(dev, "Failed to register interrupt\n"); return error; } @@ -261,13 +307,13 @@ static int mpr_touchkey_probe(struct i2c_client *client, return error; i2c_set_clientdata(client, mpr121); - device_init_wakeup(&client->dev, pdata->wakeup); + device_init_wakeup(dev, + device_property_read_bool(dev, "wakeup-source")); return 0; } -#ifdef CONFIG_PM_SLEEP -static int mpr_suspend(struct device *dev) +static int __maybe_unused mpr_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -279,7 +325,7 @@ static int mpr_suspend(struct device *dev) return 0; } -static int mpr_resume(struct device *dev) +static int __maybe_unused mpr_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client); @@ -292,7 +338,6 @@ static int mpr_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume); @@ -302,10 +347,19 @@ static const struct i2c_device_id mpr121_id[] = { }; MODULE_DEVICE_TABLE(i2c, mpr121_id); +#ifdef CONFIG_OF +static const struct of_device_id mpr121_touchkey_dt_match_table[] = { + { .compatible = "fsl,mpr121-touchkey" }, + { }, +}; +MODULE_DEVICE_TABLE(of, mpr121_touchkey_dt_match_table); +#endif + static struct i2c_driver mpr_touchkey_driver = { .driver = { .name = "mpr121", .pm = &mpr121_touchkey_pm_ops, + .of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table), }, .id_table = mpr121_id, .probe = mpr_touchkey_probe, diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index 7abfd34eb87e..c7f26fa3034c 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -249,8 +249,6 @@ static int nspire_keypad_probe(struct platform_device *pdev) return error; } - platform_set_drvdata(pdev, keypad); - dev_dbg(&pdev->dev, "TI-NSPIRE keypad at %pR (scan_interval=%uus, row_delay=%uus%s)\n", res, keypad->row_delay, keypad->scan_interval, diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 6639b2b8528a..ebc67ba41fe2 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -223,8 +223,8 @@ static int omap4_keypad_parse_dt(struct device *dev, struct device_node *np = dev->of_node; int err; - err = matrix_keypad_parse_of_params(dev, &keypad_data->rows, - &keypad_data->cols); + err = matrix_keypad_parse_properties(dev, &keypad_data->rows, + &keypad_data->cols); if (err) return err; @@ -375,7 +375,6 @@ static int omap4_keypad_probe(struct platform_device *pdev) err_pm_disable: pm_runtime_disable(&pdev->dev); - device_init_wakeup(&pdev->dev, false); free_irq(keypad_data->irq, keypad_data); err_free_keymap: kfree(keypad_data->keymap); @@ -401,8 +400,6 @@ static int omap4_keypad_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - device_init_wakeup(&pdev->dev, false); - input_unregister_device(keypad_data->input); iounmap(keypad_data->base); diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index f8502bb29176..d62b4068c077 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -75,8 +75,6 @@ static int opencores_kbd_probe(struct platform_device *pdev) input->name = pdev->name; input->phys = "opencores-kbd/input0"; - input_set_drvdata(input, opencores_kbd); - input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; @@ -112,8 +110,6 @@ static int opencores_kbd_probe(struct platform_device *pdev) return error; } - platform_set_drvdata(pdev, opencores_kbd); - return 0; } diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 5c68e3f096bc..97c5424f49b9 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -515,7 +515,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) int rc; unsigned int ctrl_val; - rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); + rc = matrix_keypad_parse_properties(&pdev->dev, &rows, &cols); if (rc) return rc; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index e24443376e75..3841fa30db33 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -126,7 +126,7 @@ static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad, u32 rows, cols; int error; - error = matrix_keypad_parse_of_params(dev, &rows, &cols); + error = matrix_keypad_parse_properties(dev, &rows, &cols); if (error) return error; diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 4e319eb9e19d..316414465c77 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -445,7 +445,6 @@ static int samsung_keypad_probe(struct platform_device *pdev) err_disable_runtime_pm: pm_runtime_disable(&pdev->dev); - device_init_wakeup(&pdev->dev, 0); err_unprepare_clk: clk_unprepare(keypad->clk); return error; @@ -456,7 +455,6 @@ static int samsung_keypad_remove(struct platform_device *pdev) struct samsung_keypad *keypad = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); - device_init_wakeup(&pdev->dev, 0); input_unregister_device(keypad->input_dev); diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 8083eaa0524a..7d25fa338ab4 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -283,8 +283,6 @@ static int spear_kbd_remove(struct platform_device *pdev) input_unregister_device(kbd->input); clk_unprepare(kbd->clk); - device_init_wakeup(&pdev->dev, 0); - return 0; } diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c index de7be4f03d91..babcfb165e4f 100644 --- a/drivers/input/keyboard/st-keyscan.c +++ b/drivers/input/keyboard/st-keyscan.c @@ -106,8 +106,8 @@ static int keypad_matrix_key_parse_dt(struct st_keyscan *keypad_data) struct device_node *np = dev->of_node; int error; - error = matrix_keypad_parse_of_params(dev, &keypad_data->n_rows, - &keypad_data->n_cols); + error = matrix_keypad_parse_properties(dev, &keypad_data->n_rows, + &keypad_data->n_cols); if (error) { dev_err(dev, "failed to parse keypad params\n"); return error; diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index fe6e3f22eed7..8c6c0b9109c7 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -354,7 +354,7 @@ static int stmpe_keypad_probe(struct platform_device *pdev) input->id.bustype = BUS_I2C; input->dev.parent = &pdev->dev; - error = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); + error = matrix_keypad_parse_properties(&pdev->dev, &rows, &cols); if (error) return error; diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index cc8f7ddcee53..a37c172452e6 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -261,7 +261,6 @@ static int sun4i_lradc_probe(struct platform_device *pdev) if (error) return error; - platform_set_drvdata(pdev, lradc); return 0; } diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 3048ef3e3e16..44dd7689c571 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -24,18 +24,17 @@ * alternative licensing inquiries. */ -#include <linux/types.h> -#include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/gpio.h> #include <linux/i2c.h> +#include <linux/init.h> #include <linux/input.h> -#include <linux/input/tca8418_keypad.h> +#include <linux/input/matrix_keypad.h> +#include <linux/interrupt.h> +#include <linux/module.h> #include <linux/of.h> +#include <linux/property.h> +#include <linux/slab.h> +#include <linux/types.h> /* TCA8418 hardware limits */ #define TCA8418_MAX_ROWS 8 @@ -264,41 +263,25 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data, } static int tca8418_keypad_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct device *dev = &client->dev; - const struct tca8418_keypad_platform_data *pdata = - dev_get_platdata(dev); struct tca8418_keypad *keypad_data; struct input_dev *input; - const struct matrix_keymap_data *keymap_data = NULL; u32 rows = 0, cols = 0; - bool rep = false; - bool irq_is_gpio = false; - int irq; int error, row_shift, max_keys; - /* Copy the platform data */ - if (pdata) { - if (!pdata->keymap_data) { - dev_err(dev, "no keymap data defined\n"); - return -EINVAL; - } - keymap_data = pdata->keymap_data; - rows = pdata->rows; - cols = pdata->cols; - rep = pdata->rep; - irq_is_gpio = pdata->irq_is_gpio; - } else { - struct device_node *np = dev->of_node; - int err; - - err = matrix_keypad_parse_of_params(dev, &rows, &cols); - if (err) - return err; - rep = of_property_read_bool(np, "keypad,autorepeat"); + /* Check i2c driver capabilities */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + dev_err(dev, "%s adapter not supported\n", + dev_driver_string(&client->adapter->dev)); + return -ENODEV; } + error = matrix_keypad_parse_properties(dev, &rows, &cols); + if (error) + return error; + if (!rows || rows > TCA8418_MAX_ROWS) { dev_err(dev, "invalid rows\n"); return -EINVAL; @@ -309,13 +292,6 @@ static int tca8418_keypad_probe(struct i2c_client *client, return -EINVAL; } - /* Check i2c driver capabilities */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { - dev_err(dev, "%s adapter not supported\n", - dev_driver_string(&client->adapter->dev)); - return -ENODEV; - } - row_shift = get_count_order(cols); max_keys = rows << row_shift; @@ -345,27 +321,20 @@ static int tca8418_keypad_probe(struct i2c_client *client, input->id.product = 0x001; input->id.version = 0x0001; - error = matrix_keypad_build_keymap(keymap_data, NULL, rows, cols, - NULL, input); + error = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL, input); if (error) { dev_err(dev, "Failed to build keymap\n"); return error; } - if (rep) + if (device_property_read_bool(dev, "keypad,autorepeat")) __set_bit(EV_REP, input->evbit); - input_set_capability(input, EV_MSC, MSC_SCAN); - - input_set_drvdata(input, keypad_data); - irq = client->irq; - if (irq_is_gpio) - irq = gpio_to_irq(irq); + input_set_capability(input, EV_MSC, MSC_SCAN); - error = devm_request_threaded_irq(dev, irq, NULL, tca8418_irq_handler, - IRQF_TRIGGER_FALLING | - IRQF_SHARED | - IRQF_ONESHOT, + error = devm_request_threaded_irq(dev, client->irq, + NULL, tca8418_irq_handler, + IRQF_SHARED | IRQF_ONESHOT, client->name, keypad_data); if (error) { dev_err(dev, "Unable to claim irq %d; error %d\n", @@ -384,30 +353,21 @@ static int tca8418_keypad_probe(struct i2c_client *client, } static const struct i2c_device_id tca8418_id[] = { - { TCA8418_NAME, 8418, }, + { "tca8418", 8418, }, { } }; MODULE_DEVICE_TABLE(i2c, tca8418_id); -#ifdef CONFIG_OF static const struct of_device_id tca8418_dt_ids[] = { { .compatible = "ti,tca8418", }, { } }; MODULE_DEVICE_TABLE(of, tca8418_dt_ids); -/* - * The device tree based i2c loader looks for - * "i2c:" + second_component_of(property("compatible")) - * and therefore we need an alias to be found. - */ -MODULE_ALIAS("i2c:tca8418"); -#endif - static struct i2c_driver tca8418_keypad_driver = { .driver = { - .name = TCA8418_NAME, - .of_match_table = of_match_ptr(tca8418_dt_ids), + .name = "tca8418_keypad", + .of_match_table = tca8418_dt_ids, }, .probe = tca8418_keypad_probe, .id_table = tca8418_id, diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c new file mode 100644 index 000000000000..485900f953e0 --- /dev/null +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -0,0 +1,284 @@ +/* + * TM2 touchkey device driver + * + * Copyright 2005 Phil Blundell + * Copyright 2016 Samsung Electronics Co., Ltd. + * + * Author: Beomho Seo <beomho.seo@samsung.com> + * Author: Jaechul Lee <jcsing.lee@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pm.h> +#include <linux/regulator/consumer.h> + +#define TM2_TOUCHKEY_DEV_NAME "tm2-touchkey" +#define TM2_TOUCHKEY_KEYCODE_REG 0x03 +#define TM2_TOUCHKEY_BASE_REG 0x00 +#define TM2_TOUCHKEY_CMD_LED_ON 0x10 +#define TM2_TOUCHKEY_CMD_LED_OFF 0x20 +#define TM2_TOUCHKEY_BIT_PRESS_EV BIT(3) +#define TM2_TOUCHKEY_BIT_KEYCODE GENMASK(2, 0) +#define TM2_TOUCHKEY_LED_VOLTAGE_MIN 2500000 +#define TM2_TOUCHKEY_LED_VOLTAGE_MAX 3300000 + +enum { + TM2_TOUCHKEY_KEY_MENU = 0x1, + TM2_TOUCHKEY_KEY_BACK, +}; + +struct tm2_touchkey_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct led_classdev led_dev; + struct regulator *vdd; + struct regulator_bulk_data regulators[2]; +}; + +static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct tm2_touchkey_data *touchkey = + container_of(led_dev, struct tm2_touchkey_data, led_dev); + u32 volt; + u8 data; + + if (brightness == LED_OFF) { + volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN; + data = TM2_TOUCHKEY_CMD_LED_OFF; + } else { + volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX; + data = TM2_TOUCHKEY_CMD_LED_ON; + } + + regulator_set_voltage(touchkey->vdd, volt, volt); + i2c_smbus_write_byte_data(touchkey->client, + TM2_TOUCHKEY_BASE_REG, data); +} + +static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey) +{ + int error; + + error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators), + touchkey->regulators); + if (error) + return error; + + /* waiting for device initialization, at least 150ms */ + msleep(150); + + return 0; +} + +static void tm2_touchkey_power_disable(void *data) +{ + struct tm2_touchkey_data *touchkey = data; + + regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators), + touchkey->regulators); +} + +static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid) +{ + struct tm2_touchkey_data *touchkey = devid; + int data; + int key; + + data = i2c_smbus_read_byte_data(touchkey->client, + TM2_TOUCHKEY_KEYCODE_REG); + if (data < 0) { + dev_err(&touchkey->client->dev, + "failed to read i2c data: %d\n", data); + goto out; + } + + switch (data & TM2_TOUCHKEY_BIT_KEYCODE) { + case TM2_TOUCHKEY_KEY_MENU: + key = KEY_PHONE; + break; + + case TM2_TOUCHKEY_KEY_BACK: + key = KEY_BACK; + break; + + default: + dev_warn(&touchkey->client->dev, + "unhandled keycode, data %#02x\n", data); + goto out; + } + + if (data & TM2_TOUCHKEY_BIT_PRESS_EV) { + input_report_key(touchkey->input_dev, KEY_PHONE, 0); + input_report_key(touchkey->input_dev, KEY_BACK, 0); + } else { + input_report_key(touchkey->input_dev, key, 1); + } + + input_sync(touchkey->input_dev); + +out: + return IRQ_HANDLED; +} + +static int tm2_touchkey_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tm2_touchkey_data *touchkey; + int error; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "incompatible I2C adapter\n"); + return -EIO; + } + + touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL); + if (!touchkey) + return -ENOMEM; + + touchkey->client = client; + i2c_set_clientdata(client, touchkey); + + touchkey->regulators[0].supply = "vcc"; + touchkey->regulators[1].supply = "vdd"; + error = devm_regulator_bulk_get(&client->dev, + ARRAY_SIZE(touchkey->regulators), + touchkey->regulators); + if (error) { + dev_err(&client->dev, "failed to get regulators: %d\n", error); + return error; + } + + /* Save VDD for easy access */ + touchkey->vdd = touchkey->regulators[1].consumer; + + error = tm2_touchkey_power_enable(touchkey); + if (error) { + dev_err(&client->dev, "failed to power up device: %d\n", error); + return error; + } + + error = devm_add_action_or_reset(&client->dev, + tm2_touchkey_power_disable, touchkey); + if (error) { + dev_err(&client->dev, + "failed to install poweroff handler: %d\n", error); + return error; + } + + /* input device */ + touchkey->input_dev = devm_input_allocate_device(&client->dev); + if (!touchkey->input_dev) { + dev_err(&client->dev, "failed to allocate input device\n"); + return -ENOMEM; + } + + touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME; + touchkey->input_dev->id.bustype = BUS_I2C; + + input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE); + input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK); + + error = input_register_device(touchkey->input_dev); + if (error) { + dev_err(&client->dev, + "failed to register input device: %d\n", error); + return error; + } + + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, tm2_touchkey_irq_handler, + IRQF_ONESHOT, + TM2_TOUCHKEY_DEV_NAME, touchkey); + if (error) { + dev_err(&client->dev, + "failed to request threaded irq: %d\n", error); + return error; + } + + /* led device */ + touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME; + touchkey->led_dev.brightness = LED_FULL; + touchkey->led_dev.max_brightness = LED_FULL; + touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set; + + error = devm_led_classdev_register(&client->dev, &touchkey->led_dev); + if (error) { + dev_err(&client->dev, + "failed to register touchkey led: %d\n", error); + return error; + } + + return 0; +} + +static int __maybe_unused tm2_touchkey_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); + + disable_irq(client->irq); + tm2_touchkey_power_disable(touchkey); + + return 0; +} + +static int __maybe_unused tm2_touchkey_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); + int ret; + + enable_irq(client->irq); + + ret = tm2_touchkey_power_enable(touchkey); + if (ret) + dev_err(dev, "failed to enable power: %d\n", ret); + + return ret; +} + +static SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops, + tm2_touchkey_suspend, tm2_touchkey_resume); + +static const struct i2c_device_id tm2_touchkey_id_table[] = { + { TM2_TOUCHKEY_DEV_NAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table); + +static const struct of_device_id tm2_touchkey_of_match[] = { + { .compatible = "cypress,tm2-touchkey", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match); + +static struct i2c_driver tm2_touchkey_driver = { + .driver = { + .name = TM2_TOUCHKEY_DEV_NAME, + .pm = &tm2_touchkey_pm_ops, + .of_match_table = of_match_ptr(tm2_touchkey_of_match), + }, + .probe = tm2_touchkey_probe, + .id_table = tm2_touchkey_id_table, +}; +module_i2c_driver(tm2_touchkey_driver); + +MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>"); +MODULE_AUTHOR("Jaechul Lee <jcsing.lee@samsung.com>"); +MODULE_DESCRIPTION("Samsung touchkey driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 323a0fb575a4..39e72b3219d8 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -374,8 +374,8 @@ static int twl4030_kp_probe(struct platform_device *pdev) kp->autorepeat = pdata->rep; keymap_data = pdata->keymap_data; } else { - error = matrix_keypad_parse_of_params(&pdev->dev, &kp->n_rows, - &kp->n_cols); + error = matrix_keypad_parse_properties(&pdev->dev, &kp->n_rows, + &kp->n_cols); if (error) return error; @@ -441,7 +441,6 @@ static int twl4030_kp_probe(struct platform_device *pdev) return -EIO; } - platform_set_drvdata(pdev, kp); return 0; } |