Modern OLED panels often need to vary their prepare commands based on the mode being set (resolution and refresh rate). Introduce a new variant of the drm_panel_prepare callback that passes the chosen mode as an argument to allow for this.
Signed-off-by: Val Packett <[email protected]> --- drivers/gpu/drm/bridge/panel.c | 8 ++++++-- drivers/gpu/drm/drm_panel.c | 15 +++++++++++++-- include/drm/drm_panel.h | 12 ++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 184a8b7049a7..58c9d9c44363 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -116,7 +116,7 @@ static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge, struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); struct drm_encoder *encoder = bridge->encoder; struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder); if (!crtc) @@ -126,7 +126,11 @@ static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge, if (old_crtc_state && old_crtc_state->self_refresh_active) return; - drm_panel_prepare(panel_bridge->panel); + new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc); + if (!new_crtc_state) + return; + + drm_panel_prepare_for_mode(panel_bridge->panel, &new_crtc_state->mode); } static void panel_bridge_atomic_enable(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index d1e6598ea3bc..cc313f778253 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -112,6 +112,13 @@ EXPORT_SYMBOL(drm_panel_remove); * drm_panel_disable() afterwards. */ void drm_panel_prepare(struct drm_panel *panel) +{ + drm_panel_prepare_for_mode(panel, NULL); +} +EXPORT_SYMBOL(drm_panel_prepare); + +void drm_panel_prepare_for_mode(struct drm_panel *panel, + struct drm_display_mode *mode) { struct drm_panel_follower *follower; int ret; @@ -126,7 +133,11 @@ void drm_panel_prepare(struct drm_panel *panel) mutex_lock(&panel->follower_lock); - if (panel->funcs && panel->funcs->prepare) { + if (panel->funcs && panel->funcs->prepare_for_mode && mode) { + ret = panel->funcs->prepare_for_mode(panel, mode); + if (ret < 0) + goto exit; + } else if (panel->funcs && panel->funcs->prepare) { ret = panel->funcs->prepare(panel); if (ret < 0) goto exit; @@ -146,7 +157,7 @@ void drm_panel_prepare(struct drm_panel *panel) exit: mutex_unlock(&panel->follower_lock); } -EXPORT_SYMBOL(drm_panel_prepare); +EXPORT_SYMBOL(drm_panel_prepare_for_mode); /** * drm_panel_unprepare - power off a panel diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 2407bfa60236..0c2e5232ab20 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -80,6 +80,16 @@ struct drm_panel_funcs { */ int (*prepare)(struct drm_panel *panel); + /** + * @prepare_for_mode: + * + * Turn on panel and perform set up, with awareness of the mode being set. + * + * This function is optional. + */ + int (*prepare_for_mode)(struct drm_panel *panel, + struct drm_display_mode *mode); + /** * @enable: * @@ -331,6 +341,8 @@ void drm_panel_add(struct drm_panel *panel); void drm_panel_remove(struct drm_panel *panel); void drm_panel_prepare(struct drm_panel *panel); +void drm_panel_prepare_for_mode(struct drm_panel *panel, + struct drm_display_mode *mode); void drm_panel_unprepare(struct drm_panel *panel); void drm_panel_enable(struct drm_panel *panel); -- 2.53.0

