diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 5e684564d7..45b7e14021 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -602,6 +602,7 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; + struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_plane *plane; struct drm_plane_state *plane_state; @@ -663,6 +664,9 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms, if (ops & SDE_KMS_OPS_CLEANUP_PLANE_FB) { SDE_DEBUG("cleanup planes\n"); drm_atomic_helper_cleanup_planes(dev, state); + for_each_oldnew_plane_in_state(state, plane, + old_plane_state, new_plane_state, i) + sde_plane_destroy_fb(old_plane_state); } if (ops & SDE_KMS_OPS_SECURE_STATE_CHANGE) { SDE_DEBUG("secure ctrl\n"); diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index 50845af5bc..c03171bdd5 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -4043,6 +4043,28 @@ static void sde_plane_destroy(struct drm_plane *plane) } } +void sde_plane_destroy_fb(struct drm_plane_state *state) +{ + struct sde_plane_state *pstate; + + if (!state) { + SDE_ERROR("invalid arg state %d\n", !state); + return; + } + + pstate = to_sde_plane_state(state); + + if (sde_plane_get_property(pstate, PLANE_PROP_FB_TRANSLATION_MODE) == + SDE_DRM_FB_SEC) { + /* remove ref count for frame buffers */ + if (state->fb) { + drm_framebuffer_put(state->fb); + state->fb = NULL; + } + } + +} + static void sde_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { diff --git a/msm/sde/sde_plane.h b/msm/sde/sde_plane.h index ed16e69d5b..316bd75f47 100644 --- a/msm/sde/sde_plane.h +++ b/msm/sde/sde_plane.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -133,6 +133,12 @@ struct sde_multirect_plane_states { #define sde_plane_get_property(S, X) ((S) && ((X) < PLANE_PROP_COUNT) ? \ ((S)->property_values[(X)].value) : 0) +/** + * sde_plane_destroy_fb - destroy fb object and clear fb + * @state: old plane state + */ +void sde_plane_destroy_fb(struct drm_plane_state *state); + /** * sde_plane_pipe - return sspp identifier for the given plane * @plane: Pointer to DRM plane object