Procházet zdrojové kódy

Merge "disp: msm: sde: handle LTM switch in and out of dual pipe merge mode"

qctecmdr před 4 roky
rodič
revize
72f7dfe428

+ 40 - 1
msm/sde/sde_color_processing.c

@@ -2049,6 +2049,41 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu
 	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;
@@ -2086,6 +2121,7 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
 
 	_sde_cp_flush_properties(crtc);
 	mutex_lock(&sde_crtc->crtc_cp_lock);
+	_sde_clear_ltm_merge_mode(sde_crtc);
 
 	if (list_empty(&sde_crtc->cp_dirty_list) &&
 			list_empty(&sde_crtc->ad_dirty) &&
@@ -2554,6 +2590,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);
@@ -2711,6 +2748,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);
@@ -4104,6 +4142,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++)
@@ -4175,7 +4214,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;

+ 2 - 0
msm/sde/sde_crtc.h

@@ -312,6 +312,7 @@ struct sde_frame_data {
  * @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
@@ -407,6 +408,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;

+ 2 - 0
msm/sde/sde_hw_color_proc_common_v4.h

@@ -148,6 +148,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;

+ 16 - 1
msm/sde/sde_hw_color_proc_v4.c

@@ -340,7 +340,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));
@@ -399,6 +399,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 *ctx, u64 val)
 {
 	u32 demura_base;

+ 7 - 0
msm/sde/sde_hw_color_proc_v4.h

@@ -72,6 +72,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
  * @ctx: pointer to dspp object

+ 2 - 0
msm/sde/sde_hw_dspp.c

@@ -247,6 +247,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;
@@ -255,6 +256,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))

+ 6 - 0
msm/sde/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.

+ 1 - 1
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -3795,7 +3795,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);
 }