[v1] Input: rotary-encoder - Add gpio as push button
diff mbox series

Message ID 20190614133651.28396-1-mylene.josserand@bootlin.com
State New
Headers show
Series
  • [v1] Input: rotary-encoder - Add gpio as push button
Related show

Commit Message

Mylène Josserand June 14, 2019, 1:36 p.m. UTC
Add the support of a gpio that can be defined as a push button.
Thanks to that, it is possible to emit a keycode in case of a
"push" event, if the rotary supports that.

The keycode to emit is defined using "linux,code" property
(such as in gpio-keys).

Signed-off-by: Mylène Josserand <mylene.josserand@bootlin.com>
---
 .../devicetree/bindings/input/rotary-encoder.txt   |  5 +++
 drivers/input/misc/rotary_encoder.c                | 50 ++++++++++++++++++++++
 2 files changed, 55 insertions(+)

Comments

Maxime Ripard June 14, 2019, 2:51 p.m. UTC | #1
Hi Mylene,

On Fri, Jun 14, 2019 at 03:36:51PM +0200, Mylène Josserand wrote:
> Add the support of a gpio that can be defined as a push button.
> Thanks to that, it is possible to emit a keycode in case of a
> "push" event, if the rotary supports that.
>
> The keycode to emit is defined using "linux,code" property
> (such as in gpio-keys).
>
> Signed-off-by: Mylène Josserand <mylene.josserand@bootlin.com>
> ---
>  .../devicetree/bindings/input/rotary-encoder.txt   |  5 +++
>  drivers/input/misc/rotary_encoder.c                | 50 ++++++++++++++++++++++
>  2 files changed, 55 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> index a644408b33b8..1cfce5d0b5c4 100644
> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> @@ -22,6 +22,9 @@ Optional properties:
>  - wakeup-source: Boolean, rotary encoder can wake up the system.
>  - rotary-encoder,encoding: String, the method used to encode steps.
>    Supported are "gray" (the default and more common) and "binary".
> +- push-gpio: a gpio to be used as a detection of a push from the rotary.

According to Documentation/devicetree/bindings/gpio/gpio.txt, GPIO
properties with a -gpio suffix are now deprecated in favor of the
-gpios suffix.

> +- linux,code: keycode to emit with the push-gpio of this rotary encoder.
> +  Required property in case "push-gpio"'s one is used.

I guess we should make it clear in the property name that it's the
keycode emitted at push. Otherwise, it will be ambiguous between the
rotary itself, or the button.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Dmitry Torokhov June 23, 2019, 7:05 a.m. UTC | #2
On Fri, Jun 14, 2019 at 04:51:58PM +0200, Maxime Ripard wrote:
> Hi Mylene,
> 
> On Fri, Jun 14, 2019 at 03:36:51PM +0200, Mylène Josserand wrote:
> > Add the support of a gpio that can be defined as a push button.
> > Thanks to that, it is possible to emit a keycode in case of a
> > "push" event, if the rotary supports that.
> >
> > The keycode to emit is defined using "linux,code" property
> > (such as in gpio-keys).
> >
> > Signed-off-by: Mylène Josserand <mylene.josserand@bootlin.com>
> > ---
> >  .../devicetree/bindings/input/rotary-encoder.txt   |  5 +++
> >  drivers/input/misc/rotary_encoder.c                | 50 ++++++++++++++++++++++
> >  2 files changed, 55 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> > index a644408b33b8..1cfce5d0b5c4 100644
> > --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> > +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> > @@ -22,6 +22,9 @@ Optional properties:
> >  - wakeup-source: Boolean, rotary encoder can wake up the system.
> >  - rotary-encoder,encoding: String, the method used to encode steps.
> >    Supported are "gray" (the default and more common) and "binary".
> > +- push-gpio: a gpio to be used as a detection of a push from the rotary.
> 
> According to Documentation/devicetree/bindings/gpio/gpio.txt, GPIO
> properties with a -gpio suffix are now deprecated in favor of the
> -gpios suffix.
> 
> > +- linux,code: keycode to emit with the push-gpio of this rotary encoder.
> > +  Required property in case "push-gpio"'s one is used.
> 
> I guess we should make it clear in the property name that it's the
> keycode emitted at push. Otherwise, it will be ambiguous between the
> rotary itself, or the button.

