From 9e4cc255e6e18418ddbeea447efa506bb43d57a2 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 25 Apr 2016 14:02:16 -0700 Subject: Input: twl6040-vibra - remove mutex The mutex does not seem to be needed. twl4030-vibra doesn't use one either. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl6040-vibra.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index ea63fad48de6..36c8182b7bd2 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -47,7 +47,7 @@ struct vibra_info { struct input_dev *input_dev; struct workqueue_struct *workqueue; struct work_struct play_work; - struct mutex mutex; + int irq; bool enabled; @@ -183,8 +183,6 @@ static void vibra_play_work(struct work_struct *work) struct vibra_info *info = container_of(work, struct vibra_info, play_work); - mutex_lock(&info->mutex); - if (info->weak_speed || info->strong_speed) { if (!info->enabled) twl6040_vibra_enable(info); @@ -193,7 +191,6 @@ static void vibra_play_work(struct work_struct *work) } else if (info->enabled) twl6040_vibra_disable(info); - mutex_unlock(&info->mutex); } static int vibra_play(struct input_dev *input, void *data, @@ -228,12 +225,8 @@ static void twl6040_vibra_close(struct input_dev *input) cancel_work_sync(&info->play_work); - mutex_lock(&info->mutex); - if (info->enabled) twl6040_vibra_disable(info); - - mutex_unlock(&info->mutex); } static int __maybe_unused twl6040_vibra_suspend(struct device *dev) @@ -241,13 +234,11 @@ static int __maybe_unused twl6040_vibra_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct vibra_info *info = platform_get_drvdata(pdev); - mutex_lock(&info->mutex); + cancel_work_sync(&info->play_work); if (info->enabled) twl6040_vibra_disable(info); - mutex_unlock(&info->mutex); - return 0; } @@ -305,8 +296,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev) return -EINVAL; } - mutex_init(&info->mutex); - error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, twl6040_vib_irq_handler, IRQF_ONESHOT, -- cgit v1.2.3 From c90a0f08fedc57e2b8ff871cc036cdbdde683de4 Mon Sep 17 00:00:00 2001 From: Florian Euchner Date: Wed, 4 May 2016 15:59:18 -0700 Subject: Input: cm109 - fix handling of volume and mute buttons The CM109 driver reported key press events of volume up / down and record / playback mute buttons, but no release events. Report those events properly by handling volume and mute keys seperately. For the record and playback mute buttons, only presses are registered by the CM109, therefore simulate press-n-release. This fixes the volume control buttons of various USB headsets. Signed-off-by: Florian Euchner Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cm109.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 9365535ba7f1..ee1bedd7c54c 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -76,8 +76,8 @@ enum { BUZZER_ON = 1 << 5, - /* up to 256 normal keys, up to 16 special keys */ - KEYMAP_SIZE = 256 + 16, + /* up to 256 normal keys, up to 15 special key combinations */ + KEYMAP_SIZE = 256 + 15, }; /* CM109 protocol packet */ @@ -139,7 +139,7 @@ static unsigned short special_keymap(int code) { if (code > 0xff) { switch (code - 0xff) { - case RECORD_MUTE: return KEY_MUTE; + case RECORD_MUTE: return KEY_MICMUTE; case PLAYBACK_MUTE: return KEY_MUTE; case VOLUME_DOWN: return KEY_VOLUMEDOWN; case VOLUME_UP: return KEY_VOLUMEUP; @@ -312,6 +312,32 @@ static void report_key(struct cm109_dev *dev, int key) input_sync(idev); } +/* + * Converts data of special key presses (volume, mute) into events + * for the input subsystem, sends press-n-release for mute keys. + */ +static void cm109_report_special(struct cm109_dev *dev) +{ + static const u8 autorelease = RECORD_MUTE | PLAYBACK_MUTE; + struct input_dev *idev = dev->idev; + u8 data = dev->irq_data->byte[HID_IR0]; + unsigned short keycode; + int i; + + for (i = 0; i < 4; i++) { + keycode = dev->keymap[0xff + BIT(i)]; + if (keycode == KEY_RESERVED) + continue; + + input_report_key(idev, keycode, data & BIT(i)); + if (data & autorelease & BIT(i)) { + input_sync(idev); + input_report_key(idev, keycode, 0); + } + } + input_sync(idev); +} + /****************************************************************************** * CM109 usb communication interface *****************************************************************************/ @@ -357,10 +383,7 @@ static void cm109_urb_irq_callback(struct urb *urb) } /* Special keys */ - if (dev->irq_data->byte[HID_IR0] & 0x0f) { - const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); - report_key(dev, dev->keymap[0xff + code]); - } + cm109_report_special(dev); /* Scan key column */ if (dev->keybit == 0xf) { -- cgit v1.2.3 From d144cf42eee0eabdb2e76ea67a9b0437c5070751 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 2 May 2016 11:15:01 -0700 Subject: Input: cm109 - spin_lock in complete() cleanup Complete() will be run with interrupt enabled, so change to spin_lock_irqsave(). Signed-off-by: Ming Lei Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cm109.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index ee1bedd7c54c..9cc6d057c302 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -366,6 +366,7 @@ static void cm109_urb_irq_callback(struct urb *urb) struct cm109_dev *dev = urb->context; const int status = urb->status; int error; + unsigned long flags; dev_dbg(&dev->intf->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n", dev->irq_data->byte[0], @@ -404,7 +405,7 @@ static void cm109_urb_irq_callback(struct urb *urb) out: - spin_lock(&dev->ctl_submit_lock); + spin_lock_irqsave(&dev->ctl_submit_lock, flags); dev->irq_urb_pending = 0; @@ -428,7 +429,7 @@ static void cm109_urb_irq_callback(struct urb *urb) __func__, error); } - spin_unlock(&dev->ctl_submit_lock); + spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); } static void cm109_urb_ctl_callback(struct urb *urb) @@ -436,6 +437,7 @@ static void cm109_urb_ctl_callback(struct urb *urb) struct cm109_dev *dev = urb->context; const int status = urb->status; int error; + unsigned long flags; dev_dbg(&dev->intf->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n", dev->ctl_data->byte[0], @@ -450,7 +452,7 @@ static void cm109_urb_ctl_callback(struct urb *urb) __func__, status); } - spin_lock(&dev->ctl_submit_lock); + spin_lock_irqsave(&dev->ctl_submit_lock, flags); dev->ctl_urb_pending = 0; @@ -471,7 +473,7 @@ static void cm109_urb_ctl_callback(struct urb *urb) } } - spin_unlock(&dev->ctl_submit_lock); + spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); } static void cm109_toggle_buzzer_async(struct cm109_dev *dev) -- cgit v1.2.3 From d96caf8c33cad42b5eabcf1b686dd91581e306f4 Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Mon, 9 May 2016 17:00:22 -0700 Subject: Input: rotary-encoder - fix bare use of 'unsigned' fix checkpatch.pl warning about 'Prefer 'unsigned int' to bare use of 'unsigned'' Signed-off-by: Clifton Barnes Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 96c486de49e0..c7fc8d4fb080 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -47,13 +47,13 @@ struct rotary_encoder { bool armed; signed char dir; /* 1 - clockwise, -1 - CCW */ - unsigned last_stable; + unsigned int last_stable; }; -static unsigned rotary_encoder_get_state(struct rotary_encoder *encoder) +static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder) { int i; - unsigned ret = 0; + unsigned int ret = 0; for (i = 0; i < encoder->gpios->ndescs; ++i) { int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]); @@ -100,7 +100,7 @@ static void rotary_encoder_report_event(struct rotary_encoder *encoder) static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) { struct rotary_encoder *encoder = dev_id; - unsigned state; + unsigned int state; mutex_lock(&encoder->access_mutex); -- cgit v1.2.3 From ad4e9fec143c453cae145d7d5ccac902c37fb912 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 14 Apr 2016 21:17:25 +0200 Subject: input: misc: max77693: Use pwm_get_args() where appropriate The PWM framework has clarified the concept of reference PWM config (the platform dependent config retrieved from the DT or the PWM lookup table) and real PWM state. Use pwm_get_args() when the PWM user wants to retrieve this reference config and not the current state. This is part of the rework allowing the PWM framework to support hardware readout and expose real PWM state even when the PWM has just been requested (before the user calls pwm_config/enable/disable()). Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/input/misc/max77693-haptic.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 6d96bff32a0e..29ddeb7be84b 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -70,10 +70,13 @@ struct max77693_haptic { static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic) { - int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2; + struct pwm_args pargs; + int delta; int error; - error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period); + pwm_get_args(haptic->pwm_dev, &pargs); + delta = (pargs.period + haptic->pwm_duty) / 2; + error = pwm_config(haptic->pwm_dev, delta, pargs.period); if (error) { dev_err(haptic->dev, "failed to configure pwm: %d\n", error); return error; @@ -234,6 +237,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { struct max77693_haptic *haptic = input_get_drvdata(dev); + struct pwm_args pargs; u64 period_mag_multi; haptic->magnitude = effect->u.rumble.strong_magnitude; @@ -245,7 +249,8 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data, * The formula to convert magnitude to pwm_duty as follows: * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF) */ - period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude; + pwm_get_args(haptic->pwm_dev, &pargs); + period_mag_multi = (u64)pargs.period * haptic->magnitude; haptic->pwm_duty = (unsigned int)(period_mag_multi >> MAX_MAGNITUDE_SHIFT); @@ -329,6 +334,12 @@ static int max77693_haptic_probe(struct platform_device *pdev) return PTR_ERR(haptic->pwm_dev); } + /* + * FIXME: pwm_apply_args() should be removed when switching to the + * atomic PWM API. + */ + pwm_apply_args(haptic->pwm_dev); + haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic"); if (IS_ERR(haptic->motor_reg)) { dev_err(&pdev->dev, "failed to get regulator\n"); -- cgit v1.2.3 From de93170b85d7ee2a6a6a881c019160a65adeb636 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 14 Apr 2016 21:17:33 +0200 Subject: input: misc: max8997: Explicitly apply PWM config extracted from pwm_args Call pwm_apply_args() just after requesting the PWM device so that the polarity and period are initialized according to the information provided in pwm_args. This is an intermediate state, and pwm_apply_args() should be dropped as soon as the atomic PWM infrastructure is in place and the driver makes use of it. Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/input/misc/max8997_haptic.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index a806ba3818f7..bf17f654ed88 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -304,6 +304,12 @@ static int max8997_haptic_probe(struct platform_device *pdev) error); goto err_free_mem; } + + /* + * FIXME: pwm_apply_args() should be removed when switching to + * the atomic PWM API. + */ + pwm_apply_args(chip->pwm); break; default: -- cgit v1.2.3 From cfae56f18c7cbdb0542025b0d3f000d9ba0152d0 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 14 Apr 2016 21:17:34 +0200 Subject: input: misc: pwm-beeper: Explicitly apply PWM config extracted from pwm_args Call pwm_apply_args() just after requesting the PWM device so that the polarity and period are initialized according to the information provided in pwm_args. This is an intermediate state, and pwm_apply_args() should be dropped as soon as the atomic PWM infrastructure is in place and the driver makes use of it. Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/input/misc/pwm-beeper.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index f2261ab54701..8d7133268745 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -87,6 +87,12 @@ static int pwm_beeper_probe(struct platform_device *pdev) goto err_free; } + /* + * FIXME: pwm_apply_args() should be removed when switching to + * the atomic PWM API. + */ + pwm_apply_args(beeper->pwm); + beeper->input = input_allocate_device(); if (!beeper->input) { dev_err(&pdev->dev, "Failed to allocate input device\n"); -- cgit v1.2.3 From affa80bd97f7ca282d1faa91667b3ee9e4c590e6 Mon Sep 17 00:00:00 2001 From: Ricky Liang Date: Fri, 20 May 2016 10:58:59 -0700 Subject: Input: uinput - handle compat ioctl for UI_SET_PHYS When running a 32-bit userspace on a 64-bit kernel, the UI_SET_PHYS ioctl needs to be treated with special care, as it has the pointer size encoded in the command. Signed-off-by: Ricky Liang Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 4eb9e4d94f46..79338f4bdecb 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -981,9 +981,15 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT + +#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t) + static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + if (cmd == UI_SET_PHYS_COMPAT) + cmd = UI_SET_PHYS; + return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg)); } #endif -- cgit v1.2.3 From f49cf3b8b4c841457244c461c66186a719e13bcc Mon Sep 17 00:00:00 2001 From: Manfred Schlaegl Date: Fri, 27 May 2016 16:36:36 -0700 Subject: Input: pwm-beeper - fix - scheduling while atomic Pwm config may sleep so defer it using a worker. On a Freescale i.MX53 based board we ran into "BUG: scheduling while atomic" because input_inject_event locks interrupts, but imx_pwm_config_v2 sleeps. Tested on Freescale i.MX53 SoC with 4.6.0. Signed-off-by: Manfred Schlaegl Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pwm-beeper.c | 69 ++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index f2261ab54701..18663d4edae5 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -20,21 +20,40 @@ #include #include #include +#include struct pwm_beeper { struct input_dev *input; struct pwm_device *pwm; + struct work_struct work; unsigned long period; }; #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x)) +static void __pwm_beeper_set(struct pwm_beeper *beeper) +{ + unsigned long period = beeper->period; + + if (period) { + pwm_config(beeper->pwm, period / 2, period); + pwm_enable(beeper->pwm); + } else + pwm_disable(beeper->pwm); +} + +static void pwm_beeper_work(struct work_struct *work) +{ + struct pwm_beeper *beeper = + container_of(work, struct pwm_beeper, work); + + __pwm_beeper_set(beeper); +} + static int pwm_beeper_event(struct input_dev *input, unsigned int type, unsigned int code, int value) { - int ret = 0; struct pwm_beeper *beeper = input_get_drvdata(input); - unsigned long period; if (type != EV_SND || value < 0) return -EINVAL; @@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input, return -EINVAL; } - if (value == 0) { - pwm_disable(beeper->pwm); - } else { - period = HZ_TO_NANOSECONDS(value); - ret = pwm_config(beeper->pwm, period / 2, period); - if (ret) - return ret; - ret = pwm_enable(beeper->pwm); - if (ret) - return ret; - beeper->period = period; - } + if (value == 0) + beeper->period = 0; + else + beeper->period = HZ_TO_NANOSECONDS(value); + + schedule_work(&beeper->work); return 0; } +static void pwm_beeper_stop(struct pwm_beeper *beeper) +{ + cancel_work_sync(&beeper->work); + + if (beeper->period) + pwm_disable(beeper->pwm); +} + +static void pwm_beeper_close(struct input_dev *input) +{ + struct pwm_beeper *beeper = input_get_drvdata(input); + + pwm_beeper_stop(beeper); +} + static int pwm_beeper_probe(struct platform_device *pdev) { unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev); @@ -87,6 +115,8 @@ static int pwm_beeper_probe(struct platform_device *pdev) goto err_free; } + INIT_WORK(&beeper->work, pwm_beeper_work); + beeper->input = input_allocate_device(); if (!beeper->input) { dev_err(&pdev->dev, "Failed to allocate input device\n"); @@ -106,6 +136,7 @@ static int pwm_beeper_probe(struct platform_device *pdev) beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL); beeper->input->event = pwm_beeper_event; + beeper->input->close = pwm_beeper_close; input_set_drvdata(beeper->input, beeper); @@ -135,7 +166,6 @@ static int pwm_beeper_remove(struct platform_device *pdev) input_unregister_device(beeper->input); - pwm_disable(beeper->pwm); pwm_free(beeper->pwm); kfree(beeper); @@ -147,8 +177,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev) { struct pwm_beeper *beeper = dev_get_drvdata(dev); - if (beeper->period) - pwm_disable(beeper->pwm); + pwm_beeper_stop(beeper); return 0; } @@ -157,10 +186,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev) { struct pwm_beeper *beeper = dev_get_drvdata(dev); - if (beeper->period) { - pwm_config(beeper->pwm, beeper->period / 2, beeper->period); - pwm_enable(beeper->pwm); - } + if (beeper->period) + __pwm_beeper_set(beeper); return 0; } -- cgit v1.2.3