diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index e8b0d18a3b..8b79e55c00 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -4708,7 +4708,7 @@ void sde_cp_crtc_disable(struct drm_crtc *drm_crtc) kfree(info); } -void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem) +void sde_cp_clear_state_info(struct drm_crtc_state *state) { struct sde_crtc_state *crtc_state; int i; @@ -4722,15 +4722,46 @@ void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem) } SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); for (i = 0; i < ARRAY_SIZE(crtc_state->cp_range_payload); i++) { - if (free_mem) - kfree((void *)crtc_state->cp_range_payload[i].addr); - + kfree((void *)crtc_state->cp_range_payload[i].addr); crtc_state->cp_range_payload[i].addr = 0; crtc_state->cp_range_payload[i].len = 0; } - memset(&crtc_state->cp_dirty_list, 0, - sizeof(crtc_state->cp_dirty_list)); - memset(&crtc_state->cp_prop_values, 0, - sizeof(crtc_state->cp_prop_values)); - crtc_state->cp_prop_cnt = 0; +} + +void sde_cp_duplicate_state_info(struct drm_crtc_state *drm_old_state, + struct drm_crtc_state *drm_state) +{ + struct sde_crtc_state *old_state, *curr_state; + u32 len, i; + + if (!drm_old_state || !drm_state) + return; + + old_state = to_sde_crtc_state(drm_old_state); + curr_state = to_sde_crtc_state(drm_state); + if (!old_state || !curr_state) + return; + + SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); + for (i = 0; i < ARRAY_SIZE(old_state->cp_range_payload); i++) { + /* heap address copied from old state should be cleared, each state should have + * its own heap allocation. + */ + curr_state->cp_range_payload[i].addr = 0; + curr_state->cp_range_payload[i].len = 0; + if (!old_state->cp_range_payload[i].addr || !old_state->cp_range_payload[i].len) + continue; + + len = old_state->cp_range_payload[i].len; + curr_state->cp_range_payload[i].addr = (u64)kmalloc(len, GFP_KERNEL); + if (!curr_state->cp_range_payload[i].addr) { + SDE_EVT32(curr_state->cp_range_payload[i].addr); + continue; + } + memcpy((u8 *)curr_state->cp_range_payload[i].addr, + (u8 *)old_state->cp_range_payload[i].addr, len); + curr_state->cp_range_payload[i].len = len; + SDE_EVT32(curr_state->cp_range_payload[i].addr, + curr_state->cp_range_payload[i].len); + } } diff --git a/msm/sde/sde_color_processing.h b/msm/sde/sde_color_processing.h index 3903b03cc6..98d71b70c9 100644 --- a/msm/sde/sde_color_processing.h +++ b/msm/sde/sde_color_processing.h @@ -319,7 +319,15 @@ void sde_cp_crtc_disable(struct drm_crtc *crtc); /** * sde_cp_clear_state_info(): clear color processing info in the state. * @state: Pointer to drm_crtc_state. - * @free_mem: Boolean indicating if owned memory should be freed. */ -void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem); +void sde_cp_clear_state_info(struct drm_crtc_state *state); + +/** + * sde_cp_duplicate_state_info(): duplicate the cp state information. + * Function should be called only from sde_crtc_duplicate_state. + * @old_state: Pointer to old drm_crtc_state. + * @state: Pointer to current drm_crtc_state. + */ +void sde_cp_duplicate_state_info(struct drm_crtc_state *old_state, + struct drm_crtc_state *state); #endif /*_SDE_COLOR_PROCESSING_H */ diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 957b1b2a83..f566d3db03 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3606,7 +3606,7 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc, drm_for_each_encoder_mask(enc, crtc->dev, state->encoder_mask) sde_rm_release(&sde_kms->rm, enc, true); - sde_cp_clear_state_info(state, true); + sde_cp_clear_state_info(state); __drm_atomic_helper_crtc_destroy_state(state); /* destroy value helper */ @@ -4024,7 +4024,7 @@ static struct drm_crtc_state *sde_crtc_duplicate_state(struct drm_crtc *crtc) msm_property_duplicate_state(&sde_crtc->property_info, old_cstate, cstate, &cstate->property_state, cstate->property_values); - sde_cp_clear_state_info(&cstate->base, false); + sde_cp_duplicate_state_info(&old_cstate->base, &cstate->base); /* duplicate base helper */ __drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);