]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/panel: himax-hx83102: Add support for DSI DCS backlight control
authorVal Packett <val@packett.cool>
Tue, 17 Feb 2026 07:00:12 +0000 (04:00 -0300)
committerNeil Armstrong <neil.armstrong@linaro.org>
Thu, 26 Mar 2026 09:00:05 +0000 (10:00 +0100)
The HTF065H045 panel based on the HX83102 controller does use DCS
commands for controlling backlight brightness. Make the driver fall back
to DCS when no external backlight has been defined in the device tree,
like many other drivers do.

Signed-off-by: Val Packett <val@packett.cool>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patch.msgid.link/20260217070121.190108-5-val@packett.cool
drivers/gpu/drm/panel/panel-himax-hx83102.c

index 34e0e956db48fdaffd664694e6cfe20494f021f9..8b2a68ee851e3950b3ed464b827646c648fa35a6 100644 (file)
@@ -7,6 +7,7 @@
  * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c
  */
 
+#include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
@@ -76,6 +77,8 @@ struct hx83102_panel_desc {
                unsigned int height_mm;
        } size;
 
+       bool has_backlight;
+
        int (*init)(struct hx83102 *ctx);
 };
 
@@ -913,6 +916,7 @@ static const struct hx83102_panel_desc holitech_htf065h045_desc = {
                .width_mm = 68,
                .height_mm = 151,
        },
+       .has_backlight = true,
        .init = holitech_htf065h045_init,
 };
 
@@ -1049,6 +1053,59 @@ static const struct drm_panel_funcs hx83102_drm_funcs = {
        .get_orientation = hx83102_get_orientation,
 };
 
+static int hx83102_bl_update_status(struct backlight_device *bl)
+{
+       struct mipi_dsi_device *dsi = bl_get_data(bl);
+       u16 brightness = backlight_get_brightness(bl);
+       int ret;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+       if (ret < 0)
+               return ret;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       return 0;
+}
+
+static int hx83102_bl_get_brightness(struct backlight_device *bl)
+{
+       struct mipi_dsi_device *dsi = bl_get_data(bl);
+       u16 brightness;
+       int ret;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
+       if (ret < 0)
+               return ret;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       return brightness;
+}
+
+static const struct backlight_ops hx83102_bl_ops = {
+       .update_status = hx83102_bl_update_status,
+       .get_brightness = hx83102_bl_get_brightness,
+};
+
+static struct backlight_device *
+hx83102_create_dcs_backlight(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       const struct backlight_properties props = {
+               .type = BACKLIGHT_RAW,
+               .brightness = 4095,
+               .max_brightness = 4095,
+       };
+
+       return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+                                             &hx83102_bl_ops, &props);
+}
+
 static int hx83102_panel_add(struct hx83102 *ctx)
 {
        struct device *dev = &ctx->dsi->dev;
@@ -1080,6 +1137,14 @@ static int hx83102_panel_add(struct hx83102 *ctx)
        if (err)
                return err;
 
+       /* Use DSI-based backlight as fallback if available */
+       if (ctx->desc->has_backlight && !ctx->base.backlight) {
+               ctx->base.backlight = hx83102_create_dcs_backlight(ctx->dsi);
+               if (IS_ERR(ctx->base.backlight))
+                       return dev_err_probe(dev, PTR_ERR(ctx->base.backlight),
+                                            "Failed to create backlight\n");
+       }
+
        ctx->base.funcs = &hx83102_drm_funcs;
        ctx->base.dev = &ctx->dsi->dev;