Browse Source

disp: msm: sde: add support for WB VBIF clock split

Add support for localized CLK_CTRL access through WB
hardware block.

Change-Id: I408d1bbc798902d1abc7da5bcae9492baa3159c8
Signed-off-by: Amine Najahi <[email protected]>
Amine Najahi 3 years ago
parent
commit
c8a4cdc761
4 changed files with 92 additions and 25 deletions
  1. 20 22
      msm/sde/sde_hw_catalog.c
  2. 54 1
      msm/sde/sde_hw_wb.c
  3. 4 1
      msm/sde/sde_hw_wb.h
  4. 14 1
      msm/sde/sde_rm.c

+ 20 - 22
msm/sde/sde_hw_catalog.c

@@ -2588,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:

+ 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.

+ 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;
 }