ソースを参照

Merge "disp: msm: sde: add support for WD timer on INTF"

qctecmdr 4 年 前
コミット
eabc0a4304

+ 8 - 15
msm/sde/sde_encoder.c

@@ -1083,8 +1083,7 @@ static int _sde_encoder_update_roi(struct drm_encoder *drm_enc)
 	return 0;
 }
 
-void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
-			u32 vsync_source, bool is_dummy)
+void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, u32 vsync_source)
 {
 	struct sde_vsync_source_cfg vsync_cfg = { 0 };
 	struct sde_kms *sde_kms;
@@ -1123,14 +1122,13 @@ void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
 		vsync_cfg.pp_count = sde_enc->num_phys_encs;
 		vsync_cfg.frame_rate = sde_enc->mode_info.frame_rate;
 		vsync_cfg.vsync_source = vsync_source;
-		vsync_cfg.is_dummy = is_dummy;
 
 		hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
 	}
 }
 
 static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
-			struct msm_display_info *disp_info, bool is_dummy)
+			struct msm_display_info *disp_info)
 {
 	struct sde_encoder_phys *phys;
 	int i;
@@ -1148,24 +1146,19 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
 	}
 
 	if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_CMD_MODE)) {
-		if (is_dummy)
-			vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0 -
-					sde_enc->te_source;
-		else if (disp_info->is_te_using_watchdog_timer)
-			vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_4 +
-					sde_enc->te_source;
+		if (disp_info->is_te_using_watchdog_timer)
+			vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_4 + sde_enc->te_source;
 		else
 			vsync_source = sde_enc->te_source;
 
-		SDE_EVT32(DRMID(&sde_enc->base), vsync_source, is_dummy,
+		SDE_EVT32(DRMID(&sde_enc->base), vsync_source,
 				disp_info->is_te_using_watchdog_timer);
 
 		for (i = 0; i < sde_enc->num_phys_encs; i++) {
 			phys = sde_enc->phys_encs[i];
 
 			if (phys && phys->ops.setup_vsync_source)
-				phys->ops.setup_vsync_source(phys,
-					vsync_source, is_dummy);
+				phys->ops.setup_vsync_source(phys, vsync_source);
 		}
 	}
 }
@@ -1189,7 +1182,7 @@ int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc,
 
 	memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info));
 	disp_info.is_te_using_watchdog_timer = watchdog_te;
-	_sde_encoder_update_vsync_source(sde_enc, &disp_info, false);
+	_sde_encoder_update_vsync_source(sde_enc, &disp_info);
 
 	sde_encoder_control_te(drm_enc, true);
 
@@ -2567,7 +2560,7 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
 				sde_enc->cur_master->hw_ctl,
 				&sde_enc->cur_master->intf_cfg_v1);
 
-	_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info, false);
+	_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info);
 	sde_encoder_control_te(drm_enc, true);
 
 	memset(&sde_enc->prv_conn_roi, 0, sizeof(sde_enc->prv_conn_roi));

+ 3 - 6
msm/sde/sde_encoder_phys.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_ENCODER_PHYS_H__
@@ -185,8 +185,7 @@ struct sde_encoder_phys_ops {
 	int (*get_wr_line_count)(struct sde_encoder_phys *phys);
 	bool (*wait_dma_trigger)(struct sde_encoder_phys *phys);
 	int (*wait_for_active)(struct sde_encoder_phys *phys);
-	void (*setup_vsync_source)(struct sde_encoder_phys *phys,
-			u32 vsync_source, bool is_dummy);
+	void (*setup_vsync_source)(struct sde_encoder_phys *phys, u32 vsync_source);
 	u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys);
 };
 
@@ -567,10 +566,8 @@ void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc);
  * sde_encoder_helper_vsync_config - configure vsync source for cmd mode
  * @phys_enc: Pointer to physical encoder structure
  * @vsync_source: vsync source selection
- * @is_dummy: used only for RSC
  */
