Эх сурвалжийг харах

Merge "disp: msm: sde: add support for DMA 4,5 for Kalama"

qctecmdr 3 жил өмнө
parent
commit
34ca07a0b0

+ 41 - 40
msm/sde/sde_hw_catalog.c

@@ -2030,25 +2030,27 @@ static int _sde_sspp_setup_cmn(struct device_node *np,
 		sblk->src_blk.len = PROP_VALUE_ACCESS(props->values, SSPP_SIZE,
 				0);
 
-		for (j = 0; j < sde_cfg->mdp_count; j++) {
-			sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].reg_off =
-					PROP_BITVALUE_ACCESS(props->values,
-					SSPP_CLK_CTRL, i, 0);
-			sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].bit_off =
-					PROP_BITVALUE_ACCESS(props->values,
-					SSPP_CLK_CTRL, i, 1);
-			sde_cfg->mdp[j].clk_status[sspp->clk_ctrl].reg_off =
-					PROP_BITVALUE_ACCESS(props->values,
-					SSPP_CLK_STATUS, i, 0);
-			sde_cfg->mdp[j].clk_status[sspp->clk_ctrl].bit_off =
-					PROP_BITVALUE_ACCESS(props->values,
-					SSPP_CLK_STATUS, i, 1);
-		}
+		if (!test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features)) {
+			for (j = 0; j < sde_cfg->mdp_count; j++) {
+				sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].reg_off =
+						PROP_BITVALUE_ACCESS(props->values,
+						SSPP_CLK_CTRL, i, 0);
+				sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].bit_off =
+						PROP_BITVALUE_ACCESS(props->values,
+						SSPP_CLK_CTRL, i, 1);
+				sde_cfg->mdp[j].clk_status[sspp->clk_ctrl].reg_off =
+						PROP_BITVALUE_ACCESS(props->values,
+						SSPP_CLK_STATUS, i, 0);
+				sde_cfg->mdp[j].clk_status[sspp->clk_ctrl].bit_off =
+						PROP_BITVALUE_ACCESS(props->values,
+						SSPP_CLK_STATUS, i, 1);
+			}
 
-		SDE_DEBUG("xin:%d ram:%d clk%d:%x/%d\n",
-			sspp->xin_id, sblk->pixel_ram_size, sspp->clk_ctrl,
-			sde_cfg->mdp[0].clk_ctrls[sspp->clk_ctrl].reg_off,
-			sde_cfg->mdp[0].clk_ctrls[sspp->clk_ctrl].bit_off);
+			SDE_DEBUG("xin:%d ram:%d clk%d:%x/%d\n",
+					sspp->xin_id, sblk->pixel_ram_size, sspp->clk_ctrl,
+					sde_cfg->mdp[0].clk_ctrls[sspp->clk_ctrl].reg_off,
+					sde_cfg->mdp[0].clk_ctrls[sspp->clk_ctrl].bit_off);
+		}
 	}
 
 end:
@@ -2586,31 +2588,29 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
 			}
 		}
 
-		for (j = 0; j < sde_cfg->mdp_count; j++) {
-			sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off =
-				PROP_BITVALUE_ACCESS(prop_value,
-						WB_CLK_CTRL, i, 0);
-			sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].bit_off =
-				PROP_BITVALUE_ACCESS(prop_value,
-						WB_CLK_CTRL, i, 1);
-			sde_cfg->mdp[j].clk_status[wb->clk_ctrl].reg_off =
-				PROP_BITVALUE_ACCESS(prop_value,
-						WB_CLK_STATUS, i, 0);
-			sde_cfg->mdp[j].clk_status[wb->clk_ctrl].bit_off =
-				PROP_BITVALUE_ACCESS(prop_value,
-						WB_CLK_STATUS, i, 1);
+		if (!test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features)) {
+			for (j = 0; j < sde_cfg->mdp_count; j++) {
+				sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off =
+					PROP_BITVALUE_ACCESS(prop_value,
+							WB_CLK_CTRL, i, 0);
+				sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].bit_off =
+					PROP_BITVALUE_ACCESS(prop_value,
+							WB_CLK_CTRL, i, 1);
+				sde_cfg->mdp[j].clk_status[wb->clk_ctrl].reg_off =
+					PROP_BITVALUE_ACCESS(prop_value,
+							WB_CLK_STATUS, i, 0);
+				sde_cfg->mdp[j].clk_status[wb->clk_ctrl].bit_off =
+					PROP_BITVALUE_ACCESS(prop_value,
+							WB_CLK_STATUS, i, 1);
+			}
+
+			SDE_DEBUG("wb:%d xin:%d vbif:%d clk%d:%x/%d\n", wb->id - WB_0,
+					wb->xin_id, wb->vbif_idx, wb->clk_ctrl,
+					sde_cfg->mdp[0].clk_ctrls[wb->clk_ctrl].reg_off,
+					sde_cfg->mdp[0].clk_ctrls[wb->clk_ctrl].bit_off);
 		}
 
 		wb->format_list = sde_cfg->wb_formats;
-
-		SDE_DEBUG(
-			"wb:%d xin:%d vbif:%d clk%d:%x/%d\n",
-			wb->id - WB_0,
-			wb->xin_id,
-			wb->vbif_idx,
-			wb->clk_ctrl,
-			sde_cfg->mdp[0].clk_ctrls[wb->clk_ctrl].reg_off,
-			sde_cfg->mdp[0].clk_ctrls[wb->clk_ctrl].bit_off);
 	}
 
 end:
@@ -5108,6 +5108,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
 		set_bit(SDE_FEATURE_UBWC_STATS, sde_cfg->features);
 		set_bit(SDE_FEATURE_HW_VSYNC_TS, sde_cfg->features);
 		set_bit(SDE_FEATURE_AVR_STEP, sde_cfg->features);
