diff options
author | Sam Ravnborg <sam@ravnborg.org> | 2019-12-07 15:03:30 +0100 |
---|---|---|
committer | Sam Ravnborg <sam@ravnborg.org> | 2019-12-09 22:57:26 +0100 |
commit | 152dbdeab1b2571c107357a7bd59f5cd5be52e30 (patch) | |
tree | c928343816c2ef2eeff3acf351331a56d1e1350d /drivers/gpu/drm/drm_panel.c | |
parent | 5dce87a91970bf7c7ef3de5e2bff08b695d858a3 (diff) |
drm/panel: add backlight support
Panels often support backlight as specified in a device tree.
Update the drm_panel infrastructure to support this to
simplify the drivers.
With this the panel driver just needs to add the following to the
probe() function:
err = drm_panel_of_backlight(panel);
if (err)
return err;
Then drm_panel will handle all the rest.
There is one caveat with the backlight support.
If drm_panel_(enable|disable) are called multiple times
in a row then backlight_(enable|disable) will be called multiple times.
The above will happen when a panel drivers unconditionally
calls drm_panel_disable() in their shutdown() function,
whan the panel is already disabled and then shutdown() is called.
Reading the backlight code it seems safe to call
the backlight_(enable|disable) several times.
v3:
- Improve comments, fix grammar (Laurent)
- Do not fail in drm_panel_of_backlight() if no DT support (Laurent)
- Log if backlight_(enable|disable) fails (Laurent)
- Improve drm_panel_of_backlight() docs
- Updated changelog with backlight analysis (triggered by Laurent)
v2:
- Drop test of CONFIG_DRM_PANEL in header-file (Laurent)
- do not enable backlight if ->enable() returns an error
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <maxime.ripard@bootlin.com>
Cc: Sean Paul <sean@poorly.run>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20191207140353.23967-3-sam@ravnborg.org
Diffstat (limited to 'drivers/gpu/drm/drm_panel.c')
-rw-r--r-- | drivers/gpu/drm/drm_panel.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 4ab7229fb22b..a5e4084eb0e3 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -21,11 +21,13 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/backlight.h> #include <linux/err.h> #include <linux/module.h> #include <drm/drm_crtc.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> static DEFINE_MUTEX(panel_lock); static LIST_HEAD(panel_list); @@ -196,11 +198,21 @@ EXPORT_SYMBOL(drm_panel_unprepare); */ int drm_panel_enable(struct drm_panel *panel) { + int ret; + if (!panel) return -EINVAL; - if (panel->funcs && panel->funcs->enable) - return panel->funcs->enable(panel); + if (panel->funcs && panel->funcs->enable) { + ret = panel->funcs->enable(panel); + if (ret < 0) + return ret; + } + + ret = backlight_enable(panel->backlight); + if (ret < 0) + DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n", + ret); return 0; } @@ -218,9 +230,16 @@ EXPORT_SYMBOL(drm_panel_enable); */ int drm_panel_disable(struct drm_panel *panel) { + int ret; + if (!panel) return -EINVAL; + ret = backlight_disable(panel->backlight); + if (ret < 0) + DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n", + ret); + if (panel->funcs && panel->funcs->disable) return panel->funcs->disable(panel); @@ -289,6 +308,45 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) EXPORT_SYMBOL(of_drm_find_panel); #endif +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +/** + * drm_panel_of_backlight - use backlight device node for backlight + * @panel: DRM panel + * + * Use this function to enable backlight handling if your panel + * uses device tree and has a backlight phandle. + * + * When the panel is enabled backlight will be enabled after a + * successful call to &drm_panel_funcs.enable() + * + * When the panel is disabled backlight will be disabled before the + * call to &drm_panel_funcs.disable(). + * + * A typical implementation for a panel driver supporting device tree + * will call this function at probe time. Backlight will then be handled + * transparently without requiring any intervention from the driver. + * drm_panel_of_backlight() must be called after the call to drm_panel_init(). + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_panel_of_backlight(struct drm_panel *panel) +{ + struct backlight_device *backlight; + + if (!panel || !panel->dev) + return -EINVAL; + + backlight = devm_of_find_backlight(panel->dev); + + if (IS_ERR(backlight)) + return PTR_ERR(backlight); + + panel->backlight = backlight; + return 0; +} +EXPORT_SYMBOL(drm_panel_of_backlight); +#endif + MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); MODULE_DESCRIPTION("DRM panel infrastructure"); MODULE_LICENSE("GPL and additional rights"); |