-void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
-			u32 vsync_source, bool is_dummy);
+void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, u32 vsync_source);
 
 /**
  * sde_encoder_helper_wait_event_timeout - wait for event with timeout

+ 15 - 3
msm/sde/sde_encoder_phys_cmd.c

@@ -1935,13 +1935,25 @@ static void sde_encoder_phys_cmd_trigger_start(
 }
 
 static void sde_encoder_phys_cmd_setup_vsync_source(
-		struct sde_encoder_phys *phys_enc,
-		u32 vsync_source, bool is_dummy)
+		struct sde_encoder_phys *phys_enc, u32 vsync_source)
 {
+	struct sde_encoder_virt *sde_enc;
+
 	if (!phys_enc || !phys_enc->hw_intf)
 		return;
 
-	sde_encoder_helper_vsync_config(phys_enc, vsync_source, is_dummy);
+	sde_enc = to_sde_encoder_virt(phys_enc->parent);
+	if (!sde_enc)
+		return;
+
+	if (sde_enc->disp_info.is_te_using_watchdog_timer &&
+			phys_enc->hw_intf->ops.setup_vsync_source) {
+		vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
+		phys_enc->hw_intf->ops.setup_vsync_source(phys_enc->hw_intf,
+				sde_enc->mode_info.frame_rate);
+	} else {
+		sde_encoder_helper_vsync_config(phys_enc, vsync_source);
+	}
 
 	if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel)
 		phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf,

+ 7 - 1
msm/sde/sde_hw_catalog.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.
  */
 
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -2248,6 +2248,10 @@ static int sde_intf_parse_dt(struct device_node *np,
 		if (SDE_HW_MAJOR(sde_cfg->hwversion) >=
 				SDE_HW_MAJOR(SDE_HW_VER_700))
 			set_bit(SDE_INTF_TE_ALIGN_VSYNC, &intf->features);
+
+		if (SDE_HW_MAJOR(sde_cfg->hwversion) >=
+				SDE_HW_MAJOR(SDE_HW_VER_810))
+			set_bit(SDE_INTF_WD_TIMER, &intf->features);
 	}
 
 end:
@@ -3807,6 +3811,8 @@ static int sde_top_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
 	major_version = SDE_HW_MAJOR(cfg->hwversion);
 	if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
 		set_bit(SDE_MDP_VSYNC_SEL, &cfg->mdp[0].features);
+	else if (major_version < SDE_HW_MAJOR(SDE_HW_VER_810))
+		set_bit(SDE_MDP_WD_TIMER, &cfg->mdp[0].features);
 
 	rc = _add_to_irq_offset_list(cfg, SDE_INTR_HWBLK_TOP,
 			SDE_INTR_TOP_INTR, cfg->mdp[0].base);