+		set_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features);
 		sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH;
 		sde_cfg->perf.min_prefill_lines = 40;
 		sde_cfg->vbif_qos_nlvl = 8;

+ 42 - 0
msm/sde/sde_hw_catalog.h

@@ -657,6 +657,7 @@ enum {
  * @SDE_FEATURE_SUI_NS_ALLOWED SecureUI allowed to access non-secure context banks
  * @SDE_FEATURE_TRUSTED_VM     Trusted VM supported
  * @SDE_FEATURE_UBWC_STATS     UBWC statistics supported
+ * @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
  * @SDE_FEATURE_MAX:             MAX features value
  */
 enum sde_mdss_features {
@@ -696,6 +697,7 @@ enum sde_mdss_features {
 	SDE_FEATURE_SUI_NS_ALLOWED,
 	SDE_FEATURE_TRUSTED_VM,
 	SDE_FEATURE_UBWC_STATS,
+	SDE_FEATURE_VBIF_CLK_SPLIT,
 	SDE_FEATURE_MAX
 };
 
@@ -1025,15 +1027,55 @@ enum sde_clk_ctrl_type {
 	SDE_CLK_CTRL_RGB3,
 	SDE_CLK_CTRL_DMA0,
 	SDE_CLK_CTRL_DMA1,
+	SDE_CLK_CTRL_DMA2,
+	SDE_CLK_CTRL_DMA3,
+	SDE_CLK_CTRL_DMA4,
+	SDE_CLK_CTRL_DMA5,
 	SDE_CLK_CTRL_CURSOR0,
 	SDE_CLK_CTRL_CURSOR1,
 	SDE_CLK_CTRL_WB0,
 	SDE_CLK_CTRL_WB1,
 	SDE_CLK_CTRL_WB2,
 	SDE_CLK_CTRL_LUTDMA,
+	SDE_CLK_CTRL_IPCC_MSI,
 	SDE_CLK_CTRL_MAX,
 };
 
+#define SDE_CLK_CTRL_VALID(x) (x > SDE_CLK_CTRL_NONE && x < SDE_CLK_CTRL_MAX)
+#define SDE_CLK_CTRL_SSPP_VALID(x) (x >= SDE_CLK_CTRL_VIG0 && x <= SDE_CLK_CTRL_CURSOR1)
+#define SDE_CLK_CTRL_WB_VALID(x) (x >= SDE_CLK_CTRL_WB0 && x <= SDE_CLK_CTRL_WB2)
+#define SDE_CLK_CTRL_LUTDMA_VALID(x) (x == SDE_CLK_CTRL_LUTDMA)
+#define SDE_CLK_CTRL_IPCC_MSI_VALID(x) (x == SDE_CLK_CTRL_IPCC_MSI)
+
+/**
+ * sde_clk_ctrl_type - String of top level clock control signals
+ */
+static const char *sde_clk_ctrl_type_s[SDE_CLK_CTRL_MAX] = {
+	[SDE_CLK_CTRL_NONE] = "NONE",
+	[SDE_CLK_CTRL_VIG0] = "VIG0",
+	[SDE_CLK_CTRL_VIG1] = "VIG1",
+	[SDE_CLK_CTRL_VIG2] = "VIG2",
+	[SDE_CLK_CTRL_VIG3] = "VIG3",
+	[SDE_CLK_CTRL_VIG4] = "VIG4",
+	[SDE_CLK_CTRL_RGB0] = "RGB0",
+	[SDE_CLK_CTRL_RGB1] = "RGB1",
+	[SDE_CLK_CTRL_RGB2] = "RGB2",
+	[SDE_CLK_CTRL_RGB3] = "RGB3",
+	[SDE_CLK_CTRL_DMA0] = "DMA0",
+	[SDE_CLK_CTRL_DMA1] = "DMA1",
+	[SDE_CLK_CTRL_DMA2] = "DMA2",
+	[SDE_CLK_CTRL_DMA3] = "DMA3",
+	[SDE_CLK_CTRL_DMA4] = "DMA4",
+	[SDE_CLK_CTRL_DMA5] = "DMA5",
+	[SDE_CLK_CTRL_CURSOR0] = "CURSOR0",
+	[SDE_CLK_CTRL_CURSOR1] = "CURSOR1",
+	[SDE_CLK_CTRL_WB0] = "WB0",
+	[SDE_CLK_CTRL_WB1] = "WB1",
+	[SDE_CLK_CTRL_WB2] = "WB2",
+	[SDE_CLK_CTRL_LUTDMA] = "LUTDMA",
+	[SDE_CLK_CTRL_IPCC_MSI] = "IPCC_MSI",
+};
+
 /* struct sde_clk_ctrl_reg : Clock control register
  * @reg_off:           register offset
  * @bit_off:           bit offset

+ 13 - 6
msm/sde/sde_hw_ctl.c

@@ -18,6 +18,8 @@
 	(0x70 + (((lm) - LM_0) * 0x004))
 #define CTL_LAYER_EXT3(lm)             \
 	(0xA0 + (((lm) - LM_0) * 0x004))
+#define CTL_LAYER_EXT4(lm)             \
+	(0xB8 + (((lm) - LM_0) * 0x004))
 #define CTL_TOP                       0x014
 #define CTL_FLUSH                     0x018
 #define CTL_START                     0x01C
@@ -54,7 +56,7 @@
 #define CTL_FLUSH_MASK_ROT              BIT(27)
 #define CTL_FLUSH_MASK_CTL              BIT(17)
 
-#define CTL_NUM_EXT			4
+#define CTL_NUM_EXT			5
 #define CTL_SSPP_MAX_RECTS		2
 
 #define SDE_REG_RESET_TIMEOUT_US        2000
@@ -73,7 +75,7 @@
  * List of SSPP bits in CTL_FLUSH
  */
 static const u32 sspp_tbl[SSPP_MAX] = { SDE_NONE, 0, 1, 2, 18, 3, 4, 5,
-	19, 11, 12, 24, 25, SDE_NONE, SDE_NONE};
+	19, 11, 12, 24, 25, 13, 14, SDE_NONE, SDE_NONE};
 
 /**
  * List of layer mixer bits in CTL_FLUSH
@@ -123,7 +125,7 @@ static const u32 intf_tbl[INTF_MAX] = {SDE_NONE, 31, 30, 29, 28};
  */
 static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
 	CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
-	1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT};
+	1, 2, 3, 4, 5, CTL_INVALID_BIT, CTL_INVALID_BIT};
 
 /**
  * list of WB bits in CTL_WB_FLUSH
@@ -218,6 +220,8 @@ sspp_reg_cfg_tbl[SSPP_MAX][CTL_SSPP_MAX_RECTS] = {
 	/* SSPP_DMA1 */{ {0, 21, 3, BIT(18)}, {2, 12, 4, 0} },
 	/* SSPP_DMA2 */{ {2, 0, 4, 0}, {2, 16, 4, 0} },
 	/* SSPP_DMA3 */{ {2, 4, 4, 0}, {2, 20, 4, 0} },
