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

disp: msm: sde: add offline WB QoS support

Add support to parse and configure QoS values for offline writeback.
Expose a writeback connector property to allow user-mode to set
the usage type of the writeback block - WFD, CWB, offline-WB.

Change-Id: I864f79c4896ec757ac2d8b0f57a6a5775d164f21
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 3 жил өмнө
parent
commit
b7f241585a

+ 2 - 0
msm/msm_drv.h

@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -233,6 +234,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_AVR_STEP,
 	CONNECTOR_PROP_CACHE_STATE,
 	CONNECTOR_PROP_DSC_MODE,
+	CONNECTOR_PROP_WB_USAGE_TYPE,
 
 	/* total # of properties */
 	CONNECTOR_PROP_COUNT

+ 3 - 0
msm/sde/sde_connector.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -682,6 +683,7 @@ struct sde_connector {
  * @dnsc_blur_count: Number of downscale blur blocks used
  * @dnsc_blur_cfg: Configs for the downscale blur block
  * @dnsc_blur_lut: LUT idx used for the Gaussian filter LUTs in downscale blur block
+ * @usage_type: WB connector usage type
  */
 struct sde_connector_state {
 	struct drm_connector_state base;
@@ -702,6 +704,7 @@ struct sde_connector_state {
 	u32 dnsc_blur_count;
 	struct sde_drm_dnsc_blur_cfg dnsc_blur_cfg[DNSC_BLUR_MAX_COUNT];
 	u32 dnsc_blur_lut;
+	enum sde_wb_usage_type usage_type;
 };
 
 /**

+ 21 - 1
msm/sde/sde_crtc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -140,6 +140,26 @@ static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
 	return to_sde_kms(priv->kms);
 }
 
+enum sde_wb_usage_type sde_crtc_get_wb_usage_type(struct drm_crtc *crtc)
+{
+	struct drm_connector *conn;
+	struct drm_connector_list_iter conn_iter;
+	enum sde_wb_usage_type usage_type = 0;
+
+	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
+	drm_for_each_connector_iter(conn, &conn_iter) {
+		if (conn->state && (conn->state->crtc == crtc)
+				&& (conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)) {
+			usage_type = sde_connector_get_property(conn->state,
+					CONNECTOR_PROP_WB_USAGE_TYPE);
+			break;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	return usage_type;
+}
+
 static inline struct drm_connector_state *_sde_crtc_get_virt_conn_state(
 		struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
 {

+ 7 - 1
msm/sde/sde_crtc.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -720,6 +720,12 @@ u32 sde_crtc_get_fps_mode(struct drm_crtc *crtc);
  */
 u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc);
 
+/**
+ * sde_crtc_get_wb_usage_type - get writeback usage type
+ * @crtc: Pointert to crtc
+ */
+enum sde_wb_usage_type sde_crtc_get_wb_usage_type(struct drm_crtc *crtc);
+
 /**
  * sde_crtc_get_client_type - check the crtc type- rt, rsc_rt, etc.
  * @crtc: Pointer to crtc

+ 31 - 13
msm/sde/sde_encoder_phys_wb.c

@@ -78,19 +78,24 @@ static enum sde_intr_type sde_encoder_phys_wb_get_intr_type(
  * sde_encoder_phys_wb_set_ot_limit - set OT limit for writeback interface
  * @phys_enc:	Pointer to physical encoder
  */
-static void sde_encoder_phys_wb_set_ot_limit(
-		struct sde_encoder_phys *phys_enc)
+static void sde_encoder_phys_wb_set_ot_limit(struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
 	struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
+	struct drm_connector_state *conn_state;
 	struct sde_vbif_set_ot_params ot_params;
+	enum sde_wb_usage_type usage_type;
+
+	conn_state = phys_enc->connector->state;
+	usage_type = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_USAGE_TYPE);
 
 	memset(&ot_params, 0, sizeof(ot_params));
 	ot_params.xin_id = hw_wb->caps->xin_id;
 	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);
+	ot_params.is_wfd = ((phys_enc->in_clone_mode) || (usage_type == WB_USAGE_OFFLINE_WB)) ?
+					false : true;
 	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;
@@ -108,7 +113,9 @@ static void sde_encoder_phys_wb_set_qos_remap(struct sde_encoder_phys *phys_enc)
 	struct sde_encoder_phys_wb *wb_enc;
 	struct sde_hw_wb *hw_wb;
 	struct drm_crtc *crtc;
+	struct drm_connector_state *conn_state;
 	struct sde_vbif_set_qos_params qos_params;
+	enum sde_wb_usage_type usage_type;
 
 	if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) {
 		SDE_ERROR("invalid arguments\n");
@@ -122,6 +129,8 @@ static void sde_encoder_phys_wb_set_qos_remap(struct sde_encoder_phys *phys_enc)
 	}
 
 	crtc = wb_enc->crtc;