+ 5 - 1
msm/sde/sde_hw_catalog.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_CATALOG_H
@@ -208,6 +208,7 @@ struct sde_intr_irq_offsets {
  *                         compression initial revision
  * @SDE_MDP_UBWC_1_5,      Universal Bandwidth compression version 1.5
  * @SDE_MDP_VSYNC_SEL      Vsync selection for command mode panels
+ * @SDE_MDP_WD_TIMER      WD timer support
  * @SDE_MDP_DHDR_MEMPOOL   Dynamic HDR Metadata mempool present
  * @SDE_MDP_DHDR_MEMPOOL_4K Dynamic HDR mempool is 4k aligned
  * @SDE_MDP_MAX            Maximum value
@@ -220,6 +221,7 @@ enum {
 	SDE_MDP_UBWC_1_0,
 	SDE_MDP_UBWC_1_5,
 	SDE_MDP_VSYNC_SEL,
+	SDE_MDP_WD_TIMER,
 	SDE_MDP_DHDR_MEMPOOL,
 	SDE_MDP_DHDR_MEMPOOL_4K,
 	SDE_MDP_MAX
@@ -475,6 +477,7 @@ enum {
  *                              pixel data arrives to this INTF
  * @SDE_INTF_TE                 INTF block has TE configuration support
  * @SDE_INTF_TE_ALIGN_VSYNC     INTF block has POMS Align vsync support
+ * @SDE_INTF_WD_TIMER          INTF block has WD Timer support
  * @SDE_INTF_STATUS             INTF block has INTF_STATUS register
  * @SDE_INTF_MAX
  */
@@ -482,6 +485,7 @@ enum {
 	SDE_INTF_INPUT_CTRL = 0x1,
 	SDE_INTF_TE,
 	SDE_INTF_TE_ALIGN_VSYNC,
+	SDE_INTF_WD_TIMER,
 	SDE_INTF_STATUS,
 	SDE_INTF_MAX
 };

+ 3 - 1
msm/sde/sde_hw_interrupts.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/bitops.h>
@@ -166,6 +166,7 @@
 #define SDE_INTR_DSICMD_2_INTO_STATIC BIT(6)
 #define SDE_INTR_DSICMD_2_OUTOF_STATIC BIT(7)
 #define SDE_INTR_PROG_LINE BIT(8)
+#define SDE_INTR_INTF_WD_TIMER_0_DONE BIT(13)
 
 /**
  * AD4 interrupt status bit definitions
@@ -398,6 +399,7 @@ static struct sde_irq_type sde_irq_intf_map[] = {
 		SDE_INTR_DSICMD_2_OUTOF_STATIC, -1},
 
 	{ SDE_IRQ_TYPE_PROG_LINE, -1, SDE_INTR_PROG_LINE, -1},
+	{ SDE_IRQ_TYPE_WD_TIMER, -1, SDE_INTR_WD_TIMER_0_DONE, -1},
 };
 
 static struct sde_irq_type sde_irq_ad4_map[] = {

+ 30 - 1
msm/sde/sde_hw_intf.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 <linux/iopoll.h>
 
@@ -61,6 +61,9 @@
 #define INTF_MISR_CTRL                  0x180
 #define INTF_MISR_SIGNATURE             0x184
 
+#define INTF_WD_TIMER_0_CTL             0x230
+#define INTF_WD_TIMER_0_CTL2            0x234
+#define INTF_WD_TIMER_0_LOAD_VALUE      0x238
 #define INTF_MUX                        0x25C
 #define INTF_UNDERRUN_COUNT             0x268
 #define INTF_STATUS                     0x26C
@@ -396,6 +399,29 @@ static void sde_hw_intf_setup_prg_fetch(
 	SDE_REG_WRITE(c, INTF_CONFIG, fetch_enable);
 }
 
+static void sde_hw_intf_setup_vsync_source(struct sde_hw_intf *intf,
+		u32 frame_rate)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 reg;
+
+	if (!intf)
+		return;
+
+	c = &intf->hw;
+
+	SDE_REG_WRITE(c, INTF_WD_TIMER_0_LOAD_VALUE, CALCULATE_WD_LOAD_VALUE(frame_rate));
+
+	SDE_REG_WRITE(c, INTF_WD_TIMER_0_CTL, BIT(0)); /* clear timer */
+	reg = SDE_REG_READ(c, INTF_WD_TIMER_0_CTL2);
+	reg |= BIT(8); /* enable heartbeat timer */
+	reg |= BIT(0); /* enable WD timer */
+	SDE_REG_WRITE(c, INTF_WD_TIMER_0_CTL2, reg);
+
+	/* make sure that timers are enabled/disabled for vsync state */
+	wmb();
+}
+
 static void sde_hw_intf_bind_pingpong_blk(
 		struct sde_hw_intf *intf,
 		bool enable,
@@ -805,6 +831,9 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
 	if (cap & BIT(SDE_INTF_INPUT_CTRL))
 		ops->bind_pingpong_blk = sde_hw_intf_bind_pingpong_blk;
 
+	if (cap & BIT(SDE_INTF_WD_TIMER))
+		ops->setup_vsync_source = sde_hw_intf_setup_vsync_source;
+
 	if (cap & BIT(SDE_INTF_TE)) {
 		ops->setup_tearcheck = sde_hw_intf_setup_te_config;
 		ops->enable_tearcheck = sde_hw_intf_enable_te;

+ 4 - 1
msm/sde/sde_hw_intf.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_INTF_H
@@ -78,6 +78,7 @@ struct intf_avr_params {
  * @ get_line_count: reads current vertical line counter
  * @ get_underrun_line_count: reads current underrun pixel clock count and
  *                            converts it into line count
+ * @setup_vsync_source: Configure vsync source selection for intf
  * @bind_pingpong_blk: enable/disable the connection with pingpong which will
  *                     feed pixels to this interface
  */
@@ -112,6 +113,8 @@ struct sde_hw_intf_ops {
 	u32 (*get_line_count)(struct sde_hw_intf *intf);
 	u32 (*get_underrun_line_count)(struct sde_hw_intf *intf);
 
+	void (*setup_vsync_source)(struct sde_hw_intf *intf, u32 frame_rate);
+
 	void (*bind_pingpong_blk)(struct sde_hw_intf *intf,
 			bool enable,
 			const enum sde_pingpong pp);

+ 8 - 1
msm/sde/sde_hw_mdss.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_MDSS_H
@@ -61,6 +61,13 @@ enum sde_format_flags {
 	(((X)->fetch_mode == SDE_FETCH_UBWC) && \
 			test_bit(SDE_FORMAT_FLAG_COMPRESSED_BIT, (X)->flag))
 
+#define MDP_TICK_COUNT                    16
+#define XO_CLK_RATE                       19200
+#define MS_TICKS_IN_SEC                   1000
+
+#define CALCULATE_WD_LOAD_VALUE(fps) \
+	((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps)))
+
 #define SDE_BLEND_FG_ALPHA_FG_CONST	(0 << 0)
 #define SDE_BLEND_FG_ALPHA_BG_CONST	(1 << 0)
 #define SDE_BLEND_FG_ALPHA_FG_PIXEL	(2 << 0)

+ 9 - 22
msm/sde/sde_hw_top.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 "sde_hwio.h"
@@ -50,16 +50,9 @@
 #define MDP_WD_TIMER_4_CTL2               0x444
 #define MDP_WD_TIMER_4_LOAD_VALUE         0x448
 
-#define MDP_TICK_COUNT                    16
-#define XO_CLK_RATE                       19200
-#define MS_TICKS_IN_SEC                   1000
-
 #define AUTOREFRESH_TEST_POINT	0x2
 #define TEST_MASK(id, tp)	((id << 4) | (tp << 1) | BIT(0))
 
-#define CALCULATE_WD_LOAD_VALUE(fps) \
-	((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps)))
-
 #define DCE_SEL                           0x450
 
 #define MDP_SID_VIG0			  0x0
@@ -316,18 +309,13 @@ static void _update_vsync_source(struct sde_hw_mdp *mdp,
 			break;
 		}
 
-		if (cfg->is_dummy) {
-			SDE_REG_WRITE(c, wd_ctl2, 0x0);
-		} else {
-			SDE_REG_WRITE(c, wd_load_value,
-				CALCULATE_WD_LOAD_VALUE(cfg->frame_rate));
-
-			SDE_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */
-			reg = SDE_REG_READ(c, wd_ctl2);
-			reg |= BIT(8);		/* enable heartbeat timer */
-			reg |= BIT(0);		/* enable WD timer */
-			SDE_REG_WRITE(c, wd_ctl2, reg);
-		}
+		SDE_REG_WRITE(c, wd_load_value, CALCULATE_WD_LOAD_VALUE(cfg->frame_rate));
+
+		SDE_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */
+		reg = SDE_REG_READ(c, wd_ctl2);
+		reg |= BIT(8); /* enable heartbeat timer */
+		reg |= BIT(0); /* enable WD timer */
+		SDE_REG_WRITE(c, wd_ctl2, reg);
 
 		/* make sure that timers are enabled/disabled for vsync state */
 		wmb();
@@ -623,7 +611,6 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
 	ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl;
 	ops->get_clk_ctrl_status = sde_hw_get_clk_ctrl_status;
 	ops->get_danger_status = sde_hw_get_danger_status;
-	ops->setup_vsync_source = sde_hw_setup_vsync_source;
 	ops->set_cwb_ppb_cntl = sde_hw_program_cwb_ppb_ctrl;
 	ops->get_safe_status = sde_hw_get_safe_status;
 	ops->get_split_flush_status = sde_hw_get_split_flush;
@@ -633,7 +620,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
 	ops->set_mdp_hw_events = sde_hw_mdp_events;
 	if (cap & BIT(SDE_MDP_VSYNC_SEL))
 		ops->setup_vsync_source = sde_hw_setup_vsync_source;
-	else
+	else if (cap & BIT(SDE_MDP_WD_TIMER))
 		ops->setup_vsync_source = sde_hw_setup_vsync_source_v1;
 
 	if (cap & BIT(SDE_MDP_DHDR_MEMPOOL_4K) ||

+ 1 - 4
msm/sde/sde_hw_top.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_TOP_H
@@ -79,15 +79,12 @@ struct sde_danger_safe_status {
  * @frame_rate: Display frame rate
  * @ppnumber: ping pong index array
  * @vsync_source: vsync source selection
- * @is_dummy: a dummy source of vsync selection. It must not be selected for
- *           any case other than sde rsc idle request.
  */
 struct sde_vsync_source_cfg {
 	u32 pp_count;
 	u32 frame_rate;
 	u32 ppnumber[PINGPONG_MAX];
 	u32 vsync_source;
-	bool is_dummy;
 };
 
 /**