Skip to content

Commit 152dbde

Browse files
committed
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 <[email protected]> Reviewed-by: Laurent Pinchart <[email protected]> Cc: Thierry Reding <[email protected]> Cc: Laurent Pinchart <[email protected]> Cc: Maarten Lankhorst <[email protected]> Cc: Maxime Ripard <[email protected]> Cc: Sean Paul <[email protected]> Cc: David Airlie <[email protected]> Cc: Daniel Vetter <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 5dce87a commit 152dbde

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

drivers/gpu/drm/drm_panel.c

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
* DEALINGS IN THE SOFTWARE.
2222
*/
2323

24+
#include <linux/backlight.h>
2425
#include <linux/err.h>
2526
#include <linux/module.h>
2627

2728
#include <drm/drm_crtc.h>
2829
#include <drm/drm_panel.h>
30+
#include <drm/drm_print.h>
2931

3032
static DEFINE_MUTEX(panel_lock);
3133
static LIST_HEAD(panel_list);
@@ -196,11 +198,21 @@ EXPORT_SYMBOL(drm_panel_unprepare);
196198
*/
197199
int drm_panel_enable(struct drm_panel *panel)
198200
{
201+
int ret;
202+
199203
if (!panel)
200204
return -EINVAL;
201205

202-
if (panel->funcs && panel->funcs->enable)
203-
return panel->funcs->enable(panel);
206+
if (panel->funcs && panel->funcs->enable) {
207+
ret = panel->funcs->enable(panel);
208+
if (ret < 0)
209+
return ret;
210+
}
211+
212+
ret = backlight_enable(panel->backlight);
213+
if (ret < 0)
214+
DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n",
215+
ret);
204216

205217
return 0;
206218
}
@@ -218,9 +230,16 @@ EXPORT_SYMBOL(drm_panel_enable);
218230
*/
219231
int drm_panel_disable(struct drm_panel *panel)
220232
{
233+
int ret;
234+
221235
if (!panel)
222236
return -EINVAL;
223237

238+
ret = backlight_disable(panel->backlight);
239+
if (ret < 0)
240+
DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n",
241+
ret);
242+
224243
if (panel->funcs && panel->funcs->disable)
225244
return panel->funcs->disable(panel);
226245

@@ -289,6 +308,45 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np)
289308
EXPORT_SYMBOL(of_drm_find_panel);
290309
#endif
291310

311+
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
312+
/**
313+
* drm_panel_of_backlight - use backlight device node for backlight
314+
* @panel: DRM panel
315+
*
316+
* Use this function to enable backlight handling if your panel
317+
* uses device tree and has a backlight phandle.
318+
*
319+
* When the panel is enabled backlight will be enabled after a
320+
* successful call to &drm_panel_funcs.enable()
321+
*
322+
* When the panel is disabled backlight will be disabled before the
323+
* call to &drm_panel_funcs.disable().
324+
*
325+
* A typical implementation for a panel driver supporting device tree
326+
* will call this function at probe time. Backlight will then be handled
327+
* transparently without requiring any intervention from the driver.
328+
* drm_panel_of_backlight() must be called after the call to drm_panel_init().
329+
*
330+
* Return: 0 on success or a negative error code on failure.
331+
*/
332+
int drm_panel_of_backlight(struct drm_panel *panel)
333+
{
334+
struct backlight_device *backlight;
335+
336+
if (!panel || !panel->dev)
337+
return -EINVAL;
338+
339+
backlight = devm_of_find_backlight(panel->dev);
340+
341+
if (IS_ERR(backlight))
342+
return PTR_ERR(backlight);
343+
344+
panel->backlight = backlight;
345+
return 0;
346+
}
347+
EXPORT_SYMBOL(drm_panel_of_backlight);
348+
#endif
349+
292350
MODULE_AUTHOR("Thierry Reding <[email protected]>");
293351
MODULE_DESCRIPTION("DRM panel infrastructure");
294352
MODULE_LICENSE("GPL and additional rights");

include/drm/drm_panel.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/errno.h>
2929
#include <linux/list.h>
3030

31+
struct backlight_device;
3132
struct device_node;
3233
struct drm_connector;
3334
struct drm_device;
@@ -59,6 +60,10 @@ struct display_timing;
5960
*
6061
* To save power when no video data is transmitted, a driver can power down
6162
* the panel. This is the job of the .unprepare() function.
63+
*
64+
* Backlight can be handled automatically if configured using
65+
* drm_panel_of_backlight(). Then the driver does not need to implement the
66+
* functionality to enable/disable backlight.
6267
*/
6368
struct drm_panel_funcs {
6469
/**
@@ -144,6 +149,17 @@ struct drm_panel {
144149
*/
145150
struct device *dev;
146151

152+
/**
153+
* @backlight:
154+
*
155+
* Backlight device, used to turn on backlight after the call
156+
* to enable(), and to turn off backlight before the call to
157+
* disable().
158+
* backlight is set by drm_panel_of_backlight() and drivers
159+
* shall not assign it.
160+
*/
161+
struct backlight_device *backlight;
162+
147163
/**
148164
* @funcs:
149165
*
@@ -195,4 +211,13 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
195211
}
196212
#endif
197213

214+
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
215+
int drm_panel_of_backlight(struct drm_panel *panel);
216+
#else
217+
static inline int drm_panel_of_backlight(struct drm_panel *panel)
218+
{
219+
return 0;
220+
}
221+
#endif
222+
198223
#endif

0 commit comments

Comments
 (0)