diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index f4b3cf7b33e3..188fde70df11 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1959,6 +1959,41 @@ static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush) return 0; } +static void _sde_clear_ltm_merge_mode(struct sde_crtc *sde_crtc) +{ + u32 num_mixers = 0, i = 0; + struct sde_hw_ctl *ctl = NULL; + struct sde_hw_dspp *hw_dspp = NULL; + unsigned long irq_flags; + + num_mixers = sde_crtc->num_mixers; + if (!num_mixers) { + DRM_ERROR("no mixers for this crtc\n"); + return; + } + + spin_lock_irqsave(&sde_crtc->ltm_lock, irq_flags); + if (!sde_crtc->ltm_merge_clear_pending) { + spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); + return; + } + + sde_cp_dspp_flush_helper(sde_crtc, SDE_CP_CRTC_DSPP_LTM_HIST_CTL); + for (i = 0; i < num_mixers; i++) { + hw_dspp = sde_crtc->mixers[i].hw_dspp; + ctl = sde_crtc->mixers[i].hw_ctl; + if (!hw_dspp || !ctl || i >= DSPP_MAX) + continue; + if (hw_dspp->ops.clear_ltm_merge_mode) + hw_dspp->ops.clear_ltm_merge_mode(hw_dspp); + if (ctl->ops.update_bitmask_dspp) + ctl->ops.update_bitmask_dspp(ctl, hw_dspp->idx, 1); + } + + sde_crtc->ltm_merge_clear_pending = false; + spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); +} + void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; @@ -1988,6 +2023,7 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) } mutex_lock(&sde_crtc->crtc_cp_lock); + _sde_clear_ltm_merge_mode(sde_crtc); if (list_empty(&sde_crtc->dirty_list) && list_empty(&sde_crtc->ad_dirty) && @@ -2307,6 +2343,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) } sde_crtc->ltm_buffer_cnt = 0; sde_crtc->ltm_hist_en = false; + sde_crtc->ltm_merge_clear_pending = false; sde_crtc->hist_irq_idx = -1; mutex_destroy(&sde_crtc->crtc_cp_lock); @@ -2352,6 +2389,7 @@ void sde_cp_crtc_suspend(struct drm_crtc *crtc) spin_lock_irqsave(&sde_crtc->ltm_lock, irq_flags); sde_crtc->ltm_hist_en = false; + sde_crtc->ltm_merge_clear_pending = false; spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); if (ad_suspend) @@ -2402,6 +2440,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc) } sde_crtc->ltm_buffer_cnt = 0; sde_crtc->ltm_hist_en = false; + sde_crtc->ltm_merge_clear_pending = false; sde_crtc->hist_irq_idx = -1; INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); @@ -3791,6 +3830,7 @@ static void _sde_cp_crtc_disable_ltm_hist(struct sde_crtc *sde_crtc, spin_lock_irqsave(&sde_crtc->ltm_lock, irq_flags); sde_crtc->ltm_hist_en = false; + sde_crtc->ltm_merge_clear_pending = true; INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); for (i = 0; i < sde_crtc->ltm_buffer_cnt; i++) @@ -3862,7 +3902,7 @@ static void sde_cp_ltm_hist_interrupt_cb(void *arg, int irq_idx) hw_dspp->ops.setup_ltm_hist_ctrl(hw_dspp, NULL, false, 0); } - + sde_crtc->ltm_merge_clear_pending = true; spin_unlock_irqrestore(&sde_crtc->ltm_lock, irq_flags); DRM_DEBUG_DRIVER("LTM histogram is disabled\n"); return; diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 2248a59c5090..c325097eeba8 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -286,6 +286,7 @@ struct sde_crtc_misr_info { * @ltm_buf_free : list of LTM buffers that are available * @ltm_buf_busy : list of LTM buffers that are been used by HW * @ltm_hist_en : flag to indicate whether LTM hist is enabled or not + * @ltm_merge_clear_pending : flag indicates merge mode bit needs to be cleared * @ltm_buffer_lock : muttx to protect ltm_buffers allcation and free * @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists * @needs_hw_reset : Initiate a hw ctl reset @@ -376,6 +377,7 @@ struct sde_crtc { struct list_head ltm_buf_free; struct list_head ltm_buf_busy; bool ltm_hist_en; + bool ltm_merge_clear_pending; struct drm_msm_ltm_cfg_param ltm_cfg; struct mutex ltm_buffer_lock; spinlock_t ltm_lock; diff --git a/msm/sde/sde_hw_color_proc_common_v4.h b/msm/sde/sde_hw_color_proc_common_v4.h index 104aaf521b69..4c9ac0fba74b 100644 --- a/msm/sde/sde_hw_color_proc_common_v4.h +++ b/msm/sde/sde_hw_color_proc_common_v4.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019,2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_COLOR_PROC_COMMON_V4_H_ #define _SDE_HW_COLOR_PROC_COMMON_V4_H_ @@ -121,6 +121,8 @@ enum { #define SSPP 0 #define DSPP 1 +#define LTM_CONFIG_MERGE_MODE_ONLY (BIT(16) | BIT(17)) + struct sde_ltm_phase_info { u32 init_h[LTM_MAX]; u32 init_v; diff --git a/msm/sde/sde_hw_color_proc_v4.c b/msm/sde/sde_hw_color_proc_v4.c index 2fb5c209a42e..2bf3e1930ac7 100644 --- a/msm/sde/sde_hw_color_proc_v4.c +++ b/msm/sde/sde_hw_color_proc_v4.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include #include "sde_hw_color_proc_common_v4.h" @@ -339,7 +339,7 @@ void sde_setup_dspp_ltm_hist_ctrlv1(struct sde_hw_dspp *ctx, void *cfg, if (op_mode & BIT(1)) op_mode &= ~BIT(0); else - op_mode = 0; + op_mode &= LTM_CONFIG_MERGE_MODE_ONLY; SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->ltm.base + 0x4, (op_mode & 0x1FFFFFF)); @@ -398,6 +398,21 @@ void sde_ltm_read_intr_status(struct sde_hw_dspp *ctx, u32 *status) SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->ltm.base + 0x58, clear); } +void sde_ltm_clear_merge_mode(struct sde_hw_dspp *ctx) +{ + u32 clear; + + if (!ctx) { + DRM_ERROR("invalid parameters ctx %pK\n", ctx); + return; + } + + /* clear the merge_mode bit */ + clear = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->ltm.base + 0x04); + clear &= ~LTM_CONFIG_MERGE_MODE_ONLY; + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->ltm.base + 0x04, clear); +} + void sde_demura_backlight_cfg(struct sde_hw_dspp *dspp, u64 val) { u32 demura_base; diff --git a/msm/sde/sde_hw_color_proc_v4.h b/msm/sde/sde_hw_color_proc_v4.h index fa8e0db7a51f..9cb550679f62 100644 --- a/msm/sde/sde_hw_color_proc_v4.h +++ b/msm/sde/sde_hw_color_proc_v4.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_COLOR_PROC_V4_H_ #define _SDE_HW_COLOR_PROC_V4_H_ @@ -70,6 +70,13 @@ void sde_setup_dspp_ltm_hist_bufferv1(struct sde_hw_dspp *ctx, u64 addr); */ void sde_ltm_read_intr_status(struct sde_hw_dspp *dspp, u32 *status); +/** + * sde_ltm_clear_merge_mode - api to clear ltm merge_mode + * @dspp: pointer to dspp object + */ +void sde_ltm_clear_merge_mode(struct sde_hw_dspp *dspp); + + /** * sde_demura_backlight_cfg - api to set backlight for demura * @dspp: pointer to dspp object diff --git a/msm/sde/sde_hw_dspp.c b/msm/sde/sde_hw_dspp.c index 56427afec159..b5a6cde9372d 100644 --- a/msm/sde/sde_hw_dspp.c +++ b/msm/sde/sde_hw_dspp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include @@ -245,6 +245,7 @@ static void dspp_ltm(struct sde_hw_dspp *c) c->ops.setup_ltm_hist_buffer = sde_setup_dspp_ltm_hist_bufferv1; c->ops.ltm_read_intr_status = sde_ltm_read_intr_status; + c->ops.clear_ltm_merge_mode = sde_ltm_clear_merge_mode; } else { c->ops.setup_ltm_init = NULL; c->ops.setup_ltm_roi = NULL; @@ -253,6 +254,7 @@ static void dspp_ltm(struct sde_hw_dspp *c) c->ops.setup_ltm_hist_ctrl = NULL; c->ops.setup_ltm_hist_buffer = NULL; c->ops.ltm_read_intr_status = NULL; + c->ops.clear_ltm_merge_mode = NULL; } if (!ret && c->cap->sblk->ltm.version == SDE_COLOR_PROCESS_VER(0x1, 0x1)) diff --git a/msm/sde/sde_hw_dspp.h b/msm/sde/sde_hw_dspp.h index 8b4946415ad4..c6619622fdce 100644 --- a/msm/sde/sde_hw_dspp.h +++ b/msm/sde/sde_hw_dspp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_DSPP_H @@ -210,6 +210,12 @@ struct sde_hw_dspp_ops { */ void (*ltm_read_intr_status)(struct sde_hw_dspp *ctx, u32 *status); + /** + * clear_ltm_merge_mode - clear LTM merge_mode bit + * @ctx: Pointer to dspp context + */ + void (*clear_ltm_merge_mode)(struct sde_hw_dspp *ctx); + /** * validate_rc_mask - Validate RC mask configuration * @ctx: Pointer to dspp context. diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 45a1360f15c9..93d9b58729a1 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -3805,7 +3805,7 @@ static void ltm_vlutv1_disable(struct sde_hw_dspp *ctx) /* disable VLUT/INIT/ROI */ opmode &= REG_DMA_LTM_VLUT_DISABLE_OP_MASK; else - opmode = 0; + opmode &= LTM_CONFIG_MERGE_MODE_ONLY; SDE_REG_WRITE(&ctx->hw, offset, opmode); }