Skip to content

Commit d2aacaf

Browse files
committed
drm/panel: Check for already prepared/enabled in drm_panel
In a whole pile of panel drivers, we have code to make the prepare/unprepare/enable/disable callbacks behave as no-ops if they've already been called. It's silly to have this code duplicated everywhere. Add it to the core instead so that we can eventually delete it from all the drivers. Note: to get some idea of the duplicated code, try: git grep 'if.*>prepared' -- drivers/gpu/drm/panel git grep 'if.*>enabled' -- drivers/gpu/drm/panel NOTE: arguably, the right thing to do here is actually to skip this patch and simply remove all the extra checks from the individual drivers. Perhaps the checks were needed at some point in time in the past but maybe they no longer are? Certainly as we continue transitioning over to "panel_bridge" then we expect there to be much less variety in how these calls are made. When we're called as part of the bridge chain, things should be pretty simple. In fact, there was some discussion in the past about these checks [1], including a discussion about whether the checks were needed and whether the calls ought to be refcounted. At the time, I decided not to mess with it because it felt too risky. Looking closer at it now, I'm fairly certain that nothing in the existing codebase is expecting these calls to be refcounted. The only real question is whether someone is already doing something to ensure prepare()/unprepare() match and enabled()/disable() match. I would say that, even if there is something else ensuring that things match, there's enough complexity that adding an extra bool and an extra double-check here is a good idea. Let's add a drm_warn() to let people know that it's considered a minor error to take advantage of drm_panel's double-checking but we'll still make things work fine. We'll also add an entry to the official DRM todo list to remove the now pointless check from the panels after this patch lands and, eventually, fixup anyone who is triggering the new warning. [1] https://lore.kernel.org/r/20210416153909.v4.27.I502f2a92ddd36c3d28d014dd75e170c2d405a0a5@changeid Acked-by: Neil Armstrong <[email protected]> Reviewed-by: Maxime Ripard <[email protected]> Signed-off-by: Douglas Anderson <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20230727101636.v4.2.I59b417d4c29151cc2eff053369ec4822b606f375@changeid
1 parent 2ca376e commit d2aacaf

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

Documentation/gpu/todo.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,30 @@ Contact: Thomas Zimmermann <[email protected]>
460460

461461
Level: Starter
462462

463+
Clean up checks for already prepared/enabled in panels
464+
------------------------------------------------------
465+
466+
In a whole pile of panel drivers, we have code to make the
467+
prepare/unprepare/enable/disable callbacks behave as no-ops if they've already
468+
been called. To get some idea of the duplicated code, try:
469+
git grep 'if.*>prepared' -- drivers/gpu/drm/panel
470+
git grep 'if.*>enabled' -- drivers/gpu/drm/panel
471+
472+
In the patch ("drm/panel: Check for already prepared/enabled in drm_panel")
473+
we've moved this check to the core. Now we can most definitely remove the
474+
check from the individual panels and save a pile of code.
475+
476+
In adition to removing the check from the individual panels, it is believed
477+
that even the core shouldn't need this check and that should be considered
478+
an error if other code ever relies on this check. The check in the core
479+
currently prints a warning whenever something is relying on this check with
480+
dev_warn(). After a little while, we likely want to promote this to a
481+
WARN(1) to help encourage folks not to rely on this behavior.
482+
483+
Contact: Douglas Anderson <[email protected]>
484+
485+
Level: Starter/Intermediate
486+
463487

464488
Core refactorings
465489
=================

drivers/gpu/drm/drm_panel.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,22 @@ EXPORT_SYMBOL(drm_panel_remove);
105105
*/
106106
int drm_panel_prepare(struct drm_panel *panel)
107107
{
108+
int ret;
109+
108110
if (!panel)
109111
return -EINVAL;
110112

111-
if (panel->funcs && panel->funcs->prepare)
112-
return panel->funcs->prepare(panel);
113+
if (panel->prepared) {
114+
dev_warn(panel->dev, "Skipping prepare of already prepared panel\n");
115+
return 0;
116+
}
117+
118+
if (panel->funcs && panel->funcs->prepare) {
119+
ret = panel->funcs->prepare(panel);
120+
if (ret < 0)
121+
return ret;
122+
}
123+
panel->prepared = true;
113124

114125
return 0;
115126
}
@@ -128,11 +139,22 @@ EXPORT_SYMBOL(drm_panel_prepare);
128139
*/
129140
int drm_panel_unprepare(struct drm_panel *panel)
130141
{
142+
int ret;
143+
131144
if (!panel)
132145
return -EINVAL;
133146

134-
if (panel->funcs && panel->funcs->unprepare)
135-
return panel->funcs->unprepare(panel);
147+
if (!panel->prepared) {
148+
dev_warn(panel->dev, "Skipping unprepare of already unprepared panel\n");
149+
return 0;
150+
}
151+
152+
if (panel->funcs && panel->funcs->unprepare) {
153+
ret = panel->funcs->unprepare(panel);
154+
if (ret < 0)
155+
return ret;
156+
}
157+
panel->prepared = false;
136158

137159
return 0;
138160
}
@@ -155,11 +177,17 @@ int drm_panel_enable(struct drm_panel *panel)
155177
if (!panel)
156178
return -EINVAL;
157179

180+
if (panel->enabled) {
181+
dev_warn(panel->dev, "Skipping enable of already enabled panel\n");
182+
return 0;
183+
}
184+
158185
if (panel->funcs && panel->funcs->enable) {
159186
ret = panel->funcs->enable(panel);
160187
if (ret < 0)
161188
return ret;
162189
}
190+
panel->enabled = true;
163191

164192
ret = backlight_enable(panel->backlight);
165193
if (ret < 0)
@@ -187,13 +215,22 @@ int drm_panel_disable(struct drm_panel *panel)
187215
if (!panel)
188216
return -EINVAL;
189217

218+
if (!panel->enabled) {
219+
dev_warn(panel->dev, "Skipping disable of already disabled panel\n");
220+
return 0;
221+
}
222+
190223
ret = backlight_disable(panel->backlight);
191224
if (ret < 0)
192225
DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n",
193226
ret);
194227

195-
if (panel->funcs && panel->funcs->disable)
196-
return panel->funcs->disable(panel);
228+
if (panel->funcs && panel->funcs->disable) {
229+
ret = panel->funcs->disable(panel);
230+
if (ret < 0)
231+
return ret;
232+
}
233+
panel->enabled = false;
197234

198235
return 0;
199236
}

include/drm/drm_panel.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,20 @@ struct drm_panel {
198198
* the panel is powered up.
199199
*/
200200
bool prepare_prev_first;
201+
202+
/**
203+
* @prepared:
204+
*
205+
* If true then the panel has been prepared.
206+
*/
207+
bool prepared;
208+
209+
/**
210+
* @enabled:
211+
*
212+
* If true then the panel has been enabled.
213+
*/
214+
bool enabled;
201215
};
202216

203217
void drm_panel_init(struct drm_panel *panel, struct device *dev,

0 commit comments

Comments
 (0)