+	conn_state = phys_enc->connector->state;
+	usage_type = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_USAGE_TYPE);
 
 	if (!wb_enc->hw_wb || !wb_enc->hw_wb->caps) {
 		SDE_ERROR("[enc:%d wb:%d] invalid WB HW\n", DRMID(phys_enc->parent), WBID(wb_enc));
@@ -135,8 +144,12 @@ static void sde_encoder_phys_wb_set_qos_remap(struct sde_encoder_phys *phys_enc)
 	qos_params.xin_id = hw_wb->caps->xin_id;
 	qos_params.clk_ctrl = hw_wb->caps->clk_ctrl;
 	qos_params.num = hw_wb->idx - WB_0;
-	qos_params.client_type = phys_enc->in_clone_mode ?
-					VBIF_CWB_CLIENT : VBIF_NRT_CLIENT;
+	if (phys_enc->in_clone_mode)
+		qos_params.client_type = VBIF_CWB_CLIENT;
+	else if (usage_type == WB_USAGE_OFFLINE_WB)
+		qos_params.client_type = VBIF_OFFLINE_WB_CLIENT;
+	else
+		qos_params.client_type = VBIF_NRT_CLIENT;
 
 	SDE_DEBUG("[enc:%d wb:%d] qos_remap - wb:%d vbif:%d xin:%d clone:%d\n",
 		DRMID(phys_enc->parent), WBID(wb_enc), qos_params.num,
@@ -153,9 +166,11 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_phys_wb *wb_enc;
 	struct sde_hw_wb *hw_wb;
+	struct drm_connector_state *conn_state;
 	struct sde_hw_wb_qos_cfg qos_cfg = {0};
 	struct sde_perf_cfg *perf;
 	u32 fps_index = 0, lut_index, creq_index, ds_index, frame_rate, qos_count;
+	enum sde_wb_usage_type usage_type;
 
 	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog) {
 		SDE_ERROR("invalid parameter(s)\n");
@@ -168,6 +183,9 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
 		return;
 	}
 
+	conn_state = phys_enc->connector->state;
+	usage_type = sde_connector_get_property(conn_state, CONNECTOR_PROP_WB_USAGE_TYPE);
+
 	perf = &phys_enc->sde_kms->catalog->perf;
 	frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode);
 
@@ -182,13 +200,13 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
 
 	qos_cfg.danger_safe_en = true;
 
-	if (phys_enc->in_clone_mode && (SDE_FORMAT_IS_TILE(wb_enc->wb_fmt) ||
-				SDE_FORMAT_IS_UBWC(wb_enc->wb_fmt)))
-		lut_index = SDE_QOS_LUT_USAGE_CWB_TILE;
-	else if (phys_enc->in_clone_mode)
-		lut_index = SDE_QOS_LUT_USAGE_CWB;
+	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 = SDE_QOS_LUT_USAGE_NRT;
+		lut_index = (usage_type == WB_USAGE_OFFLINE_WB) ?
+					SDE_QOS_LUT_USAGE_OFFLINE_WB : SDE_QOS_LUT_USAGE_NRT;
 
 	creq_index = lut_index * SDE_CREQ_LUT_TYPE_MAX;
 	creq_index += (fps_index * SDE_QOS_LUT_USAGE_MAX * SDE_CREQ_LUT_TYPE_MAX);
@@ -199,9 +217,9 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
 	qos_cfg.danger_lut = perf->danger_lut[ds_index];
 	qos_cfg.safe_lut = (u32) perf->safe_lut[ds_index];
 
-	SDE_DEBUG("[enc:%d wb:%d] fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n",
+	SDE_DEBUG("[enc:%d wb:%d] fps:%d mode:%d type:%d luts[0x%x,0x%x 0x%llx]\n",
 		DRMID(phys_enc->parent), WBID(wb_enc), frame_rate, phys_enc->in_clone_mode,
-		qos_cfg.danger_lut, qos_cfg.safe_lut, qos_cfg.creq_lut);
+		usage_type, qos_cfg.danger_lut, qos_cfg.safe_lut, qos_cfg.creq_lut);
 
 	if (hw_wb->ops.setup_qos_lut)
 		hw_wb->ops.setup_qos_lut(hw_wb, &qos_cfg);

+ 8 - 0
msm/sde/sde_hw_catalog.c

@@ -502,6 +502,7 @@ enum {
 	VBIF_QOS_CWB_REMAP,
 	VBIF_QOS_LUTDMA_REMAP,
 	VBIF_QOS_CNOC_REMAP,
+	VBIF_QOS_OFFLINE_WB_REMAP,
 	VBIF_PROP_MAX,
 };
 