+	/* SSPP_DMA4 */{ {4, 0, 4, 0}, {4, 8, 4, 0} },
+	/* SSPP_DMA5 */{ {4, 4, 4, 0}, {4, 12, 4, 0} },
 	/* SSPP_CURSOR0 */{ {1, 20, 4, 0}, {0, 0, 0, 0} },
 	/* SSPP_CURSOR1 */{ {1, 26, 4, 0}, {0, 0, 0, 0} }
 };
@@ -846,6 +850,7 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
 		SDE_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
 		SDE_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
 		SDE_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
+		SDE_REG_WRITE(c, CTL_LAYER_EXT4(mixer_id), 0);
 	}
 	SDE_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
 }
@@ -894,6 +899,7 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
 	struct sde_hw_blk_reg_map *c;
 	u32 cfg[CTL_NUM_EXT] = { 0 };
 	int stages;
+	bool null_commit;
 
 	if (!ctx)
 		return;
@@ -907,15 +913,15 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
 	if (stage_cfg)
 		_sde_hw_ctl_get_mixer_cfg(ctx, stage_cfg, stages, cfg);
 
-	if (!disable_border &&
-			((!cfg[0] && !cfg[1] && !cfg[2] && !cfg[3]) ||
-			(stage_cfg && !stage_cfg->stage[0][0])))
+	null_commit = (!cfg[0] && !cfg[1] && !cfg[2] && !cfg[3] && !cfg[4]);
+	if (!disable_border && (null_commit || (stage_cfg && !stage_cfg->stage[0][0])))
 		cfg[0] |= CTL_MIXER_BORDER_OUT;
 
 	SDE_REG_WRITE(c, CTL_LAYER(lm), cfg[0]);
 	SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), cfg[1]);
 	SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), cfg[2]);
 	SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), cfg[3]);
