Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/panel: Allow powering on panel follower after panel is enabled

Some touch controllers have to be powered on after the panel's backlight
is enabled. To support these controllers, introduce .panel_enabled() and
.panel_disabling() to panel_follower_funcs and use them to power on the
device after the panel and its backlight are enabled.

Signed-off-by: Pin-yen Lin <treapking@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20250818115015.2909525-1-treapking@chromium.org

authored by

Pin-yen Lin and committed by
Douglas Anderson
2eb22214 efe927b9

+76 -11
+62 -11
drivers/gpu/drm/drm_panel.c
··· 134 134 panel->prepared = true; 135 135 136 136 list_for_each_entry(follower, &panel->followers, list) { 137 + if (!follower->funcs->panel_prepared) 138 + continue; 139 + 137 140 ret = follower->funcs->panel_prepared(follower); 138 141 if (ret < 0) 139 142 dev_info(panel->dev, "%ps failed: %d\n", ··· 182 179 mutex_lock(&panel->follower_lock); 183 180 184 181 list_for_each_entry(follower, &panel->followers, list) { 182 + if (!follower->funcs->panel_unpreparing) 183 + continue; 184 + 185 185 ret = follower->funcs->panel_unpreparing(follower); 186 186 if (ret < 0) 187 187 dev_info(panel->dev, "%ps failed: %d\n", ··· 215 209 */ 216 210 void drm_panel_enable(struct drm_panel *panel) 217 211 { 212 + struct drm_panel_follower *follower; 218 213 int ret; 219 214 220 215 if (!panel) ··· 226 219 return; 227 220 } 228 221 222 + mutex_lock(&panel->follower_lock); 223 + 229 224 if (panel->funcs && panel->funcs->enable) { 230 225 ret = panel->funcs->enable(panel); 231 226 if (ret < 0) 232 - return; 227 + goto exit; 233 228 } 234 229 panel->enabled = true; 235 230 ··· 239 230 if (ret < 0) 240 231 DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n", 241 232 ret); 233 + 234 + list_for_each_entry(follower, &panel->followers, list) { 235 + if (!follower->funcs->panel_enabled) 236 + continue; 237 + 238 + ret = follower->funcs->panel_enabled(follower); 239 + if (ret < 0) 240 + dev_info(panel->dev, "%ps failed: %d\n", 241 + follower->funcs->panel_enabled, ret); 242 + } 243 + 244 + exit: 245 + mutex_unlock(&panel->follower_lock); 242 246 } 243 247 EXPORT_SYMBOL(drm_panel_enable); 244 248 ··· 265 243 */ 266 244 void drm_panel_disable(struct drm_panel *panel) 267 245 { 246 + struct drm_panel_follower *follower; 268 247 int ret; 269 248 270 249 if (!panel) ··· 285 262 return; 286 263 } 287 264 265 + mutex_lock(&panel->follower_lock); 266 + 267 + list_for_each_entry(follower, &panel->followers, list) { 268 + if (!follower->funcs->panel_disabling) 269 + continue; 270 + 271 + ret = follower->funcs->panel_disabling(follower); 272 + if (ret < 0) 273 + dev_info(panel->dev, "%ps failed: %d\n", 274 + follower->funcs->panel_disabling, ret); 275 + } 276 + 288 277 ret = backlight_disable(panel->backlight); 289 278 if (ret < 0) 290 279 DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n", ··· 305 270 if (panel->funcs && panel->funcs->disable) { 306 271 ret = panel->funcs->disable(panel); 307 272 if (ret < 0) 308 - return; 273 + goto exit; 309 274 } 310 275 panel->enabled = false; 276 + 277 + exit: 278 + mutex_unlock(&panel->follower_lock); 311 279 } 312 280 EXPORT_SYMBOL(drm_panel_disable); 313 281 ··· 577 539 * @follower_dev: The 'struct device' for the follower. 578 540 * @follower: The panel follower descriptor for the follower. 579 541 * 580 - * A panel follower is called right after preparing the panel and right before 581 - * unpreparing the panel. It's primary intention is to power on an associated 582 - * touchscreen, though it could be used for any similar devices. Multiple 583 - * devices are allowed the follow the same panel. 542 + * A panel follower is called right after preparing/enabling the panel and right 543 + * before unpreparing/disabling the panel. It's primary intention is to power on 544 + * an associated touchscreen, though it could be used for any similar devices. 545 + * Multiple devices are allowed the follow the same panel. 584 546 * 585 - * If a follower is added to a panel that's already been turned on, the 586 - * follower's prepare callback is called right away. 547 + * If a follower is added to a panel that's already been prepared/enabled, the 548 + * follower's prepared/enabled callback is called right away. 587 549 * 588 550 * The "panel" property of the follower points to the panel to be followed. 589 551 * ··· 607 569 mutex_lock(&panel->follower_lock); 608 570 609 571 list_add_tail(&follower->list, &panel->followers); 610 - if (panel->prepared) { 572 + if (panel->prepared && follower->funcs->panel_prepared) { 611 573 ret = follower->funcs->panel_prepared(follower); 612 574 if (ret < 0) 613 575 dev_info(panel->dev, "%ps failed: %d\n", 614 576 follower->funcs->panel_prepared, ret); 577 + } 578 + if (panel->enabled && follower->funcs->panel_enabled) { 579 + ret = follower->funcs->panel_enabled(follower); 580 + if (ret < 0) 581 + dev_info(panel->dev, "%ps failed: %d\n", 582 + follower->funcs->panel_enabled, ret); 615 583 } 616 584 617 585 mutex_unlock(&panel->follower_lock); ··· 631 587 * @follower: The panel follower descriptor for the follower. 632 588 * 633 589 * Undo drm_panel_add_follower(). This includes calling the follower's 634 - * unprepare function if we're removed from a panel that's currently prepared. 590 + * unpreparing/disabling function if we're removed from a panel that's currently 591 + * prepared/enabled. 635 592 * 636 593 * Return: 0 or an error code. 637 594 */ ··· 643 598 644 599 mutex_lock(&panel->follower_lock); 645 600 646 - if (panel->prepared) { 601 + if (panel->enabled && follower->funcs->panel_disabling) { 602 + ret = follower->funcs->panel_disabling(follower); 603 + if (ret < 0) 604 + dev_info(panel->dev, "%ps failed: %d\n", 605 + follower->funcs->panel_disabling, ret); 606 + } 607 + if (panel->prepared && follower->funcs->panel_unpreparing) { 647 608 ret = follower->funcs->panel_unpreparing(follower); 648 609 if (ret < 0) 649 610 dev_info(panel->dev, "%ps failed: %d\n",
+14
include/drm/drm_panel.h
··· 160 160 * Called before the panel is powered off. 161 161 */ 162 162 int (*panel_unpreparing)(struct drm_panel_follower *follower); 163 + 164 + /** 165 + * @panel_enabled: 166 + * 167 + * Called after the panel and the backlight have been enabled. 168 + */ 169 + int (*panel_enabled)(struct drm_panel_follower *follower); 170 + 171 + /** 172 + * @panel_disabling: 173 + * 174 + * Called before the panel and the backlight are disabled. 175 + */ 176 + int (*panel_disabling)(struct drm_panel_follower *follower); 163 177 }; 164 178 165 179 struct drm_panel_follower {