Message ID | 20191202193230.21310-3-sam@ravnborg.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/panel infrastructure + backlight update | expand |
Hi Sam, Thank you for the patch. On Mon, Dec 02, 2019 at 08:32:06PM +0100, Sam Ravnborg wrote: > Panels often supports 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. > > 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> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > Cc: Maxime Ripard <maxime.ripard@bootlin.com> > Cc: Sean Paul <sean@poorly.run> > Cc: Thierry Reding <thierry.reding@gmail.com> > Cc: Sam Ravnborg <sam@ravnborg.org> > Cc: David Airlie <airlied@linux.ie> > Cc: Daniel Vetter <daniel@ffwll.ch> > --- > drivers/gpu/drm/drm_panel.c | 49 +++++++++++++++++++++++++++++++++++-- > include/drm/drm_panel.h | 23 +++++++++++++++++ > 2 files changed, 70 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c > index 2d59cdd05e50..35609c90e467 100644 > --- a/drivers/gpu/drm/drm_panel.c > +++ b/drivers/gpu/drm/drm_panel.c > @@ -21,6 +21,7 @@ > * DEALINGS IN THE SOFTWARE. > */ > > +#include <linux/backlight.h> > #include <linux/err.h> > #include <linux/module.h> > > @@ -196,13 +197,18 @@ EXPORT_SYMBOL(drm_panel_unprepare); > */ > int drm_panel_enable(struct drm_panel *panel) > { > + int ret = 0; > + > if (!panel) > return -EINVAL; > > if (panel->funcs && panel->funcs->enable) > - return panel->funcs->enable(panel); > + ret = panel->funcs->enable(panel); > > - return 0; > + if (ret >= 0) I'd write if (panel->funcs && panel->funcs->enable) { ret = panel->funcs->enable(panel); if (ret < 0) return ret; } and then handle the backlight with one less indentation level. > + backlight_enable(panel->backlight); What is backlight_enable() returns an error ? Should we at least log that ? > + > + return ret; > } > EXPORT_SYMBOL(drm_panel_enable); > > @@ -221,6 +227,8 @@ int drm_panel_disable(struct drm_panel *panel) > if (!panel) > return -EINVAL; > > + backlight_disable(panel->backlight); > + > if (panel->funcs && panel->funcs->disable) > return panel->funcs->disable(panel); > > @@ -289,6 +297,43 @@ 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 handle. s/handle/phandle/ > + * > + * When panel is enabled backlight will be enabled after a s/panel/the panel/ > + * successfull call to &drm_panel_funcs.enable() > + * > + * When panel is disabled backlight will be disabled before the Same here. > + * call to &drm_panel_funcs.disable(). > + * > + * A typical implementation for a panel driver supporting device tree > + * will call this function and then backlight just works. How about "will call this function at probe time. Backlight will then be handled transparently without requiring any intervention from the driver at runtime." > + * > + * 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"); > diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h > index ce8da64022b4..d30c98567384 100644 > --- a/include/drm/drm_panel.h > +++ b/include/drm/drm_panel.h > @@ -28,6 +28,7 @@ > #include <linux/errno.h> > #include <linux/list.h> > > +struct backlight_device; > struct device_node; > struct drm_connector; > struct drm_device; > @@ -59,6 +60,10 @@ struct display_timing; > * > * To save power when no video data is transmitted, a driver can power down > * the panel. This is the job of the .unprepare() function. > + * > + * Backlight can be handled automatically if configured using > + * drm_panel_of_backlight(). Then the driver do not need to implement the s/do not/does not/ > + * functionality to enable/disable backlight. > */ > struct drm_panel_funcs { > /** > @@ -132,6 +137,15 @@ struct drm_panel { > */ > struct device *dev; > > + /** > + * @backlight: > + * > + * Backlight device, used to turn on backlight after > + * the call to enable(), and to turn off > + * backlight before call to disable(). s/before call/before the call/ or maybe simpler s/before call to disable()/before disable()/ (and 'after enable()' above in that case). Should you mention that this field shall not be set directly by drivers, but is set by drm_panel_of_backlight() instead ? You can also reflow the text to reach the 80 columns limit :-) > + */ > + struct backlight_device *backlight; > + > /** > * @funcs: > * > @@ -183,4 +197,13 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) > } > #endif > > +#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) > +int drm_panel_of_backlight(struct drm_panel *panel); > +#else > +static inline int drm_panel_of_backlight(struct drm_panel *panel) > +{ > + return -EINVAL; Shouldn't you return 0 instead ? Otherwise panel driver that can support backlight will all fail to probe if CONFIG_BACKLIGHT_CLASS_DEVICE is disabled. > +} > +#endif > + > #endif
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 2d59cdd05e50..35609c90e467 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/backlight.h> #include <linux/err.h> #include <linux/module.h> @@ -196,13 +197,18 @@ EXPORT_SYMBOL(drm_panel_unprepare); */ int drm_panel_enable(struct drm_panel *panel) { + int ret = 0; + if (!panel) return -EINVAL; if (panel->funcs && panel->funcs->enable) - return panel->funcs->enable(panel); + ret = panel->funcs->enable(panel); - return 0; + if (ret >= 0) + backlight_enable(panel->backlight); + + return ret; } EXPORT_SYMBOL(drm_panel_enable); @@ -221,6 +227,8 @@ int drm_panel_disable(struct drm_panel *panel) if (!panel) return -EINVAL; + backlight_disable(panel->backlight); + if (panel->funcs && panel->funcs->disable) return panel->funcs->disable(panel); @@ -289,6 +297,43 @@ 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 handle. + * + * When panel is enabled backlight will be enabled after a + * successfull call to &drm_panel_funcs.enable() + * + * When 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 and then backlight just works. + * + * 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"); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index ce8da64022b4..d30c98567384 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -28,6 +28,7 @@ #include <linux/errno.h> #include <linux/list.h> +struct backlight_device; struct device_node; struct drm_connector; struct drm_device; @@ -59,6 +60,10 @@ struct display_timing; * * To save power when no video data is transmitted, a driver can power down * the panel. This is the job of the .unprepare() function. + * + * Backlight can be handled automatically if configured using + * drm_panel_of_backlight(). Then the driver do not need to implement the + * functionality to enable/disable backlight. */ struct drm_panel_funcs { /** @@ -132,6 +137,15 @@ struct drm_panel { */ struct device *dev; + /** + * @backlight: + * + * Backlight device, used to turn on backlight after + * the call to enable(), and to turn off + * backlight before call to disable(). + */ + struct backlight_device *backlight; + /** * @funcs: * @@ -183,4 +197,13 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) } #endif +#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +int drm_panel_of_backlight(struct drm_panel *panel); +#else +static inline int drm_panel_of_backlight(struct drm_panel *panel) +{ + return -EINVAL; +} +#endif + #endif
Panels often supports 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. 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> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <maxime.ripard@bootlin.com> Cc: Sean Paul <sean@poorly.run> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> --- drivers/gpu/drm/drm_panel.c | 49 +++++++++++++++++++++++++++++++++++-- include/drm/drm_panel.h | 23 +++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-)