@@ -943,6 +944,8 @@ static struct sde_prop_type vbif_prop[] = {
 	{VBIF_QOS_CWB_REMAP, "qcom,sde-vbif-qos-cwb-remap", false, PROP_TYPE_U32_ARRAY},
 	{VBIF_QOS_LUTDMA_REMAP, "qcom,sde-vbif-qos-lutdma-remap", false, PROP_TYPE_U32_ARRAY},
 	{VBIF_QOS_CNOC_REMAP, "qcom,sde-vbif-qos-cnoc-remap", false, PROP_TYPE_U32_ARRAY},
+	{VBIF_QOS_OFFLINE_WB_REMAP, "qcom,sde-vbif-qos-offline-wb-remap", false,
+		PROP_TYPE_U32_ARRAY},
 };
 
 static struct sde_prop_type uidle_prop[] = {
@@ -3863,6 +3866,11 @@ static int sde_vbif_parse_dt(struct device_node *np,
 	if (rc)
 		goto end;
 
+	rc = _validate_dt_entry(np, &vbif_prop[VBIF_QOS_OFFLINE_WB_REMAP], 1,
+			&prop_count[VBIF_QOS_OFFLINE_WB_REMAP], NULL);
+	if (rc)
+		goto end;
+
 	sde_cfg->vbif_count = off_count;
 
 	rc = _read_dt_entry(np, vbif_prop, ARRAY_SIZE(vbif_prop), prop_count,

+ 3 - 0
msm/sde/sde_hw_catalog.h

@@ -850,6 +850,7 @@ enum sde_qos_lut_usage {
 	SDE_QOS_LUT_USAGE_CWB_TILE,
 	SDE_QOS_LUT_USAGE_INLINE,
 	SDE_QOS_LUT_USAGE_INLINE_RESTRICTED_FMTS,
+	SDE_QOS_LUT_USAGE_OFFLINE_WB,
 	SDE_QOS_LUT_USAGE_MAX,
 };
 
@@ -1509,6 +1510,7 @@ struct sde_vbif_qos_tbl {
  * @VBIF_CWB_CLIENT: concurrent writeback client
  * @VBIF_LUTDMA_CLIENT: LUTDMA client
  * @VBIF_CNOC_CLIENT: HW fence client
+ * @VBIF_OFFLINE_WB_CLIENT: Offline WB client used in 2-pass composition
  * @VBIF_MAX_CLIENT: max number of clients
  */
 enum sde_vbif_client_type {
@@ -1517,6 +1519,7 @@ enum sde_vbif_client_type {
 	VBIF_CWB_CLIENT,
 	VBIF_LUTDMA_CLIENT,
 	VBIF_CNOC_CLIENT,
+	VBIF_OFFLINE_WB_CLIENT,
 	VBIF_MAX_CLIENT
 };
 

+ 13 - 1
msm/sde/sde_hw_mdss.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -500,6 +500,18 @@ enum sde_sys_cache_state {
 	CACHE_STATE_FRAME_READ
 };
 
+/**
+ * enum sde_wb_usage_type: Type of usage of the WB connector
+ * WB_USAGE_WFD: WB connector used for WFD
+ * WB_USAGE_CWB: WB connector used for concurrent writeback
+ * WB_USAGE_OFFLINE_WB: WB connector used for 2-pass composition
+ */
+enum sde_wb_usage_type {
+	WB_USAGE_WFD,
+	WB_USAGE_CWB,
+	WB_USAGE_OFFLINE_WB,
+};
+
 /** struct sde_format - defines the format configuration which
  * allows SDE HW to correctly fetch and decode the format
  * @base: base msm_format struture containing fourcc code

+ 14 - 18
msm/sde/sde_plane.c

@@ -78,18 +78,6 @@ enum sde_plane_qos {
 	SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
 };
 
-/*
- * struct sde_plane - local sde plane structure
- * @aspace: address space pointer
- * @csc_cfg: Decoded user configuration for csc
- * @csc_usr_ptr: Points to csc_cfg if valid user config available
- * @csc_ptr: Points to sde_csc_cfg structure to use for current
- * @mplane_list: List of multirect planes of the same pipe
- * @catalog: Points to sde catalog structure
- * @revalidate: force revalidation of all the plane properties
- * @xin_halt_forced_clk: whether or not clocks were forced on for xin halt
- * @blob_rot_caps: Pointer to rotator capability blob
- */
 struct sde_plane {
 	struct drm_plane base;
 
@@ -108,6 +96,7 @@ struct sde_plane {
 	uint32_t color_fill;
 	bool is_error;
 	bool is_rt_pipe;
+	enum sde_wb_usage_type wb_usage_type;
 	bool is_virtual;
 	struct list_head mplane_list;
 	struct sde_mdss_cfg *catalog;
@@ -305,7 +294,8 @@ static void _sde_plane_set_qos_lut(struct drm_plane *plane,
 		else
 			lut_index = SDE_QOS_LUT_USAGE_MACROTILE;
 	} else {
-		lut_index = SDE_QOS_LUT_USAGE_NRT;
+		lut_index = (psde->wb_usage_type == WB_USAGE_OFFLINE_WB) ?
+					SDE_QOS_LUT_USAGE_OFFLINE_WB : SDE_QOS_LUT_USAGE_NRT;
 	}
 
 	creq_lut_index = lut_index * SDE_CREQ_LUT_TYPE_MAX;
@@ -325,11 +315,12 @@ static void _sde_plane_set_qos_lut(struct drm_plane *plane,
 			(fmt) ? fmt->fetch_mode : 0, psde->pipe_qos_cfg.danger_lut,
 			psde->pipe_qos_cfg.safe_lut, psde->pipe_qos_cfg.creq_lut);
 
-	SDE_DEBUG("plane%u: pnum:%d fmt:%4.4s fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n",
+	SDE_DEBUG("plane%u: pnum:%d fmt:%4.4s fps:%d mode:%d lut[0x%x,0x%x 0x%llx] rt:%d type:%d\n",
 		plane->base.id, psde->pipe - SSPP_VIG0,
 		fmt ? (char *)&fmt->base.pixel_format : NULL, frame_rate,
 		fmt ? fmt->fetch_mode : -1, psde->pipe_qos_cfg.danger_lut,
-		psde->pipe_qos_cfg.safe_lut, psde->pipe_qos_cfg.creq_lut);
+		psde->pipe_qos_cfg.safe_lut, psde->pipe_qos_cfg.creq_lut,
+		psde->is_rt_pipe, psde->wb_usage_type);
 
 	psde->pipe_hw->ops.setup_qos_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
 }
@@ -472,7 +463,8 @@ static void _sde_plane_set_ot_limit(struct drm_plane *plane,
 	ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
 	ot_params.width = psde->pipe_cfg.src_rect.w;
 	ot_params.height = psde->pipe_cfg.src_rect.h;
-	ot_params.is_wfd = !psde->is_rt_pipe;
+	ot_params.is_wfd = ((psde->is_rt_pipe)
+				|| (psde->wb_usage_type == WB_USAGE_OFFLINE_WB)) ? false : true;
 	ot_params.frame_rate = drm_mode_vrefresh(&crtc->mode);
 	ot_params.vbif_idx = VBIF_RT;
 	ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
@@ -515,8 +507,11 @@ static void _sde_plane_set_qos_remap(struct drm_plane *plane)
 	qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
 	qos_params.xin_id = psde->pipe_hw->cap->xin_id;
 	qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
-	qos_params.client_type = psde->is_rt_pipe ?
-					VBIF_RT_CLIENT : VBIF_NRT_CLIENT;
+	if (psde->is_rt_pipe)
+		qos_params.client_type =  VBIF_RT_CLIENT;
+	else
+		qos_params.client_type = (psde->wb_usage_type == WB_USAGE_OFFLINE_WB) ?
+						VBIF_OFFLINE_WB_CLIENT : VBIF_NRT_CLIENT;
 
 	SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
 			plane->base.id, qos_params.num,
@@ -3331,6 +3326,7 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
 	is_rt = sde_crtc_is_rt_client(crtc, crtc->state);
 	if (is_rt != psde->is_rt_pipe || crtc->state->mode_changed) {
 		psde->is_rt_pipe = is_rt;
+		psde->wb_usage_type = psde->is_rt_pipe ? 0 : sde_crtc_get_wb_usage_type(crtc);
 		pstate->dirty |= SDE_PLANE_DIRTY_QOS;
 	}
 

+ 11 - 1
msm/sde/sde_wb.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -602,6 +603,12 @@ int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
 		{CACHE_STATE_ENABLED, "cache_state_enabled"},
 	};
 
+	static const struct drm_prop_enum_list e_wb_usage_type[] = {
+		{WB_USAGE_WFD, "wb_usage_wfd"},
+		{WB_USAGE_CWB, "wb_usage_cwb"},
+		{WB_USAGE_OFFLINE_WB, "wb_usage_offline_wb"},
+	};
+
 	if (!connector || !display || !wb_dev->wb_cfg || !wb_dev->drm_dev->dev_private) {
 		SDE_ERROR("invalid params\n");
 		return -EINVAL;
@@ -654,8 +661,11 @@ 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);
 
-	_sde_wb_connector_install_dither_property(wb_dev);
+	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);
 
+	_sde_wb_connector_install_dither_property(wb_dev);
 
 	return 0;
 }