+	SDE_REG_WRITE(c, CTL_LAYER_EXT4(lm), cfg[4]);
 }
 
 static u32 sde_hw_ctl_get_staged_sspp(struct sde_hw_ctl *ctx, enum sde_lm lm,
@@ -937,6 +943,7 @@ static u32 sde_hw_ctl_get_staged_sspp(struct sde_hw_ctl *ctx, enum sde_lm lm,
 	mixercfg[1] = SDE_REG_READ(c, CTL_LAYER_EXT(lm));
 	mixercfg[2] = SDE_REG_READ(c, CTL_LAYER_EXT2(lm));
 	mixercfg[3] = SDE_REG_READ(c, CTL_LAYER_EXT3(lm));
+	mixercfg[4] = SDE_REG_READ(c, CTL_LAYER_EXT4(lm));
 
 	if (mixercfg[0] & CTL_MIXER_BORDER_OUT)
 		info->bordercolor = true;

+ 12 - 0
msm/sde/sde_hw_mdss.h

@@ -140,19 +140,31 @@ enum sde_sspp {
 	SSPP_VIG1,
 	SSPP_VIG2,
 	SSPP_VIG3,
+	SSPP_VIG_MAX = SSPP_VIG3,
 	SSPP_RGB0,
 	SSPP_RGB1,
 	SSPP_RGB2,
 	SSPP_RGB3,
+	SSPP_RGB_MAX = SSPP_RGB3,
 	SSPP_DMA0,
 	SSPP_DMA1,
 	SSPP_DMA2,
 	SSPP_DMA3,
+	SSPP_DMA4,
+	SSPP_DMA5,
+	SSPP_DMA_MAX = SSPP_DMA5,
 	SSPP_CURSOR0,
 	SSPP_CURSOR1,
+	SSPP_CURSOR_MAX = SSPP_CURSOR1,
 	SSPP_MAX
 };
 
+#define SDE_SSPP_VALID(x) ((x) > SSPP_NONE && (x) < SSPP_MAX)
+#define SDE_SSPP_VALID_VIG(x) ((x) >= SSPP_VIG0 && (x) <= SSPP_VIG_MAX)
+#define SDE_SSPP_VALID_RGB(x) ((x) >= SSPP_RGB0 && (x) <= SSPP_RGB_MAX)
+#define SDE_SSPP_VALID_DMA(x) ((x) >= SSPP_DMA0 && (x) <= SSPP_DMA_MAX)
+#define SDE_SSPP_VALID_CURSOR(x) ((x) >= SSPP_CURSOR0 && (x) <= SSPP_CURSOR_MAX)
+
 enum sde_sspp_type {
 	SSPP_TYPE_VIG,
 	SSPP_TYPE_RGB,

+ 1 - 2
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -2183,8 +2183,7 @@ static int reg_dma_sspp_check(struct sde_hw_pipe *ctx, void *cfg,
 	if (IS_ERR_OR_NULL(dma_ops))
 		return -EINVAL;
 
-	if (!hw_cfg->ctl || ctx->idx > SSPP_DMA3 || ctx->idx <= SSPP_NONE ||
-		feature >= REG_DMA_FEATURES_MAX) {
+	if (!hw_cfg->ctl || !SDE_SSPP_VALID(ctx->idx) || feature >= REG_DMA_FEATURES_MAX) {
 		DRM_ERROR("invalid ctl %pK sspp idx %d feature %d\n",
 			hw_cfg->ctl, ctx->idx, feature);
 		return -EINVAL;

+ 53 - 1
msm/sde/sde_hw_sspp.c

@@ -11,6 +11,7 @@
 #include "sde_dbg.h"
 #include "sde_kms.h"
 #include "sde_hw_reg_dma_v1_color_proc.h"
+#include "sde_hw_vbif.h"
 
 #define SDE_FETCH_CONFIG_RESET_VALUE   0x00000087
 
@@ -110,6 +111,8 @@
 #define SSPP_VIG_OP_MODE                   0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
+#define SSPP_CLK_CTRL                      0x330
+#define SSPP_CLK_STATUS                    0x334
 
 /* SSPP_QOS_CTRL */
 #define SSPP_QOS_CTRL_VBLANK_EN            BIT(16)
@@ -1382,6 +1385,44 @@ static void sde_hw_sspp_setup_dgm_csc(struct sde_hw_pipe *ctx,
 	SDE_REG_WRITE(&ctx->hw, offset, op_mode);
 }
 
+static bool sde_hw_sspp_setup_clk_force_ctrl(struct sde_hw_blk_reg_map *hw,
+		enum sde_clk_ctrl_type clk_ctrl, bool enable)
+{
+	u32 reg_val, new_val;
+
+	if (!hw)
+		return false;
+
+	if (!SDE_CLK_CTRL_SSPP_VALID(clk_ctrl))
+		return false;
+
+	reg_val = SDE_REG_READ(hw, SSPP_CLK_CTRL);
+
+	if (enable)
+		new_val = reg_val | BIT(0);
+	else
+		new_val = reg_val & ~BIT(0);
+
+	SDE_REG_WRITE(hw, SSPP_CLK_CTRL, new_val);
+	wmb(); /* ensure write finished before progressing */
+
+	return !(reg_val & BIT(0));
+}
+
+static int sde_hw_sspp_get_clk_ctrl_status(struct sde_hw_blk_reg_map *hw,
+		enum sde_clk_ctrl_type clk_ctrl, bool *status)
+{
+	if (!hw)
+		return -EINVAL;
+
+	if (!SDE_CLK_CTRL_SSPP_VALID(clk_ctrl))
+		return -EINVAL;
+
+	*status = SDE_REG_READ(hw, SSPP_CLK_STATUS) & BIT(0);
+
+	return 0;
+}
+
 static void _setup_layer_ops(struct sde_hw_pipe *c,
 		unsigned long features, unsigned long perf_features,
 		bool is_virtual_pipe)
@@ -1508,7 +1549,7 @@ static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
 
 struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
 		void __iomem *addr, struct sde_mdss_cfg *catalog,
-		bool is_virtual_pipe)
+		bool is_virtual_pipe, struct sde_vbif_clk_client *clk_client)
 {
 	struct sde_hw_pipe *hw_pipe;
 	struct sde_sspp_cfg *cfg;
@@ -1582,6 +1623,17 @@ struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
 				cfg->sblk->scaler_blk.len,
 			hw_pipe->hw.xin_id);
 
+	if (test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, catalog->features)) {
+		if (SDE_CLK_CTRL_SSPP_VALID(cfg->clk_ctrl)) {
+			clk_client->hw = &hw_pipe->hw;
+			clk_client->clk_ctrl = cfg->clk_ctrl;
+			clk_client->ops.get_clk_ctrl_status = sde_hw_sspp_get_clk_ctrl_status;
+			clk_client->ops.setup_clk_force_ctrl = sde_hw_sspp_setup_clk_force_ctrl;
+		} else {
+			SDE_ERROR("invalid sspp clk ctrl type %d\n", cfg->clk_ctrl);
+		}
+	}
+
 	return hw_pipe;
 }
 

+ 3 - 1
msm/sde/sde_hw_sspp.h

@@ -12,6 +12,7 @@
 #include "sde_reg_dma.h"
 #include "sde_formats.h"
 #include "sde_color_processing.h"
+#include "sde_hw_vbif.h"
 
 struct sde_hw_pipe;
 
@@ -710,10 +711,11 @@ struct sde_hw_pipe {
  * @addr: Mapped register io address of MDP
  * @catalog : Pointer to mdss catalog data
  * @is_virtual_pipe: is this pipe virtual pipe
+ * @client: Pointer to VBIF clock client info
  */
 struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
 		void __iomem *addr, struct sde_mdss_cfg *catalog,
-		bool is_virtual_pipe);
+		bool is_virtual_pipe, struct sde_vbif_clk_client *client);
 
 /**
  * sde_hw_sspp_destroy(): Destroys SSPP driver context

+ 2 - 2
msm/sde/sde_hw_top.c

@@ -415,9 +415,9 @@ void sde_hw_set_sspp_sid(struct sde_hw_sid *sid, u32 pipe, u32 vm)
 	if (!sid)
 		return;
 
-	if ((pipe >= SSPP_VIG0) && (pipe <= SSPP_VIG3))
+	if (SDE_SSPP_VALID_VIG(pipe))
 		offset = MDP_SID_VIG0 + ((pipe - SSPP_VIG0) * 4);
-	else if ((pipe >= SSPP_DMA0) && (pipe <= SSPP_DMA3))
+	else if (SDE_SSPP_VALID_DMA(pipe))
 		offset = MDP_SID_DMA0 + ((pipe - SSPP_DMA0) * 4);
 	else
 		return;

+ 35 - 1
msm/sde/sde_hw_vbif.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_VBIF_H
@@ -124,6 +124,40 @@ struct sde_hw_vbif {
 	struct mutex mutex;
 };
 
+struct sde_vbif_clk_ops {
+	/**
+	 * setup_clk_force_ctrl - set clock force control
+	 * @hw:		hw block object
+	 * @clk_ctrl:	clock to be controlled
+	 * @enable:	force on enable
+	 * @return:	if the clock is forced-on by this function
+	 */
+	bool (*setup_clk_force_ctrl)(struct sde_hw_blk_reg_map *hw,
+			enum sde_clk_ctrl_type clk_ctrl, bool enable);
+
+	/**
+	 * get_clk_ctrl_status - get clock control status
+	 * @hw:		hw block object
+	 * @clk_ctrl:	clock to be controlled
+	 * @status:	returns true if clock is on
+	 * @return:	0 if success, otherwise return error code
+	 */
+	int (*get_clk_ctrl_status)(struct sde_hw_blk_reg_map *hw,
+			enum sde_clk_ctrl_type clk_ctrl, bool *status);
+};
+
+/**
+ * sde_vbif_clk_client - vbif client info
+ * @hw:		hw block object
+ * @clk_ctrl:	clock to be controlled
+ * @ops:	VBIF client ops
+ */
+struct sde_vbif_clk_client {
+	struct sde_hw_blk_reg_map *hw;
+	enum sde_clk_ctrl_type clk_ctrl;
+	struct sde_vbif_clk_ops ops;
+};
+
 /**
  * sde_hw_vbif_init - initializes the vbif driver for the passed interface idx
  * @idx:  Interface index for which driver object is required

+ 54 - 1
msm/sde/sde_hw_wb.c

@@ -10,6 +10,7 @@
 #include "sde_formats.h"
 #include "sde_dbg.h"
 #include "sde_kms.h"
+#include "sde_vbif.h"
 
 #define WB_DST_FORMAT			0x000
 #define WB_DST_OP_MODE			0x004
@@ -44,6 +45,8 @@
 #define WB_MUX				0x150
 #define WB_CROP_CTRL			0x154
 #define WB_CROP_OFFSET			0x158
+#define WB_CLK_CTRL			0x178
+#define WB_CLK_STATUS			0x17C
 #define WB_CSC_BASE			0x260
 #define WB_DST_ADDR_SW_STATUS		0x2B0
 #define WB_CDP_CNTL			0x2B4
@@ -502,6 +505,44 @@ static void sde_hw_wb_program_cwb_dither_ctrl(struct sde_hw_wb *ctx,
 	SDE_DEBUG("cwb dither enabled, dcwb_idx %u pp_id %u\n", dcwb_idx, pp_id);
 }
 
+static bool sde_hw_wb_setup_clk_force_ctrl(struct sde_hw_blk_reg_map *hw,
+		enum sde_clk_ctrl_type clk_ctrl, bool enable)
+{
+	u32 reg_val, new_val;
+
+	if (!hw)
+		return false;
+
+	if (!SDE_CLK_CTRL_WB_VALID(clk_ctrl))
+		return false;
+
+	reg_val = SDE_REG_READ(hw, WB_CLK_CTRL);
+
+	if (enable)
+		new_val = reg_val | BIT(0);
+	else
+		new_val = reg_val & ~BIT(0);
+
+	SDE_REG_WRITE(hw, WB_CLK_CTRL, new_val);
+	wmb(); /* ensure write finished before progressing */
+
+	return !(reg_val & BIT(0));
+}
+
+static int sde_hw_wb_get_clk_ctrl_status(struct sde_hw_blk_reg_map *hw,
+		enum sde_clk_ctrl_type clk_ctrl, bool *status)
+{
+	if (!hw)
+		return -EINVAL;
+
+	if (!SDE_CLK_CTRL_WB_VALID(clk_ctrl))
+		return -EINVAL;
+
+	*status = SDE_REG_READ(hw, WB_CLK_STATUS) & BIT(0);
+
+	return 0;
+}
+
 static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
 	unsigned long features)
 {
@@ -538,7 +579,8 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
 struct sde_hw_blk_reg_map *sde_hw_wb_init(enum sde_wb idx,
 		void __iomem *addr,
 		struct sde_mdss_cfg *m,
-		struct sde_hw_mdp *hw_mdp)
+		struct sde_hw_mdp *hw_mdp,
+		struct sde_vbif_clk_client *clk_client)
 {
 	struct sde_hw_wb *c;
 	struct sde_wb_cfg *cfg;
@@ -565,6 +607,17 @@ struct sde_hw_blk_reg_map *sde_hw_wb_init(enum sde_wb idx,
 	_setup_wb_ops(&c->ops, c->caps->features);
 	c->hw_mdp = hw_mdp;
 
+	if (test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, m->features)) {
+		if (SDE_CLK_CTRL_WB_VALID(cfg->clk_ctrl)) {
+			clk_client->hw = &c->hw;
+			clk_client->clk_ctrl = cfg->clk_ctrl;
+			clk_client->ops.get_clk_ctrl_status = sde_hw_wb_get_clk_ctrl_status;
+			clk_client->ops.setup_clk_force_ctrl = sde_hw_wb_setup_clk_force_ctrl;
+		} else {
+			SDE_ERROR("invalid wb clk ctrl type %d\n", cfg->clk_ctrl);
+		}
+	}
+
 	sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name, c->hw.blk_off,
 			c->hw.blk_off + c->hw.length, c->hw.xin_id);
 