Also, I am pretty sure someone will come up with a switch instead of a
button shortly after ;) so I think we should have an event type there as
well.

Thanks.

Patch
diff mbox series

diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
index a644408b33b8..1cfce5d0b5c4 100644
--- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
@@ -22,6 +22,9 @@  Optional properties:
 - wakeup-source: Boolean, rotary encoder can wake up the system.
 - rotary-encoder,encoding: String, the method used to encode steps.
   Supported are "gray" (the default and more common) and "binary".
+- push-gpio: a gpio to be used as a detection of a push from the rotary.
+- linux,code: keycode to emit with the push-gpio of this rotary encoder.
+  Required property in case "push-gpio"'s one is used.
 
 Deprecated properties:
 - rotary-encoder,half-period: Makes the driver work on half-period mode.
@@ -47,4 +50,6 @@  Example:
 			rotary-encoder,steps = <24>;
 			rotary-encoder,encoding = "binary";
 			rotary-encoder,rollover;
+			push-gpio = <&gpio 20 0>;
+			linux-code = <28> /* KEY_ENTER */
 		};
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index d748897bf5e9..556995fb7dde 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -47,8 +47,10 @@  struct rotary_encoder {
 	unsigned int pos;
 
 	struct gpio_descs *gpios;
+	struct gpio_desc *gpio_push;
 
 	unsigned int *irq;
+	unsigned int code;
 
 	bool armed;
 	signed char dir;	/* 1 - clockwise, -1 - CCW */
@@ -56,6 +58,23 @@  struct rotary_encoder {
 	unsigned int last_stable;
 };
 
+static irqreturn_t rotary_push_irq(int irq, void *dev_id)
+{
+	struct rotary_encoder *encoder = dev_id;
+	int val;
+
+	mutex_lock(&encoder->access_mutex);
+
+	val = gpiod_get_value_cansleep(encoder->gpio_push);
+
+	input_report_key(encoder->input, encoder->code, val);
+	input_sync(encoder->input);
+
+	mutex_unlock(&encoder->access_mutex);
+
+	return IRQ_HANDLED;
+}
+
 static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
 {
 	int i;
@@ -190,6 +209,7 @@  static int rotary_encoder_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct rotary_encoder *encoder;
 	struct input_dev *input;
+	unsigned int irq_push;
 	irq_handler_t handler;
 	u32 steps_per_period;
 	unsigned int i;
@@ -250,6 +270,20 @@  static int rotary_encoder_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	encoder->gpio_push = devm_gpiod_get_optional(dev, "push", GPIOD_IN);
+	if (IS_ERR(encoder->gpio_push)) {
+		dev_err(dev, "unable to get gpio-push\n");
+		return PTR_ERR(encoder->gpio_push);
+	}
+
+	if (encoder->gpio_push) {
+		if (device_property_read_u32(dev, "linux,code",
+					     &encoder->code)) {
+			dev_err(dev, "gpio-push without keycode\n");
+			return -EINVAL;
+		}
+	}
+
 	input = devm_input_allocate_device(dev);
 	if (!input)
 		return -ENOMEM;
@@ -306,6 +340,22 @@  static int rotary_encoder_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (encoder->gpio_push) {
+		input_set_capability(encoder->input, EV_KEY, encoder->code);
+
+		irq_push = gpiod_to_irq(encoder->gpio_push);
+		err = devm_request_threaded_irq(dev, irq_push,
+						NULL, rotary_push_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT,
+						DRV_NAME, encoder);
+		if (err) {
+			dev_err(dev, "unable to request IRQ %d\n", irq_push);
+			return err;
+		}
+	}
+
 	err = input_register_device(input);
 	if (err) {
 		dev_err(dev, "failed to register input device\n");