Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3499078pxf; Mon, 22 Mar 2021 07:50:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx2M1/bzA+zliyzYKNz+BQcYZfvD22sOY3jYSdTj89pySsnlmvCe2YBCp72FVLIunQC6mzL X-Received: by 2002:a17:906:c099:: with SMTP id f25mr111562ejz.141.1616424645406; Mon, 22 Mar 2021 07:50:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616424645; cv=none; d=google.com; s=arc-20160816; b=em3cQGH5vOFU+XTPtWNqONCGP8wUiGCRYCbs79AHMZJmTHhIxCC9s4E1TcnAV8DOgu /2YtxE9P7XlkkbL6o7MIX12RGu3J0p2M7xQ4HE2U7G8JzuM3lL1dmwexCoMNnMsAeJzd D5RDiPFqZEtHvIhyfojjYUSsZPnDyvzIYbQJypahADPINcVffaxX8jCq9GFYNh+SNVrJ iRkFNh2xSy0/TbT+QcLySxy/I0GS/Ec74LVMxuSwuHJJmwh3GlCd06FX9YXvlzFSoYTz mFV21sFEdbDBzIskrNC4yvQw3jwH2IUo9okzHnjczSZ1obA8Ncn3AQWmphRRKBT3L4Hu mFPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=gFadmsYQA6m758RCaXpIUnG9gC4vMMDmwXanB5LeXm8=; b=YJkZMdp4zVJTB31c2P9uooDje5yEnLq7vWdfySY+ziL6iVjal0TfbOEGlrFNWJCYXK TvMPIyRxc/RH8cxDhloxOljhPSzhozmkpmtvC6C4DaSGW5JJ7EBLG0gVif8SQ9nQm8P+ gcIulA9DsadRwOSmeLecOsgqALDhhc4HcaMrS4InTxOZGYNu6P5Ug0Q0RR+SysIcY1Sm UTPkL69Zc0HIU6SVFkfkFYknLuSRPiOby5kZKWF90L16SCKgeY8c4d6mWMCnSLrWBkLi lAHOEsyBNuX4mIlTPWxhYFLe4yzyGyfCRiDw/INRGRZcY2sLy3LMMe+Id7Ytp/zkRgqr RQlw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u13si11429189ejc.243.2021.03.22.07.50.23; Mon, 22 Mar 2021 07:50:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231206AbhCVOtg (ORCPT + 99 others); Mon, 22 Mar 2021 10:49:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230288AbhCVOs5 (ORCPT ); Mon, 22 Mar 2021 10:48:57 -0400 Received: from michel.telenet-ops.be (michel.telenet-ops.be [IPv6:2a02:1800:110:4::f00:18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DBBEC0613E4 for ; Mon, 22 Mar 2021 07:48:54 -0700 (PDT) Received: from ramsan.of.borg ([IPv6:2a02:1810:ac12:ed20:250b:f16c:c5e2:505d]) by michel.telenet-ops.be with bizsmtp id jSot240062HDxaV06Sotq1; Mon, 22 Mar 2021 15:48:53 +0100 Received: from rox.of.borg ([192.168.97.57]) by ramsan.of.borg with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1lOLrQ-009ZWV-LC; Mon, 22 Mar 2021 15:48:52 +0100 Received: from geert by rox.of.borg with local (Exim 4.93) (envelope-from ) id 1lOLrQ-004T6u-1L; Mon, 22 Mar 2021 15:48:52 +0100 From: Geert Uytterhoeven To: Robin van der Gracht , Rob Herring , Miguel Ojeda , Paul Burton , Greg Kroah-Hartman Cc: devicetree@vger.kernel.org, linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven Subject: [PATCH 17/17] auxdisplay: ht16k33: Add segment display LED support Date: Mon, 22 Mar 2021 15:48:48 +0100 Message-Id: <20210322144848.1065067-18-geert@linux-m68k.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322144848.1065067-1-geert@linux-m68k.org> References: <20210322144848.1065067-1-geert@linux-m68k.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Instantiate a single LED for a segment display. This allows the user to control display brightness and blinking through the LED class API and triggers, and exposes the display color. Signed-off-by: Geert Uytterhoeven --- For setting display brightness, this could use the existing backlight support for frame buffer devices instantiated for dot-matrix displays. However, using the leds subsystem instead has the advantage that the driver can make use of the HT16K33's hardware blinking support, and can expose the display color. --- drivers/auxdisplay/ht16k33.c | 81 ++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index 0b502a6039f89c6b..5821addd9aec5633 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -29,6 +29,7 @@ #include #include "line-display.h" +#include "../leds/leds.h" /* for led_colors[] */ /* Registers */ #define REG_SYSTEM_SETUP 0x20 @@ -36,6 +37,10 @@ #define REG_DISPLAY_SETUP 0x80 #define REG_DISPLAY_SETUP_ON BIT(0) +#define REG_DISPLAY_SETUP_BLINK_OFF (0 << 1) +#define REG_DISPLAY_SETUP_BLINK_2HZ (1 << 1) +#define REG_DISPLAY_SETUP_BLINK_1HZ (2 << 1) +#define REG_DISPLAY_SETUP_BLINK_0HZ5 (3 << 1) #define REG_ROWINT_SET 0xA0 #define REG_ROWINT_SET_INT_EN BIT(0) @@ -57,6 +62,8 @@ #define BYTES_PER_ROW (HT16K33_MATRIX_LED_MAX_ROWS / 8) #define HT16K33_FB_SIZE (HT16K33_MATRIX_LED_MAX_COLS * BYTES_PER_ROW) +#define COLOR_DEFAULT LED_COLOR_ID_RED + enum display_type { DISP_MATRIX = 0, DISP_QUAD_7SEG, @@ -85,6 +92,7 @@ struct ht16k33_fbdev { struct ht16k33_seg { struct linedisp linedisp; + struct led_classdev led; union { struct seg7_conversion_map seg7; struct seg14_conversion_map seg14; @@ -102,6 +110,7 @@ struct ht16k33_priv { struct ht16k33_seg seg; }; enum display_type type; + uint8_t blink; }; static const struct fb_fix_screeninfo ht16k33_fb_fix = { @@ -160,7 +169,7 @@ static DEVICE_ATTR(map_seg14, 0644, map_seg_show, map_seg_store); static int ht16k33_display_on(struct ht16k33_priv *priv) { - uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON; + uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | priv->blink; return i2c_smbus_write_byte(priv->client, data); } @@ -175,8 +184,11 @@ static int ht16k33_brightness_set(struct ht16k33_priv *priv, { int error; - if (brightness == 0) + if (brightness == 0) { + // Disable blink mode + priv->blink = REG_DISPLAY_SETUP_BLINK_OFF; return ht16k33_display_off(priv); + } error = ht16k33_display_on(priv); if (error) @@ -186,6 +198,49 @@ static int ht16k33_brightness_set(struct ht16k33_priv *priv, REG_BRIGHTNESS | (brightness - 1)); } +static int ht16k33_brightness_set_blocking(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, + seg.led); + + return ht16k33_brightness_set(priv, brightness); +} + +static int ht16k33_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct ht16k33_priv *priv = container_of(led_cdev, struct ht16k33_priv, + seg.led); + unsigned int delay; + uint8_t blink; + int error; + + if (!*delay_on && !*delay_off) { + blink = REG_DISPLAY_SETUP_BLINK_1HZ; + delay = 1000; + } else if (*delay_on <= 750) { + blink = REG_DISPLAY_SETUP_BLINK_2HZ; + delay = 500; + } else if (*delay_on <= 1500) { + blink = REG_DISPLAY_SETUP_BLINK_1HZ; + delay = 1000; + } else { + blink = REG_DISPLAY_SETUP_BLINK_0HZ5; + delay = 2000; + } + + error = i2c_smbus_write_byte(priv->client, + REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | + blink); + if (error) + return error; + + priv->blink = blink; + *delay_on = *delay_off = delay; + return 0; +} + static void ht16k33_fb_queue(struct ht16k33_priv *priv) { struct ht16k33_fbdev *fbdev = &priv->fbdev; @@ -578,11 +633,29 @@ static int ht16k33_fbdev_probe(struct i2c_client *client, static int ht16k33_seg_probe(struct i2c_client *client, struct ht16k33_priv *priv, uint32_t brightness) { - struct ht16k33_seg *seg = &priv->seg; struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct ht16k33_seg *seg = &priv->seg; + u32 color = COLOR_DEFAULT; int err; - err = ht16k33_brightness_set(priv, MAX_BRIGHTNESS); + of_property_read_u32(node, "color", &color); + seg->led.name = devm_kasprintf(dev, GFP_KERNEL, + DRIVER_NAME ":%s:" LED_FUNCTION_BACKLIGHT, + color < LED_COLOR_ID_MAX ? led_colors[color] : ""); + seg->led.brightness_set_blocking = ht16k33_brightness_set_blocking; + seg->led.blink_set = ht16k33_blink_set; + seg->led.flags = LED_CORE_SUSPENDRESUME; + seg->led.brightness = brightness; + seg->led.max_brightness = MAX_BRIGHTNESS; + + err = devm_led_classdev_register(dev, &seg->led); + if (err) { + dev_err(dev, "Failed to register LED\n"); + return err; + } + + err = ht16k33_brightness_set(priv, seg->led.brightness); if (err) return err; -- 2.25.1