diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 00482c9037..8166f8d296 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -42,9 +42,6 @@ #include "sde_trace.h" #include "msm_drv.h" -#define SDE_PSTATES_MAX (SDE_STAGE_MAX * 4) -#define SDE_MULTIRECT_PLANE_MAX (SDE_STAGE_MAX * 2) - struct sde_crtc_custom_events { u32 event; int (*func)(struct drm_crtc *crtc, bool en, @@ -1257,13 +1254,6 @@ static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) sde_cp_crtc_res_change(crtc); } -struct plane_state { - struct sde_plane_state *sde_pstate; - const struct drm_plane_state *drm_pstate; - int stage; - u32 pipe_id; -}; - static int pstate_cmp(const void *a, const void *b) { struct plane_state *pa = (struct plane_state *)a; @@ -1297,24 +1287,29 @@ static int pstate_cmp(const void *a, const void *b) * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ -static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc, - struct plane_state *pstates, int cnt) +static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc) { struct plane_state *prv_pstate, *cur_pstate; enum sde_layout prev_layout, cur_layout; + struct sde_crtc *sde_crtc; struct sde_rect left_rect, right_rect; struct sde_kms *sde_kms; + struct plane_state *pstates; int32_t left_pid, right_pid; int32_t stage; int i, rc = 0; + sde_crtc = to_sde_crtc(crtc); + sde_kms = _sde_crtc_get_kms(crtc); - if (!sde_kms || !sde_kms->catalog) { + if (!sde_kms || !sde_kms->catalog || !sde_crtc) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } - for (i = 1; i < cnt; i++) { + pstates = sde_crtc->pstates; + + for (i = 1; i < sde_crtc->num_pstates; i++) { prv_pstate = &pstates[i - 1]; cur_pstate = &pstates[i]; prev_layout = prv_pstate->sde_pstate->layout; @@ -1492,7 +1487,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct sde_crtc_state *cstate; struct sde_plane_state *pstate = NULL; - struct plane_state *pstates = NULL; + struct plane_state *pstates; struct sde_format *format; struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; @@ -1513,11 +1508,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, ctl = mixer->hw_ctl; lm = mixer->hw_lm; cstate = to_sde_crtc_state(crtc->state); - pstates = kcalloc(SDE_PSTATES_MAX, - sizeof(struct plane_state), GFP_KERNEL); - if (!pstates) - return; + pstates = sde_crtc->pstates; + memset(sde_crtc->pstates, 0, sizeof(sde_crtc->pstates)); memset(fetch_active, 0, sizeof(fetch_active)); memset(zpos_cnt, 0, sizeof(zpos_cnt)); @@ -1550,7 +1543,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); if (!format) { SDE_ERROR("invalid format\n"); - goto end; + return; } blend_type = sde_plane_get_property(pstate, @@ -1641,8 +1634,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, } } -end: - kfree(pstates); } static void _sde_crtc_swap_mixers_for_right_partial_update( @@ -4523,12 +4514,19 @@ end: } static int _sde_crtc_check_secure_blend_config(struct drm_crtc *crtc, - struct drm_crtc_state *state, struct plane_state pstates[], - struct sde_crtc_state *cstate, struct sde_kms *sde_kms, - int cnt, int secure, int fb_ns, int fb_sec, int fb_sec_dir) + struct drm_crtc_state *state, struct sde_crtc_state *cstate, + struct sde_kms *sde_kms, int secure, int fb_ns, + int fb_sec, int fb_sec_dir) { struct drm_plane *plane; - int i; + int i, cnt; + struct plane_state *pstates; + struct sde_crtc *sde_crtc; + + sde_crtc = to_sde_crtc(crtc); + cnt = sde_crtc->num_pstates; + pstates = sde_crtc->pstates; + if (secure == SDE_DRM_SEC_ONLY) { /* * validate planes - only fb_sec_dir is allowed during sec_crtc @@ -4725,8 +4723,7 @@ static int _sde_crtc_check_secure_conn(struct drm_crtc *crtc, } static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, - struct drm_crtc_state *state, struct plane_state pstates[], - int cnt) + struct drm_crtc_state *state) { struct sde_crtc_state *cstate; struct sde_kms *sde_kms; @@ -4754,8 +4751,8 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, if (rc) return rc; - rc = _sde_crtc_check_secure_blend_config(crtc, state, pstates, cstate, - sde_kms, cnt, secure, fb_ns, fb_sec, fb_sec_dir); + rc = _sde_crtc_check_secure_blend_config(crtc, state, cstate, + sde_kms, secure, fb_ns, fb_sec, fb_sec_dir); if (rc) return rc; @@ -4784,10 +4781,7 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_display_mode *mode, - struct plane_state *pstates, - struct drm_plane *plane, - struct sde_multirect_plane_states *multirect_plane, - int *cnt) + struct drm_plane *plane) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; @@ -4796,6 +4790,9 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, int rc = 0, multirect_count = 0, i, mixer_width, mixer_height; int inc_sde_stage = 0; struct sde_kms *kms; + int *cnt; + struct plane_state *pstates; + struct sde_multirect_plane_states *multirect_plane; sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); @@ -4806,6 +4803,13 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, return -EINVAL; } + cnt = &sde_crtc->num_pstates; + pstates = sde_crtc->pstates; + multirect_plane = sde_crtc->multirect; + + *cnt = 0; + memset(sde_crtc->pstates, 0, sizeof(sde_crtc->pstates)); + memset(sde_crtc->multirect, 0, sizeof(sde_crtc->multirect)); memset(pipe_staged, 0, sizeof(pipe_staged)); mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, mode); @@ -4911,16 +4915,16 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, static int _sde_crtc_check_zpos(struct drm_crtc_state *state, struct sde_crtc *sde_crtc, - struct plane_state *pstates, struct sde_crtc_state *cstate, - struct drm_display_mode *mode, - int cnt) + struct drm_display_mode *mode) { int rc = 0, i, z_pos; u32 zpos_cnt = 0; struct drm_crtc *crtc; struct sde_kms *kms; enum sde_layout layout; + int cnt; + struct plane_state *pstates; crtc = &sde_crtc->base; kms = _sde_crtc_get_kms(crtc); @@ -4930,6 +4934,9 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state, return -EINVAL; } + pstates = sde_crtc->pstates; + cnt = sde_crtc->num_pstates; + sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); @@ -4983,16 +4990,14 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state, } static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc, - struct drm_crtc_state *state, - struct plane_state *pstates, - struct sde_multirect_plane_states *multirect_plane) + struct drm_crtc_state *state) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct sde_kms *kms; struct drm_plane *plane = NULL; struct drm_display_mode *mode; - int rc = 0, cnt = 0; + int rc = 0; kms = _sde_crtc_get_kms(crtc); @@ -5004,19 +5009,19 @@ static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc, sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); mode = &state->adjusted_mode; + sde_crtc->num_pstates = 0; /* get plane state for all drm planes associated with crtc state */ - rc = _sde_crtc_check_get_pstates(crtc, state, mode, pstates, - plane, multirect_plane, &cnt); + rc = _sde_crtc_check_get_pstates(crtc, state, mode, plane); if (rc) return rc; /* assign mixer stages based on sorted zpos property */ - rc = _sde_crtc_check_zpos(state, sde_crtc, pstates, cstate, mode, cnt); + rc = _sde_crtc_check_zpos(state, sde_crtc, cstate, mode); if (rc) return rc; - rc = _sde_crtc_check_secure_state(crtc, state, pstates, cnt); + rc = _sde_crtc_check_secure_state(crtc, state); if (rc) return rc; @@ -5026,7 +5031,7 @@ static int _sde_crtc_atomic_check_pstates(struct drm_crtc *crtc, * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ - rc = _sde_crtc_validate_src_split_order(crtc, pstates, cnt); + rc = _sde_crtc_validate_src_split_order(crtc); if (rc) return rc; @@ -5094,11 +5099,9 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, { struct drm_device *dev; struct sde_crtc *sde_crtc; - struct plane_state *pstates = NULL; struct sde_crtc_state *cstate; struct drm_display_mode *mode; int rc = 0; - struct sde_multirect_plane_states *multirect_plane = NULL; struct drm_connector *conn; struct drm_connector_list_iter conn_iter; @@ -5117,18 +5120,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } - pstates = kcalloc(SDE_PSTATES_MAX, - sizeof(struct plane_state), GFP_KERNEL); - - multirect_plane = kcalloc(SDE_MULTIRECT_PLANE_MAX, - sizeof(struct sde_multirect_plane_states), - GFP_KERNEL); - - if (!pstates || !multirect_plane) { - rc = -ENOMEM; - goto end; - } - mode = &state->adjusted_mode; SDE_DEBUG("%s: check", sde_crtc->name); @@ -5164,8 +5155,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, _sde_crtc_setup_is_ppsplit(state); _sde_crtc_setup_lm_bounds(crtc, state); - rc = _sde_crtc_atomic_check_pstates(crtc, state, pstates, - multirect_plane); + rc = _sde_crtc_atomic_check_pstates(crtc, state); if (rc) { SDE_ERROR("crtc%d failed pstate check %d\n", crtc->base.id, rc); goto end; @@ -5191,8 +5181,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } end: - kfree(pstates); - kfree(multirect_plane); return rc; } diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 2d71ead635..47bb0b2038 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -29,6 +29,9 @@ #include "sde_core_perf.h" #include "sde_hw_ds.h" +#define SDE_PSTATES_MAX (SDE_STAGE_MAX * 4) +#define SDE_MULTIRECT_PLANE_MAX (SDE_STAGE_MAX * 2) + #define SDE_CRTC_NAME_SIZE 12 /* define the maximum number of in-flight frame events */ @@ -216,6 +219,23 @@ struct sde_crtc_misr_info { u32 misr_frame_count; }; +struct plane_state { + struct sde_plane_state *sde_pstate; + const struct drm_plane_state *drm_pstate; + int stage; + u32 pipe_id; +}; + +/** + * struct sde_multirect_plane_states: Defines multirect pair of drm plane states + * @r0: drm plane configured on rect 0 + * @r1: drm plane configured on rect 1 + */ +struct sde_multirect_plane_states { + const struct drm_plane_state *r0; + const struct drm_plane_state *r1; +}; + /* * Maximum number of free event structures to cache */ @@ -257,6 +277,9 @@ struct sde_crtc_misr_info { * @ad_dirty : list containing ad properties that are dirty * @ad_active : list containing ad properties that are active * @crtc_lock : crtc lock around create, destroy and access. + * @pstates : array of plane states + * @num_pstates : Number of plane states + * @multirect : array of multirect plane states * @frame_pending : Whether or not an update is pending * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list @@ -338,6 +361,10 @@ struct sde_crtc { struct mutex crtc_lock; struct mutex crtc_cp_lock; + struct plane_state pstates[SDE_PSTATES_MAX]; + uint32_t num_pstates; + struct sde_multirect_plane_states multirect[SDE_MULTIRECT_PLANE_MAX]; + atomic_t frame_pending; struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct list_head frame_event_list; diff --git a/msm/sde/sde_plane.h b/msm/sde/sde_plane.h index 70b4caff86..16b72cd72d 100644 --- a/msm/sde/sde_plane.h +++ b/msm/sde/sde_plane.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -137,16 +137,6 @@ struct sde_plane_state { struct sde_hw_pipe_cdp_cfg cdp_cfg; }; -/** - * struct sde_multirect_plane_states: Defines multirect pair of drm plane states - * @r0: drm plane configured on rect 0 - * @r1: drm plane configured on rect 1 - */ -struct sde_multirect_plane_states { - const struct drm_plane_state *r0; - const struct drm_plane_state *r1; -}; - #define to_sde_plane_state(x) \ container_of(x, struct sde_plane_state, base)