On Mon, Sep 07, 2020 at 10:40:45PM +0200, Sebastian Reichel wrote: > From: Mylène Josserand <mylene.josserand@xxxxxxxxxxxxx> > > 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). But it is not... > Signed-off-by: Mylène Josserand <mylene.josserand@xxxxxxxxxxxxx> > [code cleanup to current standards and renamed some properties] > Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> > --- > .../bindings/input/rotary-encoder.yaml | 21 +++++++++ Bindings should be a separate patch. > drivers/input/misc/rotary_encoder.c | 43 +++++++++++++++++++ > 2 files changed, 64 insertions(+) > > diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.yaml b/Documentation/devicetree/bindings/input/rotary-encoder.yaml > index 5b60ea86bd62..682fee104004 100644 > --- a/Documentation/devicetree/bindings/input/rotary-encoder.yaml > +++ b/Documentation/devicetree/bindings/input/rotary-encoder.yaml > @@ -74,6 +74,24 @@ properties: > need to be passed. > type: boolean > > + push-gpios: > + description: GPIO used as a detection of a push from the rotary-encoder. > + maxItems: 1 > + > + linux,push-code: > + description: > + keycode to emit with the push-gpio of this rotary encoder. > + If not specified defaults to <28> == KEY_ENTER. > + $ref: /schemas/types.yaml#/definitions/uint32 > + default: 28 > + > + linux,push-type: > + description: > + Specify event type this button/key generates. > + If not specified defaults to <1> == EV_KEY. > + $ref: /schemas/types.yaml#definitions/uint32 > + default: 1 Can we just use 'linux,code' and 'linux,input-type' here. That's problematic if there's ever more than 1, but so is the current solution having to make up new property names every time. Why can't the gpio-keys binding just be used here? Is it important to have the events on the same device? Is there some coordination needed between the functions? > + > required: > - compatible > - gpios > @@ -97,4 +115,7 @@ examples: > linux,axis = <ABS_Y>; > rotary-encoder,encoding = "binary"; > rotary-encoder,rollover; > + push-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>; > + linux,push-code = <KEY_ENTER>; > + linux,push-type = <EV_KEY>; > }; > diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c > index 16ad86fad7cb..484042a5afa0 100644 > --- a/drivers/input/misc/rotary_encoder.c > +++ b/drivers/input/misc/rotary_encoder.c > @@ -47,12 +47,33 @@ struct rotary_encoder { > > unsigned int *irq; > > + struct gpio_desc *push_gpio; > + unsigned int push_code; > + unsigned int push_type; > + > bool armed; > signed char dir; /* 1 - clockwise, -1 - CCW */ > > 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->push_gpio); > + > + input_report_key(encoder->input, encoder->push_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; > @@ -248,6 +269,16 @@ static int rotary_encoder_probe(struct platform_device *pdev) > return -EINVAL; > } > > + encoder->push_gpio = devm_gpiod_get_optional(dev, "push", GPIOD_IN); > + if (IS_ERR(encoder->push_gpio)) > + return dev_err_probe(dev, PTR_ERR(encoder->push_gpio), "failed to get push-gpio\n"); > + > + encoder->push_code = KEY_ENTER; > + device_property_read_u32(dev, "linux,push-code", &encoder->push_code); > + > + encoder->push_type = EV_KEY; > + device_property_read_u32(dev, "linux,push-type", &encoder->push_type); > + > input = devm_input_allocate_device(dev); > if (!input) > return -ENOMEM; > @@ -304,6 +335,18 @@ static int rotary_encoder_probe(struct platform_device *pdev) > } > } > > + if (encoder->push_gpio) { > + input_set_capability(encoder->input, encoder->push_type, encoder->push_code); > + err = devm_request_threaded_irq(dev, gpiod_to_irq(encoder->push_gpio), > + NULL, rotary_push_irq, > + IRQF_TRIGGER_RISING | > + IRQF_TRIGGER_FALLING | > + IRQF_ONESHOT, > + DRV_NAME, encoder); > + if (err) > + return dev_err_probe(dev, err, "unable to request push IRQ\n"); > + } > + > err = input_register_device(input); > if (err) { > dev_err(dev, "failed to register input device\n"); > -- > 2.28.0 >