+ 4 - 1
msm/sde/sde_hw_wb.h

@@ -11,6 +11,7 @@
 #include "sde_hw_top.h"
 #include "sde_hw_util.h"
 #include "sde_hw_pingpong.h"
+#include "sde_hw_vbif.h"
 
 struct sde_hw_wb;
 
@@ -211,11 +212,13 @@ static inline struct sde_hw_wb *to_sde_hw_wb(struct sde_hw_blk_reg_map *hw)
  * @addr: mapped register io address of MDP
  * @m :   pointer to mdss catalog data
  * @hw_mdp: pointer to mdp top hw driver object
+ * @clk_client: pointer to vbif clk client info
  */
 struct sde_hw_blk_reg_map *sde_hw_wb_init(enum sde_wb idx,
 		void __iomem *addr,
 		struct sde_mdss_cfg *m,
-		struct sde_hw_mdp *hw_mdp);
+		struct sde_hw_mdp *hw_mdp,
+		struct sde_vbif_clk_client *clk_client);
 
 /**
  * sde_hw_wb_destroy(): Destroy writeback hw driver object.

+ 2 - 0
msm/sde/sde_kms.h

@@ -35,6 +35,7 @@
 #include "sde_hw_wb.h"
 #include "sde_hw_top.h"
 #include "sde_hw_uidle.h"
+#include "sde_hw_vbif.h"
 #include "sde_rm.h"
 #include "sde_power_handle.h"
 #include "sde_irq.h"
@@ -283,6 +284,7 @@ struct sde_kms {
 	struct sde_rm rm;
 	bool rm_init;
 	struct sde_splash_data splash_data;
+	struct sde_vbif_clk_client vbif_clk_clients[SDE_CLK_CTRL_MAX];
 	struct sde_hw_vbif *hw_vbif[VBIF_MAX];
 	struct sde_hw_mdp *hw_mdp;
 	struct sde_hw_uidle *hw_uidle;

+ 15 - 5
msm/sde/sde_plane.c

@@ -3703,11 +3703,11 @@ static void _sde_plane_setup_capabilities_blob(struct sde_plane *psde,
 	sde_kms_info_add_keyint(info, "max_per_pipe_bw_high",
 			psde->pipe_sblk->max_per_pipe_bw_high * 1000LL);
 
-	if (psde->pipe <= SSPP_VIG3 && psde->pipe >= SSPP_VIG0)
+	if (SDE_SSPP_VALID_VIG(psde->pipe))
 		pipe_id = psde->pipe -  SSPP_VIG0;
-	else if (psde->pipe <= SSPP_RGB3 && psde->pipe >= SSPP_RGB0)
+	else if (SDE_SSPP_VALID_RGB(psde->pipe))
 		pipe_id = psde->pipe -  SSPP_RGB0;
-	else if (psde->pipe <= SSPP_DMA3 && psde->pipe >= SSPP_DMA0)
+	else if (SDE_SSPP_VALID_DMA(psde->pipe))
 		pipe_id = psde->pipe -  SSPP_DMA0;
 	else
 		pipe_id = -1;
@@ -4738,6 +4738,7 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
 	struct msm_drm_private *priv;
 	struct sde_kms *kms;
 	enum drm_plane_type type;
+	struct sde_vbif_clk_client clk_client;
 	int ret = -EINVAL;
 
 	if (!dev) {
@@ -4783,8 +4784,8 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
 	}
 
 	/* initialize underlying h/w driver */
