aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonard Crestez <leonard.crestez@nxp.com>2018-09-17 09:42:15 -0400
committerStefan Agner <stefan@agner.ch>2018-09-26 16:07:40 -0400
commit9f19fd3bd894d694bfb4a352d649bd972ff7e43b (patch)
tree11c259551c67676566c03c956b25806a1c1ef6a0
parentf0525a1c922eefe8cb1a23a026ea90bad400797e (diff)
drm/mxsfb: Switch to drm_atomic_helper_commit_tail_rpm
The lcdif block is only powered on when display is active so plane updates when not enabled are not valid. Writing to an unpowered IP block is mostly ignored but can trigger bus errors on some chips. Prevent this situation by switching to drm_atomic_helper_commit_tail_rpm and having the drm core ensure atomic_plane_update is only called while the crtc is active. This avoids having to keep track of "enabled" bits inside the mxsfb driver. This also requires handling the vblank event for disable from mxsfb_pipe_disable. Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> Suggested-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/c19c0c00ed42e8e8f7965aa4821ac295abc5cd05.1537191359.git.leonard.crestez@nxp.com
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 5199a1febc01..2393e6d16ffd 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -98,6 +98,10 @@ static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
98 .atomic_commit = drm_atomic_helper_commit, 98 .atomic_commit = drm_atomic_helper_commit,
99}; 99};
100 100
101static const struct drm_mode_config_helper_funcs mxsfb_mode_config_helpers = {
102 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
103};
104
101static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe, 105static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
102 struct drm_crtc_state *crtc_state, 106 struct drm_crtc_state *crtc_state,
103 struct drm_plane_state *plane_state) 107 struct drm_plane_state *plane_state)
@@ -115,11 +119,21 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
115{ 119{
116 struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); 120 struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
117 struct drm_device *drm = pipe->plane.dev; 121 struct drm_device *drm = pipe->plane.dev;
122 struct drm_crtc *crtc = &pipe->crtc;
123 struct drm_pending_vblank_event *event;
118 124
119 drm_panel_disable(mxsfb->panel); 125 drm_panel_disable(mxsfb->panel);
120 mxsfb_crtc_disable(mxsfb); 126 mxsfb_crtc_disable(mxsfb);
121 drm_panel_unprepare(mxsfb->panel); 127 drm_panel_unprepare(mxsfb->panel);
122 pm_runtime_put_sync(drm->dev); 128 pm_runtime_put_sync(drm->dev);
129
130 spin_lock_irq(&drm->event_lock);
131 event = crtc->state->event;
132 if (event) {
133 crtc->state->event = NULL;
134 drm_crtc_send_vblank_event(crtc, event);
135 }
136 spin_unlock_irq(&drm->event_lock);
123} 137}
124 138
125static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe, 139static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -234,6 +248,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
234 drm->mode_config.max_width = MXSFB_MAX_XRES; 248 drm->mode_config.max_width = MXSFB_MAX_XRES;
235 drm->mode_config.max_height = MXSFB_MAX_YRES; 249 drm->mode_config.max_height = MXSFB_MAX_YRES;
236 drm->mode_config.funcs = &mxsfb_mode_config_funcs; 250 drm->mode_config.funcs = &mxsfb_mode_config_funcs;
251 drm->mode_config.helper_private = &mxsfb_mode_config_helpers;
237 252
238 drm_mode_config_reset(drm); 253 drm_mode_config_reset(drm);
239 254