Bläddra i källkod

disp: msm: sde: add support for new QoS mode of WB rotation

This change adds support for new dynamic QoS mode for WB rotation
which is required to achieve rotation output available at required
rate to meet real time use case. Though traffic shaper can be
disabled in dynamic QoS mode, part of traffic shaper algo to track
WB operating speed is enabled and WB generates creq priority
based on current ouput rate compared to targetted ouput to help
meeting real time use case requirement.

Change-Id: I98c2dcae53f1b175dc49b40238b9da33e95717a6
Signed-off-by: Prabhanjan Kandula <[email protected]>
Prabhanjan Kandula 3 år sedan
förälder
incheckning
c3991049c1
5 ändrade filer med 44 tillägg och 6 borttagningar
  1. 1 0
      msm/msm_drv.h
  2. 18 5
      msm/sde/sde_encoder_phys_wb.c
  3. 6 0
      msm/sde/sde_hw_wb.c
  4. 14 0
      msm/sde/sde_hw_wb.h
  5. 5 1
      msm/sde/sde_wb.c

+ 1 - 0
msm/msm_drv.h

@@ -244,6 +244,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_DSC_MODE,
 	CONNECTOR_PROP_WB_USAGE_TYPE,
 	CONNECTOR_PROP_WB_ROT_TYPE,
+	CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK,
 
 	/* total # of properties */
 	CONNECTOR_PROP_COUNT

+ 18 - 5
msm/sde/sde_encoder_phys_wb.c

@@ -101,8 +101,7 @@ static void sde_encoder_phys_wb_set_ot_limit(struct sde_encoder_phys *phys_enc)
 	ot_params.num = hw_wb->idx - WB_0;
 	ot_params.width = wb_enc->wb_roi.w;
 	ot_params.height = wb_enc->wb_roi.h;
-	ot_params.is_wfd = ((phys_enc->in_clone_mode) || (usage_type == WB_USAGE_OFFLINE_WB)) ?
-					false : true;
+	ot_params.is_wfd = (usage_type == WB_USAGE_WFD);
 	ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode);
 	ot_params.vbif_idx = hw_wb->caps->vbif_idx;
 	ot_params.clk_ctrl = hw_wb->caps->clk_ctrl;
@@ -153,7 +152,7 @@ static void sde_encoder_phys_wb_set_qos_remap(struct sde_encoder_phys *phys_enc)
 	qos_params.num = hw_wb->idx - WB_0;
 	if (phys_enc->in_clone_mode)
 		qos_params.client_type = VBIF_CWB_CLIENT;
-	else if (usage_type == WB_USAGE_OFFLINE_WB)
+	else if (usage_type == WB_USAGE_OFFLINE_WB || usage_type == WB_USAGE_ROT)
 		qos_params.client_type = VBIF_OFFLINE_WB_CLIENT;
 	else
 		qos_params.client_type = VBIF_NRT_CLIENT;
@@ -206,13 +205,19 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
 	}
 
 	qos_cfg.danger_safe_en = true;
+	if (usage_type == WB_USAGE_ROT) {
+		qos_cfg.danger_safe_en = false;
+		qos_cfg.qos_mode = SDE_WB_QOS_MODE_DYNAMIC;
+		qos_cfg.bytes_per_clk = sde_connector_get_property(conn_state,
+				CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK);
+	}
 
 	if (phys_enc->in_clone_mode)
 		lut_index = (SDE_FORMAT_IS_TILE(wb_enc->wb_fmt)
 				|| SDE_FORMAT_IS_UBWC(wb_enc->wb_fmt)) ?
 					SDE_QOS_LUT_USAGE_CWB_TILE : SDE_QOS_LUT_USAGE_CWB;
 	else
-		lut_index = (usage_type == WB_USAGE_OFFLINE_WB) ?
+		lut_index = (usage_type == WB_USAGE_OFFLINE_WB || usage_type == WB_USAGE_ROT) ?
 					SDE_QOS_LUT_USAGE_OFFLINE_WB : SDE_QOS_LUT_USAGE_NRT;
 
 	creq_index = lut_index * SDE_CREQ_LUT_TYPE_MAX;
@@ -996,14 +1001,15 @@ static int _sde_encoder_phys_wb_validate_rotation(struct sde_encoder_phys *phys_
 	enum sde_wb_rot_type rotation_type;
 	int ret = 0;
 	u32 src_w, src_h;
+	u32 bytes_per_clk;
 	struct sde_rect wb_src, wb_roi = {0,};
 	struct sde_io_res dnsc_res = {0,};
 	const struct sde_rect *crtc_roi = NULL;
 	struct drm_display_mode *mode;
+	enum sde_wb_usage_type usage_type;
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
 
 	rotation_type = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_ROT_TYPE);