-	psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
-							psde->is_virtual);
+	psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog, psde->is_virtual,
+			&clk_client);
 	if (IS_ERR(psde->pipe_hw)) {
 		SDE_ERROR("[%u]SSPP init failed\n", pipe);
 		ret = PTR_ERR(psde->pipe_hw);
@@ -4794,6 +4795,15 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
 		goto clean_sspp;
 	}
 
+	if (test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, kms->catalog->features)) {
+		ret = sde_vbif_clk_register(kms, &clk_client);
+		if (ret) {
+			SDE_ERROR("failed to register vbif client %d\n",
+					clk_client.clk_ctrl);
+			goto clean_sspp;
+		}
+	}
+
 	/* cache features mask for later */
 	psde->features = psde->pipe_hw->cap->features_ext;
 	psde->perf_features = psde->pipe_hw->cap->perf_features;

+ 14 - 1
msm/sde/sde_rm.c

@@ -19,6 +19,7 @@
 #include "sde_hw_vdc.h"
 #include "sde_crtc.h"
 #include "sde_hw_qdss.h"
+#include "sde_vbif.h"
 
 #define RESERVED_BY_OTHER(h, r) \
 	(((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) ||\
@@ -597,9 +598,12 @@ static int _sde_rm_hw_blk_create(
 		uint32_t id,
 		void *hw_catalog_info)
 {
+	int rc;
 	struct sde_rm_hw_blk *blk;
 	struct sde_hw_mdp *hw_mdp;
 	struct sde_hw_blk_reg_map *hw;
+	struct sde_kms *sde_kms = to_sde_kms(ddev_to_msm_kms(rm->dev));
+	struct sde_vbif_clk_client clk_client;
 
 	hw_mdp = rm->hw_mdp;
 
@@ -626,7 +630,7 @@ static int _sde_rm_hw_blk_create(
 		hw = sde_hw_intf_init(id, mmio, cat);
 		break;
 	case SDE_HW_BLK_WB:
-		hw = sde_hw_wb_init(id, mmio, cat, hw_mdp);
+		hw = sde_hw_wb_init(id, mmio, cat, hw_mdp, &clk_client);
 		break;
 	case SDE_HW_BLK_DSC:
 		hw = sde_hw_dsc_init(id, mmio, cat);
@@ -666,6 +670,15 @@ static int _sde_rm_hw_blk_create(
 
 	_sde_rm_inc_resource_info(rm, &rm->avail_res, blk);
 
+	if (test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features) &&
+			SDE_CLK_CTRL_VALID(clk_client.clk_ctrl)) {
+		rc = sde_vbif_clk_register(sde_kms, &clk_client);
+		if (rc) {
+			SDE_ERROR("failed to register vbif client %d\n", clk_client.clk_ctrl);
+			return -EFAULT;
+		}
+	}
+
 	return 0;
 }
 

+ 131 - 18
msm/sde/sde_vbif.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__
@@ -14,6 +14,121 @@
 
 #define MAX_XIN_CLIENT	16
 
+#define VBIF_CLK_CLIENT(x) sde_kms->vbif_clk_clients[x]
+#define VBIF_CLK_CLIENT_NAME(x) sde_clk_ctrl_type_s[x]
+
+int sde_vbif_clk_register(struct sde_kms *sde_kms, struct sde_vbif_clk_client *client)
+{
+	enum sde_clk_ctrl_type clk_ctrl;
+
+	if (!sde_kms || !client)
+		return -EINVAL;
+
+	clk_ctrl = client->clk_ctrl;
+	if (!SDE_CLK_CTRL_VALID(clk_ctrl))
+		return -EINVAL;
+
+	VBIF_CLK_CLIENT(clk_ctrl).hw = client->hw;
+	VBIF_CLK_CLIENT(clk_ctrl).clk_ctrl = clk_ctrl;
+	memcpy(&VBIF_CLK_CLIENT(clk_ctrl).ops, &client->ops, sizeof(struct sde_vbif_clk_ops));
+
+	SDE_DEBUG("registering hw:%pK clk_ctrl:%s\n", client->hw, VBIF_CLK_CLIENT_NAME(clk_ctrl));
+
+	return 0;
+}
+
+/**
+ * _sde_vbif_setup_clk_supported - check if VBIF setup_clk_force_ctrl API is supported
+ * @sde_kms:	Pointer to sde_kms object
+ * @clk_ctrl:	clock to be controlled
+ * @return:	true if client is supported, otherwise false
+ */
+static bool _sde_vbif_setup_clk_supported(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl)
+{
+	bool supported = false;
+	bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
+
+	if ((has_split_vbif && VBIF_CLK_CLIENT(clk_ctrl).ops.setup_clk_force_ctrl) ||
+			(!has_split_vbif && sde_kms->hw_mdp->ops.setup_clk_force_ctrl))
+		supported = true;
+
+	SDE_DEBUG("split_vbif:%d type:%s supported:%d\n", has_split_vbif,
+			VBIF_CLK_CLIENT_NAME(clk_ctrl), supported);
+
+	return supported;
+}
+
+/**
+ * _sde_vbif_get_clk_supported - check if VBIF get_clk_ctrl_status API is supported
+ * @sde_kms:	Pointer to sde_kms object
+ * @clk_ctrl:	clock to be controlled
+ * @return:	true if client is supported, otherwise false
+ */
+static bool _sde_vbif_get_clk_supported(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl)
+{
+	bool supported = false;
+	bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
+
+	if ((has_split_vbif && VBIF_CLK_CLIENT(clk_ctrl).ops.get_clk_ctrl_status) ||
+			(!has_split_vbif && sde_kms->hw_mdp->ops.get_clk_ctrl_status))
+		supported = true;
+
+	SDE_DEBUG("split_vbif:%d type:%s supported:%d\n", has_split_vbif,
+			VBIF_CLK_CLIENT_NAME(clk_ctrl), supported);
+
+	return supported;
+}
+
+/**
+ * _sde_vbif_setup_clk_force_ctrl - set clock force control
+ * @sde_kms:	Pointer to sde_kms object
+ * @clk_ctrl:	clock to be controlled
+ * @enable:	force on enable
+ * @return:	if the clock is forced-on by this function
+ */
+static int _sde_vbif_setup_clk_force_ctrl(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl,
+		bool enable)
+{
+	int rc = 0;
+	struct sde_hw_blk_reg_map *hw = VBIF_CLK_CLIENT(clk_ctrl).hw;
+	bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
+
+	if (has_split_vbif)
+		rc = VBIF_CLK_CLIENT(clk_ctrl).ops.setup_clk_force_ctrl(hw, clk_ctrl, enable);
+	else
+		rc = sde_kms->hw_mdp->ops.setup_clk_force_ctrl(sde_kms->hw_mdp, clk_ctrl, enable);
+
+	SDE_DEBUG("split_vbif:%d type:%s en:%d rc:%d\n", has_split_vbif,
+			VBIF_CLK_CLIENT_NAME(clk_ctrl), enable, rc);
+
+	return rc;
+}
+
+/**
+ * _sde_vbif_get_clk_ctrl_status - get clock control status
+ * @sde_kms:	Pointer to sde_kms object
+ * @clk_ctrl:	clock to be controlled
+ * @status:	returns true if clock is on
+ * @return:	0 if success, otherwise return error code
+ */
+static int _sde_vbif_get_clk_ctrl_status(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl,
+		bool *status)
+{
+	int rc = 0;
+	struct sde_hw_blk_reg_map *hw = VBIF_CLK_CLIENT(clk_ctrl).hw;
+	bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
+
+	if (has_split_vbif)
+		rc = VBIF_CLK_CLIENT(clk_ctrl).ops.get_clk_ctrl_status(hw, clk_ctrl, status);
+	else
+		rc = sde_kms->hw_mdp->ops.get_clk_ctrl_status(sde_kms->hw_mdp, clk_ctrl, status);
+
+	SDE_DEBUG("split_vbif:%d type:%s status:%d rc:%d\n", has_split_vbif,
+			VBIF_CLK_CLIENT_NAME(clk_ctrl), *status, rc);
+
+	return rc;
+}
+
 /**
  * _sde_vbif_wait_for_xin_halt - wait for the xin to halt
  * @vbif:	Pointer to hardware vbif driver
@@ -98,7 +213,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 	mdp = sde_kms->hw_mdp;
 	if (!vbif || !mdp || !vbif->ops.get_xin_halt_status ||
 		       !vbif->ops.set_xin_halt ||
-		       !mdp->ops.setup_clk_force_ctrl) {
+		       !_sde_vbif_setup_clk_supported(sde_kms, clk_ctrl)) {
 		SDE_ERROR("invalid vbif or mdp arguments\n");
 		return -EINVAL;
 	}
@@ -118,7 +233,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 		return 0;
 	}
 
-	forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
+	forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, clk_ctrl, true);
 
 	/* send halt request for unused plane's xin client */
 	vbif->ops.set_xin_halt(vbif, xin_id, true);
@@ -134,7 +249,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 	/* open xin client to enable transactions */
 	vbif->ops.set_xin_halt(vbif, xin_id, false);
 	if (forced_on)
-		mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false);
+		_sde_vbif_setup_clk_force_ctrl(sde_kms, clk_ctrl, false);
 
 	mutex_unlock(&vbif->mutex);
 
@@ -268,7 +383,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
 		return;
 	}
 
-	if (!mdp->ops.setup_clk_force_ctrl ||
+	if (!_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl) ||
 			!vbif->ops.set_limit_conf ||
 			!vbif->ops.set_xin_halt)
 		return;
@@ -289,7 +404,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
 	trace_sde_perf_set_ot(params->num, params->xin_id, ot_lim,
 		params->vbif_idx);
 
-	forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
+	forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
 
 	vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
 
@@ -302,7 +417,8 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
 	vbif->ops.set_xin_halt(vbif, params->xin_id, false);
 
 	if (forced_on)
-		mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
+		_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
+
 exit:
 	mutex_unlock(&vbif->mutex);
 }
