summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2022-02-23 11:11:08 -0800
committerRob Clark <robdclark@chromium.org>2022-02-25 07:59:58 -0800
commit9e4dde28e9cd34ee13a6b7247f0857fb49fd3f19 (patch)
tree17fee6c9091477bc662c43c372e91dfa203539f9 /drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
parentdb22583d6c7da2b20965514a123705cf753c931a (diff)
downloadlinux-9e4dde28e9cd34ee13a6b7247f0857fb49fd3f19.tar.bz2
drm/msm: Avoid dirtyfb stalls on video mode displays (v2)
Someone on IRC once asked an innocent enough sounding question: Why with xf86-video-modesetting is es2gears limited at 120fps. So I broke out the perfetto tracing mesa MR and took a look. It turns out the problem was drm_atomic_helper_dirtyfb(), which would end up waiting for vblank.. es2gears would rapidly push two frames to Xorg, which would blit them to screen and in idle hook (I assume) call the DIRTYFB ioctl. Which in turn would do an atomic update to flush the dirty rects, which would stall until the next vblank. And then the whole process would repeat. But this is a bit silly, we only need dirtyfb for command mode DSI panels. So track in plane state whether dirtyfb is required, and track in the fb how many attached planes require dirtyfb so that we can skip it when not required. (Note, mdp4 does not actually have cmd mode support.) Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Link: https://lore.kernel.org/r/20220223191118.881321-1-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c')
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index c6b69afcbac8..b176338ab59b 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -8,6 +8,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_print.h>
#include "mdp5_kms.h"
@@ -140,18 +141,34 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
.atomic_print_state = mdp5_plane_atomic_print_state,
};
+static int mdp5_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ struct msm_drm_private *priv = plane->dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+ bool needs_dirtyfb = to_mdp5_plane_state(new_state)->needs_dirtyfb;
+
+ if (!new_state->fb)
+ return 0;
+
+ drm_gem_plane_helper_prepare_fb(plane, new_state);
+
+ return msm_framebuffer_prepare(new_state->fb, kms->aspace, needs_dirtyfb);
+}
+
static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct msm_kms *kms = &mdp5_kms->base.base;
struct drm_framebuffer *fb = old_state->fb;
+ bool needed_dirtyfb = to_mdp5_plane_state(old_state)->needs_dirtyfb;
if (!fb)
return;
DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id);
- msm_framebuffer_cleanup(fb, kms->aspace);
+ msm_framebuffer_cleanup(fb, kms->aspace, needed_dirtyfb);
}
static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
@@ -437,7 +454,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
- .prepare_fb = msm_atomic_prepare_fb,
+ .prepare_fb = mdp5_plane_prepare_fb,
.cleanup_fb = mdp5_plane_cleanup_fb,
.atomic_check = mdp5_plane_atomic_check,
.atomic_update = mdp5_plane_atomic_update,