summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_plane_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_plane_helper.c')
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 18a1ac6ac22f..5ba5792bfdba 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -142,6 +142,17 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
{
int hscale, vscale;
+ if (!fb) {
+ *visible = false;
+ return 0;
+ }
+
+ /* crtc should only be NULL when disabling (i.e., !fb) */
+ if (WARN_ON(!crtc)) {
+ *visible = false;
+ return 0;
+ }
+
if (!crtc->enabled && !can_update_disabled) {
DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
return -EINVAL;
@@ -155,11 +166,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
return -ERANGE;
}
- if (!fb) {
- *visible = false;
- return 0;
- }
-
*visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
if (!*visible)
/*
@@ -429,7 +435,8 @@ int drm_plane_helper_commit(struct drm_plane *plane,
goto out;
}
- if (plane_funcs->prepare_fb && plane_state->fb) {
+ if (plane_funcs->prepare_fb && plane_state->fb &&
+ plane_state->fb != old_fb) {
ret = plane_funcs->prepare_fb(plane, plane_state->fb);
if (ret)
goto out;
@@ -443,13 +450,28 @@ int drm_plane_helper_commit(struct drm_plane *plane,
crtc_funcs[i]->atomic_begin(crtc[i]);
}
- plane_funcs->atomic_update(plane, plane_state);
+ /*
+ * Drivers may optionally implement the ->atomic_disable callback, so
+ * special-case that here.
+ */
+ if (drm_atomic_plane_disabling(plane, plane_state) &&
+ plane_funcs->atomic_disable)
+ plane_funcs->atomic_disable(plane, plane_state);
+ else
+ plane_funcs->atomic_update(plane, plane_state);
for (i = 0; i < 2; i++) {
if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
crtc_funcs[i]->atomic_flush(crtc[i]);
}
+ /*
+ * If we only moved the plane and didn't change fb's, there's no need to
+ * wait for vblank.
+ */
+ if (plane->state->fb == old_fb)
+ goto out;
+
for (i = 0; i < 2; i++) {
if (!crtc[i])
continue;
@@ -478,7 +500,7 @@ out:
}
/**
- * drm_plane_helper_update() - Helper for primary plane update
+ * drm_plane_helper_update() - Transitional helper for plane update
* @plane: plane object to update
* @crtc: owning CRTC of owning plane
* @fb: framebuffer to flip onto plane
@@ -517,6 +539,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
if (!plane_state)
return -ENOMEM;
+ plane_state->plane = plane;
plane_state->crtc = crtc;
drm_atomic_set_fb_for_plane(plane_state, fb);
@@ -534,7 +557,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
EXPORT_SYMBOL(drm_plane_helper_update);
/**
- * drm_plane_helper_disable() - Helper for primary plane disable
+ * drm_plane_helper_disable() - Transitional helper for plane disable
* @plane: plane to disable
*
* Provides a default plane disable handler using the atomic plane update
@@ -563,6 +586,7 @@ int drm_plane_helper_disable(struct drm_plane *plane)
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
if (!plane_state)
return -ENOMEM;
+ plane_state->plane = plane;
plane_state->crtc = NULL;
drm_atomic_set_fb_for_plane(plane_state, NULL);