@@ -376,7 +492,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
 		return false;
 	}
 
-	if (!mdp->ops.setup_clk_force_ctrl ||
+	if (!_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl) ||
 			!vbif->ops.set_xin_halt)
 		return false;
 
@@ -385,8 +501,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
 	SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
 
 	if (params->enable) {
-		forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
-				params->clk_ctrl, true);
+		forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
 
 		vbif->ops.set_xin_halt(vbif, params->xin_id, true);
 
@@ -397,8 +512,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
 		vbif->ops.set_xin_halt(vbif, params->xin_id, false);
 
 		if (params->forced_on)
-			mdp->ops.setup_clk_force_ctrl(mdp,
-					params->clk_ctrl, false);
+			_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
 	}
 
 	mutex_unlock(&vbif->mutex);
@@ -440,7 +554,7 @@ bool sde_vbif_get_xin_status(struct sde_kms *sde_kms,
 		return false;
 	}
 
-	if (!mdp->ops.get_clk_ctrl_status ||
+	if (!_sde_vbif_get_clk_supported(sde_kms, params->clk_ctrl) ||
 			!vbif->ops.get_xin_halt_status)
 		return false;
 
@@ -448,8 +562,7 @@ bool sde_vbif_get_xin_status(struct sde_kms *sde_kms,
 	SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
 	status = vbif->ops.get_xin_halt_status(vbif, params->xin_id);
 	if (status) {
-		rc = !mdp->ops.get_clk_ctrl_status(mdp, params->clk_ctrl,
-				&status);
+		rc = _sde_vbif_get_clk_ctrl_status(sde_kms, params->clk_ctrl, &status);
 		if (rc)
 			status = false;
 	}
@@ -492,7 +605,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
 		return;
 	}
 
-	if (!vbif->ops.set_qos_remap || !mdp->ops.setup_clk_force_ctrl) {
+	if (!vbif->ops.set_qos_remap || !_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl)) {
 		SDE_DEBUG("qos remap not supported\n");
 		return;
 	}
@@ -510,7 +623,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
 
 	mutex_lock(&vbif->mutex);
 
-	forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
+	forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
 
 	for (i = 0; i < qos_tbl->npriority_lvl; i++) {
 		SDE_DEBUG("vbif:%d xin:%d lvl:%d/%d\n",
@@ -521,7 +634,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
 	}
 
 	if (forced_on)
-		mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
+		_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
 
 	mutex_unlock(&vbif->mutex);
 }

+ 9 - 1
msm/sde/sde_vbif.h

@@ -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.
  */
 
 #ifndef __SDE_VBIF_H__
@@ -72,6 +72,14 @@ struct sde_vbif_set_qos_params {
 	enum sde_vbif_client_type client_type;
 };
 
+/**
+ * sde_vbif_clk_register - register vbif clk client
+ * @sde_kms:	SDE handler
+ * @client:	pointer to VBIF clk client info
+ * Returns:	0 on success, error code otherwise
+ */
+int sde_vbif_clk_register(struct sde_kms *sde_kms, struct sde_vbif_clk_client *client);
+
 /**
  * sde_vbif_set_ot_limit - set OT limit for vbif client
  * @sde_kms:	SDE handler