Hoi Robin,
On Thu, Sep 30, 2021 at 12:57 PM Robin van der Gracht <robin@xxxxxxxxxxx> wrote:On 2021-09-14 16:38, Geert Uytterhoeven wrote:
> Instantiate a single LED based on the "led" subnode in DT.
> This allows the user to control display brightness and blinking (backed
> by hardware support) through the LED class API and triggers, and exposes
> the display color. The LED will be named
> "auxdisplay:<color>:<function>".
>
> When running in dot-matrix mode and if no "led" subnode is found, the
> driver falls back to the traditional backlight mode, to preserve
> backwards compatibility.
>
> Signed-off-by: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx>
> Reviewed-by: Marek Behún <kabel@xxxxxxxxxx>
> ---
> v6:
> - Add Reviewed-by,
> - Reorder operations in ht16k33_led_probe() to ease future conversion
> to device properties,
> --- a/drivers/auxdisplay/ht16k33.c
> +++ b/drivers/auxdisplay/ht16k33.c
> @@ -425,6 +477,35 @@ static void ht16k33_seg14_update(struct work_struct
> *work)
> i2c_smbus_write_i2c_block_data(priv->client, 0, ARRAY_SIZE(buf), buf);
> }
>
> +static int ht16k33_led_probe(struct device *dev, struct led_classdev *led,
> + unsigned int brightness)
> +{
> + struct led_init_data init_data = {};
> + struct device_node *node;
> + int err;
> +
> + /* The LED is optional */
> + node = of_get_child_by_name(dev->of_node, "led");
> + if (!node)
> + return 0;
> +
> + init_data.fwnode = of_fwnode_handle(node);
> + init_data.devicename = "auxdisplay";
> + init_data.devname_mandatory = true;
> +
> + led->brightness_set_blocking = ht16k33_brightness_set_blocking;
> + led->blink_set = ht16k33_blink_set;
> + led->flags = LED_CORE_SUSPENDRESUME;
> + led->brightness = brightness;
> + led->max_brightness = MAX_BRIGHTNESS;
What do you think about adding a default trigger and making it 'backlight'?
led->default_trigger = "blacklight";
Or as an alternative, suggesting linux,default-trigger = "backlight" in the
docs? Since the led class won't respond to blank events by just making it's
function LED_FUNCTION_BACKLIGHT.
led {
function = LED_FUNCTION_BACKLIGHT;
color = <LED_COLOR_ID_GREEN>;
linux,default-trigger = "backlight";
};
The latter makes perfect sense to me. Will do.
I noticed blanking is broken. The backlight device (or LED device with
backlight trigger) doens't get notified when the framebuffer is blanked since
the driver doesn't implement fb_blank.
Right now:
echo 1 > /sys/class/graphics/fb0/blank
|
sh: write error: Invalid argument
Due to:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/video/fbdev/core/fbmem.c?h=v5.15-rc3#n1078
That's a pre-existing problem, righ? ;-)
Something like this fixes it.
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index 89ee5b4b3dfc..0883d5252c81 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -346,6 +346,15 @@ static int ht16k33_mmap(struct fb_info *info, struct
vm_area_struct *vma)
return vm_map_pages_zero(vma, &pages, 1);
}
+/*
+ * Blank events will be passed to the backlight device (or the LED device if
+ * it's trigger is 'backlight') when we return 0 here.
+ */
+static int ht16k33_blank(int blank, struct fb_info *info)
+{
+ return 0;
+}
+
static const struct fb_ops ht16k33_fb_ops = {
.owner = THIS_MODULE,
.fb_read = fb_sys_read,
@@ -354,6 +363,7 @@ static const struct fb_ops ht16k33_fb_ops = {
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
.fb_mmap = ht16k33_mmap,
+ .fb_blank = ht16k33_blank,
};
/*
Feel free to include (something like) this in the patch stack.
Thanks, will do.
> +
> + err = devm_led_classdev_register_ext(dev, led, &init_data);
> + if (err)
> + dev_err(dev, "Failed to register LED\n");
You might want to call ht16k33_brightness_set(priv, brightness) here to get a
know value into the display setup register (0x80).
Right now if I enable hardware blinking and (soft)reboot my board it keeps on
blinking even after a re-probe.
I don't have that issue.
Aha, ht16k33_seg_probe() calls ht16k33_brightness_set(), but
ht16k33_fbdev_probe() doesn't. The latter should do that, too,
when not using backwards compatibility mode.
> @@ -575,7 +660,7 @@ static int ht16k33_seg_probe(struct device *dev, struct
> ht16k33_priv *priv,
> struct ht16k33_seg *seg = &priv->seg;
> int err;
>
> - err = ht16k33_brightness_set(priv, MAX_BRIGHTNESS);
> + err = ht16k33_brightness_set(priv, brightness);
This looks like a bugfix for patch 17, maybe move this change there?
Indeed. Bad rebase. Will move.
Thanks a lot for your comments!