Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755824AbcJFMas (ORCPT ); Thu, 6 Oct 2016 08:30:48 -0400 Received: from protonic.xs4all.nl ([83.163.252.89]:17062 "EHLO protonic.xs4all.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753998AbcJFMal (ORCPT ); Thu, 6 Oct 2016 08:30:41 -0400 From: Robin van der Gracht To: Miguel Ojeda Sandonis Cc: linux-kernel@vger.kernel.org, Robin van der Gracht Subject: [PATCH] auxdisplay: ht16k33: Keyscan function is now optional. Date: Thu, 6 Oct 2016 14:30:15 +0200 Message-Id: <1475757015-2265-1-git-send-email-robin@protonic.nl> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6844 Lines: 214 Signed-off-by: Robin van der Gracht --- .../devicetree/bindings/display/ht16k33.txt | 15 ++- drivers/auxdisplay/ht16k33.c | 126 +++++++++++---------- 2 files changed, 73 insertions(+), 68 deletions(-) diff --git a/Documentation/devicetree/bindings/display/ht16k33.txt b/Documentation/devicetree/bindings/display/ht16k33.txt index 8e5b30b..e2c9048 100644 --- a/Documentation/devicetree/bindings/display/ht16k33.txt +++ b/Documentation/devicetree/bindings/display/ht16k33.txt @@ -4,18 +4,21 @@ Holtek ht16k33 RAM mapping 16*8 LED controller driver with keyscan Required properties: - compatible: "holtek,ht16k33" - reg: I2C slave address of the chip. -- interrupt-parent: A phandle pointing to the interrupt controller - serving the interrupt for this chip. -- interrupts: Interrupt specification for the key pressed interrupt. - refresh-rate-hz: Display update interval in HZ. -- debounce-delay-ms: Debouncing interval time in milliseconds. -- linux,keymap: The keymap for keys as described in the binding - document (devicetree/bindings/input/matrix-keymap.txt). Optional properties: - linux,no-autorepeat: Disable keyrepeat. - default-brightness-level: Initial brightness level [0-15] (default: 15). +- Keypad + Supply the 'interrupts' property to enable the keyscan feature. + - interrupts: Interrupt specification for the key pressed interrupt. + - interrupt-parent: A phandle pointing to the interrupt controller + serving the interrupt for this chip. + - debounce-delay-ms: Debouncing interval time in milliseconds. + - linux,keymap: The keymap for keys as described in the binding + document (devicetree/bindings/input/matrix-keymap.txt). + Example: &i2c1 { diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index 9c09bbc..5cf8fb4 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -334,15 +334,71 @@ static struct fb_ops ht16k33_fb_ops = { .fb_mmap = ht16k33_mmap, }; +static int ht16k33_register_keypad(struct ht16k33_priv *priv) +{ + int rows, cols, err; + struct ht16k33_keypad *keypad = &priv->keypad; + struct device *dev = &priv->client->dev; + + keypad->dev = devm_input_allocate_device(dev); + if (!keypad->dev) + return -ENOMEM; + + keypad->dev->name = dev_name(dev); + keypad->dev->id.bustype = BUS_I2C; + keypad->dev->open = ht16k33_keypad_start; + keypad->dev->close = ht16k33_keypad_stop; + + if (!of_get_property(dev->of_node, "linux,no-autorepeat", NULL)) + __set_bit(EV_REP, keypad->dev->evbit); + + err = of_property_read_u32(dev->of_node, "debounce-delay-ms", + &keypad->debounce_ms); + if (err) { + dev_err(dev, "key debounce delay not specified\n"); + return err; + } + + err = devm_request_threaded_irq(dev, priv->client->irq, NULL, + ht16k33_irq_thread, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + DRIVER_NAME, priv); + if (err) { + dev_err(dev, "Failed to request irq %i\n", priv->client->irq); + return err; + } + + disable_irq_nosync(priv->client->irq); + rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS; + cols = HT16K33_MATRIX_KEYPAD_MAX_COLS; + err = matrix_keypad_parse_of_params(dev, &rows, &cols); + if (err) + return err; + + err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL, + keypad->dev); + if (err) { + dev_err(dev, "failed to build keymap\n"); + return err; + } + + input_set_drvdata(keypad->dev, priv); + keypad->rows = rows; + keypad->cols = cols; + keypad->row_shift = get_count_order(cols); + INIT_DELAYED_WORK(&keypad->work, ht16k33_keypad_scan); + + return input_register_device(keypad->dev); +} + static int ht16k33_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err; - uint32_t rows, cols, dft_brightness; + uint32_t dft_brightness; struct backlight_device *bl; struct backlight_properties bl_props; struct ht16k33_priv *priv; - struct ht16k33_keypad *keypad; struct ht16k33_fbdev *fbdev; struct device_node *node = client->dev.of_node; const char *dev_id = dev_name(&client->dev); @@ -352,11 +408,6 @@ static int ht16k33_probe(struct i2c_client *client, return -EIO; } - if (client->irq <= 0) { - dev_err(&client->dev, "No IRQ specified\n"); - return -EINVAL; - } - priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -364,7 +415,6 @@ static int ht16k33_probe(struct i2c_client *client, priv->client = client; i2c_set_clientdata(client, priv); fbdev = &priv->fbdev; - keypad = &priv->keypad; priv->workqueue = create_singlethread_workqueue(dev_id); if (priv->workqueue == NULL) @@ -417,61 +467,12 @@ static int ht16k33_probe(struct i2c_client *client, goto err_fbdev_info; /* Keypad */ - keypad->dev = devm_input_allocate_device(&client->dev); - if (!keypad->dev) { - err = -ENOMEM; - goto err_fbdev_unregister; - } - - keypad->dev->name = dev_id; - keypad->dev->id.bustype = BUS_I2C; - keypad->dev->open = ht16k33_keypad_start; - keypad->dev->close = ht16k33_keypad_stop; - - if (!of_get_property(node, "linux,no-autorepeat", NULL)) - __set_bit(EV_REP, keypad->dev->evbit); - - err = of_property_read_u32(node, "debounce-delay-ms", - &keypad->debounce_ms); - if (err) { - dev_err(&client->dev, "key debounce delay not specified\n"); - goto err_fbdev_unregister; + if (client->irq > 0) { + err = ht16k33_register_keypad(priv); + if (err) + goto err_fbdev_unregister; } - err = devm_request_threaded_irq(&client->dev, client->irq, NULL, - ht16k33_irq_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - DRIVER_NAME, priv); - if (err) { - dev_err(&client->dev, "irq request failed %d, error %d\n", - client->irq, err); - goto err_fbdev_unregister; - } - - disable_irq_nosync(client->irq); - rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS; - cols = HT16K33_MATRIX_KEYPAD_MAX_COLS; - err = matrix_keypad_parse_of_params(&client->dev, &rows, &cols); - if (err) - goto err_fbdev_unregister; - - err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL, - keypad->dev); - if (err) { - dev_err(&client->dev, "failed to build keymap\n"); - goto err_fbdev_unregister; - } - - input_set_drvdata(keypad->dev, priv); - keypad->rows = rows; - keypad->cols = cols; - keypad->row_shift = get_count_order(cols); - INIT_DELAYED_WORK(&keypad->work, ht16k33_keypad_scan); - - err = input_register_device(keypad->dev); - if (err) - goto err_fbdev_unregister; - /* Backlight */ memset(&bl_props, 0, sizeof(struct backlight_properties)); bl_props.type = BACKLIGHT_RAW; @@ -504,7 +505,8 @@ static int ht16k33_probe(struct i2c_client *client, return 0; err_keypad_unregister: - input_unregister_device(keypad->dev); + if (priv->keypad.dev) + input_unregister_device(priv->keypad.dev); err_fbdev_unregister: unregister_framebuffer(fbdev->info); err_fbdev_info: -- 2.7.4