-
 	if (rotation_type == WB_ROT_NONE)
 		return ret;
 
@@ -1014,6 +1020,13 @@ static int _sde_encoder_phys_wb_validate_rotation(struct sde_encoder_phys *phys_
 		return -EINVAL;
 	}
 
+	bytes_per_clk = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK);
+	if (!bytes_per_clk) {
+		SDE_ERROR("[enc:%d wb:%d] WB output bytes per XO clock is must for rotation\n",
+				DRMID(phys_enc->parent), WBID(wb_enc));
+		return -EINVAL;
+	}
+
 	ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi);
 	if (ret) {
 		SDE_ERROR("[enc:%d wb:%d] failed to get WB output roi, ret:%d\n",

+ 6 - 0
msm/sde/sde_hw_wb.c

@@ -23,6 +23,7 @@
 #define WB_DST3_ADDR			0x018
 #define WB_DST_YSTRIDE0			0x01C
 #define WB_DST_YSTRIDE1			0x020
+#define WB_TS_WR_CLIENT	                0x040
 #define WB_DST_WRITE_CONFIG		0x048
 #define WB_OUT_SIZE			0x074
 #define WB_ALPHA_X_VALUE		0x078
@@ -307,6 +308,11 @@ static void sde_hw_wb_setup_qos_lut(struct sde_hw_wb *ctx,
 	if (cfg->danger_safe_en)
 		qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN;
 
+	if (test_bit(SDE_WB_LINEAR_ROTATION, &ctx->caps->features)) {
+		SDE_REG_WRITE(c, WB_TS_WR_CLIENT, cfg->bytes_per_clk & 0xFF);
+		qos_ctrl |= (cfg->qos_mode << 1);
+	}
+
 	SDE_REG_WRITE(c, WB_QOS_CTRL, qos_ctrl);
 }
 

+ 14 - 0
msm/sde/sde_hw_wb.h

@@ -49,17 +49,31 @@ struct sde_hw_wb_cdp_cfg {
 	u32 preload_ahead;
 };
 
+/**
+ * enum sde_hw_wb_qos_mode: enumeration of available QOS modes for WB
+ * @SDE_WB_QOS_MODE_STATIC: static qos mode same as existing NRT qos mode
+ * @SDE_WB_QOS_MODE_DYNAMIC: new qos mode to support rotation for real time
+ */
+enum sde_hw_wb_qos_mode {
+	SDE_WB_QOS_MODE_STATIC,
+	SDE_WB_QOS_MODE_DYNAMIC,
+};
+
 /**
  * struct sde_hw_wb_qos_cfg : Writeback pipe QoS configuration
  * @danger_lut: LUT for generate danger level based on fill level
  * @safe_lut: LUT for generate safe level based on fill level
  * @creq_lut: LUT for generate creq level based on fill level
+ * @bytes_per_clk: WB output bytes per XO clock value used in rotation
+ * @qos_mode: enum value mapped for selecting WB QOS mode
  * @danger_safe_en: enable danger safe generation
  */
 struct sde_hw_wb_qos_cfg {
 	u32 danger_lut;
 	u32 safe_lut;
 	u64 creq_lut;
+	u32 bytes_per_clk;
+	enum sde_hw_wb_qos_mode qos_mode;
 	bool danger_safe_en;
 };
 

+ 5 - 1
msm/sde/sde_wb.c

@@ -682,11 +682,15 @@ int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
 		msm_property_install_range(&c_conn->property_info, "dnsc_blur",
 			0x0, 0, ~0, 0, CONNECTOR_PROP_DNSC_BLUR);
 
-	if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION))
+	if (wb_dev->wb_cfg->features & BIT(SDE_WB_LINEAR_ROTATION)) {
 		msm_property_install_enum(&c_conn->property_info, "wb_rotate_type",
 			0x0, 0, e_wb_rotate_type, ARRAY_SIZE(e_wb_rotate_type),
 			0, CONNECTOR_PROP_WB_ROT_TYPE);
 
+		msm_property_install_range(&c_conn->property_info, "wb_rot_bytes_per_clk",
+			0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_WB_ROT_BYTES_PER_CLK);
+	}
+
 	msm_property_install_enum(&c_conn->property_info, "wb_usage_type",
 			0x0, 0, e_wb_usage_type, ARRAY_SIZE(e_wb_usage_type),
 			0, CONNECTOR_PROP_WB_USAGE_TYPE);