Просмотр исходного кода

disp: msm: expose qsync avr step as part of conn mode caps

Add capability to read avr step for each timing mode. This will
be in addition to the existing avr-step-list which is defined
when dfps is enabled. Expose the avr-step as part of each
mode in connector caps to user-mode.
Additionally, change the avr_step connector property to enum
to give usermode just the capability to enable/disable avr-step
and not alter the step value as its fixed from the device tree.

Change-Id: I6d7f8e9fcf03f98abef7640fc741e5e1be8597a1
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 2 лет назад
Родитель
Сommit
2e3ba9430c

+ 5 - 1
msm/dsi/dsi_defs.h

@@ -418,7 +418,8 @@ struct dsi_panel_cmd_set {
  * @vdc:              VDC compression configuration.
  * @pclk_scale:       pclk scale factor, target bpp to source bpp
  * @roi_caps:         Panel ROI capabilities.
- * @qsync_min_fps:        Qsync min fps rate
+ * @qsync_min_fps:    Qsync min fps rate
+ * @avr_step_fps:     AVR step fps rate
  */
 struct dsi_mode_info {
 	u32 h_active;
@@ -446,6 +447,7 @@ struct dsi_mode_info {
 	struct msm_ratio pclk_scale;
 	struct msm_roi_caps roi_caps;
 	u32 qsync_min_fps;
+	u32 avr_step_fps;
 };
 
 /**
@@ -625,6 +627,7 @@ struct dsi_host_config {
  *                              for command mode panels in microseconds.
  * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels.
  * @qsync_min_fps:        Qsync min fps value for the mode
+ * @avr_step_fps:         AVR step fps value for the mode
  * @clk_rate_hz:          DSI bit clock per lane in hz.
  * @min_dsi_clk_hz:       Min dsi clk per lane to transfer frame in vsync time.
  * @bit_clk_list:         List of dynamic bit clock rates supported.
@@ -654,6 +657,7 @@ struct dsi_display_mode_priv_info {
 	u32 mdp_transfer_time_us_max;
 	u32 dsi_transfer_time_us;
 	u32 qsync_min_fps;
+	u32 avr_step_fps;
 	u64 clk_rate_hz;
 	u64 min_dsi_clk_hz;
 	struct msm_dyn_clk_list bit_clk_list;

+ 15 - 28
msm/dsi/dsi_display.c

@@ -6754,7 +6754,7 @@ int dsi_display_get_info(struct drm_connector *connector,
 	info->max_height = 1080;
 	info->qsync_min_fps = display->panel->qsync_caps.qsync_min_fps;
 	info->has_qsync_min_fps_list = (display->panel->qsync_caps.qsync_min_fps_list_len > 0);
-	info->has_avr_step_req = (display->panel->avr_caps.avr_step_fps_list_len > 0);
+	info->avr_step_fps = display->panel->avr_caps.avr_step_fps;
 	info->poms_align_vsync = display->panel->poms_align_vsync;
 
 	switch (display->panel->panel_mode) {
@@ -7040,7 +7040,7 @@ void dsi_display_put_mode(struct dsi_display *display,
 int dsi_display_get_modes_helper(struct dsi_display *display,
 	struct dsi_display_ctrl *ctrl, u32 timing_mode_count,
 	struct dsi_dfps_capabilities dfps_caps, struct dsi_qsync_capabilities *qsync_caps,
-	struct dsi_dyn_clk_caps *dyn_clk_caps)
+	struct dsi_dyn_clk_caps *dyn_clk_caps, struct dsi_avr_capabilities *avr_caps)
 {
 	int dsc_modes = 0, nondsc_modes = 0, rc = 0, i, start, end;
 	u32 num_dfps_rates, mode_idx, sublinks_count, array_idx = 0;
@@ -7143,6 +7143,10 @@ int dsi_display_get_modes_helper(struct dsi_display *display,
 			if (!sub_mode->timing.qsync_min_fps && qsync_caps->qsync_min_fps)
 				sub_mode->timing.qsync_min_fps = qsync_caps->qsync_min_fps;
 
+			/* populate avr step fps, same way as qsync min fps */
+			if (!sub_mode->timing.avr_step_fps && avr_caps->avr_step_fps)
+				sub_mode->timing.avr_step_fps = avr_caps->avr_step_fps;
+
 			/*
 			 * Qsync min fps for the mode will be populated in the timing info
 			 * in dsi_panel_get_mode function.
@@ -7175,6 +7179,12 @@ int dsi_display_get_modes_helper(struct dsi_display *display,
 				sub_mode->priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps;
 			}
 
+			/* Override with avr step fps list in dfps usecases */
+			if (avr_caps->avr_step_fps_list_len) {
+				sub_mode->timing.avr_step_fps = avr_caps->avr_step_fps_list[i];
+				sub_mode->priv_info->avr_step_fps = sub_mode->timing.avr_step_fps;
+			}
+
 			dsi_display_get_dfps_timing(display, sub_mode,
 					curr_refresh_rate);
 			sub_mode->panel_mode_caps = DSI_OP_VIDEO_MODE;
@@ -7215,6 +7225,7 @@ int dsi_display_get_modes(struct dsi_display *display,
 	struct dsi_dyn_clk_caps *dyn_clk_caps;
 	int rc = -EINVAL;
 	struct dsi_qsync_capabilities *qsync_caps;
+	struct dsi_avr_capabilities *avr_caps;
 
 	if (!display || !out_modes) {
 		DSI_ERR("Invalid params\n");
@@ -7247,6 +7258,7 @@ int dsi_display_get_modes(struct dsi_display *display,
 
 	qsync_caps = &(display->panel->qsync_caps);
 	dyn_clk_caps = &(display->panel->dyn_clk_caps);
+	avr_caps = &(display->panel->avr_caps);
 
 	timing_mode_count = display->panel->num_timing_nodes;
 
@@ -7256,7 +7268,7 @@ int dsi_display_get_modes(struct dsi_display *display,
 		display->cmdline_timing = NO_OVERRIDE;
 
 	rc = dsi_display_get_modes_helper(display, ctrl, timing_mode_count,
-			dfps_caps, qsync_caps, dyn_clk_caps);
+			dfps_caps, qsync_caps, dyn_clk_caps, avr_caps);
 	if (rc)
 		goto error;
 
@@ -7353,31 +7365,6 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm)
 	return rc;
 }
 
-int dsi_display_get_avr_step_req_fps(void *display_dsi, u32 mode_fps)
-{
-	struct dsi_display *display = (struct dsi_display *)display_dsi;
-	struct dsi_panel *panel;
-	u32 i, step = 0;
-
-	if (!display || !display->panel)
-		return -EINVAL;
-
-	panel = display->panel;
-
-	/* support a single fixed rate, or rate corresponding to dfps list entry */
-	if (panel->avr_caps.avr_step_fps_list_len == 1) {
-		step = panel->avr_caps.avr_step_fps_list[0];
-	} else if (panel->avr_caps.avr_step_fps_list_len > 1) {
-		for (i = 0; i < panel->dfps_caps.dfps_list_len; i++) {
-			if (panel->dfps_caps.dfps_list[i] == mode_fps)
-				step = panel->avr_caps.avr_step_fps_list[i];
-		}
-	}
-
-	DSI_DEBUG("mode_fps %u, avr_step fps %u\n", mode_fps, step);
-	return step;
-}
-
 int dsi_display_update_transfer_time(void *display, u32 transfer_time)
 {
 	struct dsi_display *disp = (struct dsi_display *)display;

+ 0 - 9
msm/dsi/dsi_display.h

@@ -421,15 +421,6 @@ void dsi_display_put_mode(struct dsi_display *display,
  */
 int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm);
 
-/**
- * dsi_display_get_avr_step_req_fps() - get avr step rate for given fps
- * @display:            Handle to display.
- * @mode_fps:           Fps value of current mode
- *
- * Return: AVR step rate or -ve error code.
- */
-int dsi_display_get_avr_step_req_fps(void *dsi_display, u32 mode_fps);
-
 /*
  * dsi_conn_get_lm_from_mode() - retrieves LM count from dsi mode priv info
  * @display:            Handle to display.

+ 14 - 20
msm/dsi/dsi_drm.c

@@ -641,6 +641,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
 	mode_info->mdp_transfer_time_us_max = dsi_mode->priv_info->mdp_transfer_time_us_max;
 	mode_info->disable_rsc_solver = dsi_mode->priv_info->disable_rsc_solver;
 	mode_info->qsync_min_fps = dsi_mode->timing.qsync_min_fps;
+	mode_info->avr_step_fps = dsi_mode->timing.avr_step_fps;
 	mode_info->wd_jitter = dsi_mode->priv_info->wd_jitter;
 
 	mode_info->vpadding = dsi_display->panel->host_config.vpadding;
@@ -711,29 +712,24 @@ static const struct drm_bridge_funcs dsi_bridge_ops = {
 	.mode_set     = dsi_bridge_mode_set,
 };
 
-int dsi_conn_set_avr_step_info(struct dsi_panel *panel, void *info)
+int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state)
 {
-	u32 i;
-	int idx = 0;
-	size_t buff_sz = PAGE_SIZE;
-	char *buff;
-
-	buff = kzalloc(buff_sz, GFP_KERNEL);
-	if (!buff)
-		return -ENOMEM;
+	struct sde_connector_state *sde_conn_state = to_sde_connector_state(conn_state);
+	struct msm_display_mode *msm_mode;
+	struct dsi_display_mode_priv_info *priv_info;
 
-	for (i = 0; i < panel->avr_caps.avr_step_fps_list_len && (idx < (buff_sz - 1)); i++)
-		idx += scnprintf(&buff[idx], buff_sz - idx, "%u@%u ",
-				 panel->avr_caps.avr_step_fps_list[i],
-				 panel->dfps_caps.dfps_list[i]);
+	if (!sde_conn_state)
+		return -EINVAL;
 
-	sde_kms_info_add_keystr(info, "avr step requirement", buff);
-	kfree(buff);
+	msm_mode = &sde_conn_state->msm_mode;
+	if (!msm_mode || !msm_mode->private)
+		return -EINVAL;
 
-	return 0;
+	priv_info = (struct dsi_display_mode_priv_info *)(msm_mode->private);
+	return priv_info->qsync_min_fps;
 }
 
-int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state)
+int dsi_conn_get_avr_step_fps(struct drm_connector_state *conn_state)
 {
 	struct sde_connector_state *sde_conn_state = to_sde_connector_state(conn_state);
 	struct msm_display_mode *msm_mode;
@@ -747,7 +743,7 @@ int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state)
 		return -EINVAL;
 
 	priv_info = (struct dsi_display_mode_priv_info *)(msm_mode->private);
-	return priv_info->qsync_min_fps;
+	return priv_info->avr_step_fps;
 }
 
 int dsi_conn_set_info_blob(struct drm_connector *connector,
@@ -798,8 +794,6 @@ int dsi_conn_set_info_blob(struct drm_connector *connector,
 	switch (panel->panel_mode) {
 	case DSI_OP_VIDEO_MODE:
 		sde_kms_info_add_keystr(info, "panel mode", "video");
-		if (panel->avr_caps.avr_step_fps_list_len)
-			dsi_conn_set_avr_step_info(panel, info);
 		break;
 	case DSI_OP_CMD_MODE:
 		sde_kms_info_add_keystr(info, "panel mode", "command");

+ 9 - 0
msm/dsi/dsi_drm.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -179,4 +180,12 @@ void dsi_conn_set_submode_blob_info(struct drm_connector *conn,
  * Return: Qsync min fps rate or -ve error code.
  */
 int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state);
+
+/**
+ * dsi_conn_get_avr_step_fps() - get avr step fps for given mode
+ * @conn_state:         Pointer to drm_connector_state structure
+ *
+ * Return: AVR step fps rate or -ve error code.
+ */
+int dsi_conn_get_avr_step_fps(struct drm_connector_state *conn_state);
 #endif /* _DSI_DRM_H_ */

+ 16 - 2
msm/dsi/dsi_panel.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -925,6 +925,12 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode,
 		rc = 0;
 	}
 
+	rc = utils->read_u32(utils->data, "qcom,dsi-qsync-mode-avr-step-fps", &mode->avr_step_fps);
+	if (rc) {
+		DSI_DEBUG("avr step fps not defined in timing node\n");
+		rc = 0;
+	}
+
 	DSI_DEBUG("panel vert active:%d front_portch:%d back_porch:%d pulse_width:%d\n",
 		mode->v_active, mode->v_front_porch, mode->v_back_porch,
 		mode->v_sync_width);
@@ -1292,14 +1298,22 @@ static int dsi_panel_parse_avr_caps(struct dsi_panel *panel,
 	struct dsi_parser_utils *utils = &panel->utils;
 	int val, rc = 0;
 
+	rc = of_property_read_u32(of_node, "qcom,dsi-qsync-avr-step-fps", &val);
+	if (rc)
+		DSI_DEBUG("[%s] avr step fps not defined rc:%d\n", panel->name, rc);
+	avr_caps->avr_step_fps = rc ? 0 : val;
+
 	val = utils->count_u32_elems(utils->data, "qcom,dsi-qsync-avr-step-list");
 	if (val <= 0) {
 		DSI_DEBUG("[%s] optional avr step list not defined, val:%d\n", panel->name, val);
-		return rc;
+		return 0;
 	} else if (val > 1 && val != panel->dfps_caps.dfps_list_len) {
 		DSI_ERR("[%s] avr step list size %d not same as dfps list %d\n",
 				panel->name, val, panel->dfps_caps.dfps_list_len);
 		return -EINVAL;
+	} else if ((val > 0) && (avr_caps->avr_step_fps)) {
+		DSI_ERR("[%s] both modes of avr-steps are defined\n", panel->name);
+		return -EINVAL;
 	}
 
 	avr_caps->avr_step_fps_list = kcalloc(val, sizeof(u32), GFP_KERNEL);

+ 2 - 1
msm/dsi/dsi_panel.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -99,6 +99,7 @@ struct dsi_qsync_capabilities {
 };
 
 struct dsi_avr_capabilities {
+	u32 avr_step_fps;
 	u32 *avr_step_fps_list;
 	u32 avr_step_fps_list_len;
 };

+ 6 - 4
msm/msm_drv.h

@@ -246,7 +246,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_QSYNC_MODE,
 	CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
 	CONNECTOR_PROP_SET_PANEL_MODE,
-	CONNECTOR_PROP_AVR_STEP,
+	CONNECTOR_PROP_AVR_STEP_STATE,
 	CONNECTOR_PROP_EPT,
 	CONNECTOR_PROP_CACHE_STATE,
 	CONNECTOR_PROP_DSC_MODE,
@@ -814,6 +814,7 @@ struct msm_display_wd_jitter_config {
  * @disable_rsc_solver: Dynamically disable RSC solver for the timing mode due to lower bitclk rate.
  * @dyn_clk_list: List of dynamic clock rates for RFI.
  * @qsync_min_fps: qsync min fps rate
+ * @avr_step_fps: AVR step fps rate
  * @wd_jitter:         Info for WD jitter.
  * @vpadding:        panel stacking height
  */
@@ -837,6 +838,7 @@ struct msm_mode_info {
 	bool disable_rsc_solver;
 	struct msm_dyn_clk_list dyn_clk_list;
 	u32 qsync_min_fps;
+	u32 avr_step_fps;
 	struct msm_display_wd_jitter_config wd_jitter;
 	u32 vpadding;
 };
@@ -883,9 +885,9 @@ struct msm_resource_caps_info {
  *				 used instead of panel TE in cmd mode panels
  * @poms_align_vsync:   poms with vsync aligned
  * @roi_caps:           Region of interest capability info
- * @qsync_min_fps	Minimum fps supported by Qsync feature
+ * @qsync_min_fps      Minimum fps supported by Qsync feature
  * @has_qsync_min_fps_list True if dsi-supported-qsync-min-fps-list exits
- * @has_avr_step_req    Panel has defined requirement for AVR steps
+ * @avr_step_fps        AVR step fps supported
  * @te_source		vsync source pin information
  * @dsc_count:		max dsc hw blocks used by display (only available
  *			for dsi display)
@@ -915,7 +917,7 @@ struct msm_display_info {
 
 	uint32_t qsync_min_fps;
 	bool has_qsync_min_fps_list;
-	bool has_avr_step_req;
+	uint32_t avr_step_fps;
 
 	uint32_t te_source;
 

+ 33 - 25
msm/sde/sde_connector.c

@@ -854,7 +854,7 @@ void sde_connector_set_qsync_params(struct drm_connector *connector)
 {
 	struct sde_connector *c_conn;
 	struct sde_connector_state *c_state;
-	u32 qsync_propval = 0, step_val = 0;
+	u32 qsync_propval = 0;
 	bool prop_dirty;
 
 	if (!connector)
@@ -879,15 +879,9 @@ void sde_connector_set_qsync_params(struct drm_connector *connector)
 	}
 
 	prop_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state,
-					CONNECTOR_PROP_AVR_STEP);
-	if (prop_dirty) {
-		step_val = sde_connector_get_property(c_conn->base.state, CONNECTOR_PROP_AVR_STEP);
-		if (step_val != c_conn->avr_step) {
-			SDE_DEBUG("updated avr step %d -> %d\n", c_conn->avr_step, step_val);
-			c_conn->qsync_updated = true;
-			c_conn->avr_step = step_val;
-		}
-	}
+				CONNECTOR_PROP_AVR_STEP_STATE);
+	if (prop_dirty)
+		c_conn->qsync_updated = true;
 }
 
 void sde_connector_complete_qsync_commit(struct drm_connector *conn,
@@ -2932,6 +2926,7 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
 		}
 
 		sde_kms_info_add_keyint(info, "qsync_min_fps", mode_info.qsync_min_fps);
+		sde_kms_info_add_keyint(info, "avr_step_fps", mode_info.avr_step_fps);
 		sde_kms_info_add_keyint(info, "has_cwb_crop", test_bit(SDE_FEATURE_CWB_CROP,
 								       sde_kms->catalog->features));
 		sde_kms_info_add_keyint(info, "has_dedicated_cwb_support",
@@ -3058,6 +3053,33 @@ exit:
 	return rc;
 }
 
+static void _sde_connector_install_qsync_properties(struct sde_kms *sde_kms,
+		struct sde_connector *c_conn, struct dsi_display *dsi_display,
+		struct msm_display_info *display_info)
+{
+	static const struct drm_prop_enum_list e_avr_step_state[] = {
+		{AVR_STEP_NONE, "avr_step_none"},
+		{AVR_STEP_ENABLE, "avr_step_enable"},
+		{AVR_STEP_DISABLE, "avr_step_disable"},
+	};
+
+	if (test_bit(SDE_FEATURE_QSYNC, sde_kms->catalog->features) && dsi_display &&
+			dsi_display->panel && dsi_display->panel->qsync_caps.qsync_support) {
+		msm_property_install_enum(&c_conn->property_info, "qsync_mode", 0, 0, e_qsync_mode,
+				ARRAY_SIZE(e_qsync_mode), 0, CONNECTOR_PROP_QSYNC_MODE);
+
+		if (test_bit(SDE_FEATURE_EPT, sde_kms->catalog->features))
+			msm_property_install_range(&c_conn->property_info, "EPT", 0x0, 0, U64_MAX,
+					0, CONNECTOR_PROP_EPT);
+
+		if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features) &&
+				(display_info->capabilities & MSM_DISPLAY_CAP_VID_MODE))
+			msm_property_install_enum(&c_conn->property_info, "avr_step_state",
+					0, 0, e_avr_step_state, ARRAY_SIZE(e_avr_step_state), 0,
+					CONNECTOR_PROP_AVR_STEP_STATE);
+	}
+}
+
 static int _sde_connector_install_properties(struct drm_device *dev,
 	struct sde_kms *sde_kms, struct sde_connector *c_conn,
 	int connector_type, void *display,
@@ -3169,21 +3191,7 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 			CONNECTOR_PROP_AUTOREFRESH);
 
 	if (connector_type == DRM_MODE_CONNECTOR_DSI) {
-		if (test_bit(SDE_FEATURE_QSYNC, sde_kms->catalog->features) && dsi_display &&
-		    dsi_display->panel && dsi_display->panel->qsync_caps.qsync_support) {
-			msm_property_install_enum(&c_conn->property_info,
-					"qsync_mode", 0, 0, e_qsync_mode,
-					ARRAY_SIZE(e_qsync_mode), 0,
-					CONNECTOR_PROP_QSYNC_MODE);
-			if (test_bit(SDE_FEATURE_EPT, sde_kms->catalog->features))
-				msm_property_install_range(&c_conn->property_info,
-						"EPT", 0x0, 0, U64_MAX, 0,
-						CONNECTOR_PROP_EPT);
-			if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features))
-				msm_property_install_range(&c_conn->property_info,
-						"avr_step", 0x0, 0, U32_MAX, 0,
-						CONNECTOR_PROP_AVR_STEP);
-		}
+		_sde_connector_install_qsync_properties(sde_kms, c_conn, dsi_display, display_info);
 
 		msm_property_install_enum(&c_conn->property_info, "dsc_mode", 0,
 			0, e_dsc_mode, ARRAY_SIZE(e_dsc_mode), 0, CONNECTOR_PROP_DSC_MODE);

+ 15 - 13
msm/sde/sde_connector.h

@@ -408,12 +408,11 @@ struct sde_connector_ops {
 	int (*get_qsync_min_fps)(struct drm_connector_state *conn_state);
 
 	/**
-	 * get_avr_step_req - Get the required avr_step for given fps rate
-	 * @display: Pointer to private display structure
-	 * @mode_fps: Fps value in dfps list
+	 * get_avr_step_fps - Get the required avr_step for given fps rate
+	 * @conn_state: Pointer to drm_connector_state structure
 	 * Returns: AVR step fps value on success
 	 */
-	int (*get_avr_step_req)(void *display, u32 mode_fps);
+	int (*get_avr_step_fps)(struct drm_connector_state *conn_state);
 
 	/**
 	 * set_submode_info - populate given sub mode blob
@@ -449,6 +448,18 @@ struct sde_connector_ops {
 
 };
 
+/**
+ * enum sde_connector_avr_step_state: states of avr step fps
+ * @AVR_STEP_NONE: no-op
+ * @AVR_STEP_ENABLE: enable AVR step
+ * #AVR_STEP_DISABLE: disable AVR step
+ */
+enum sde_connector_avr_step_state {
+	AVR_STEP_NONE,
+	AVR_STEP_ENABLE,
+	AVR_STEP_DISABLE,
+};
+
 /**
  * enum sde_connector_display_type - list of display types
  */
@@ -556,7 +567,6 @@ struct sde_misr_sign {
  * @dimming_bl_notify_enabled: Flag to indicate if dimming bl notify is enabled or not
  * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode
  * @qsync_updated: Qsync settings were updated
- * @avr_step: fps rate for fixed steps in AVR mode; 0 means step is disabled
  * @colorspace_updated: Colorspace property was updated
  * @last_cmd_tx_sts: status of the last command transfer
  * @hdr_capable: external hdr support present
@@ -631,7 +641,6 @@ struct sde_connector {
 	u8 hdr_plus_app_ver;
 	u32 qsync_mode;
 	bool qsync_updated;
-	u32 avr_step;
 
 	bool colorspace_updated;
 
@@ -687,13 +696,6 @@ struct sde_connector {
 #define sde_connector_get_qsync_mode(C) \
 	((C) ? to_sde_connector((C))->qsync_mode : 0)
 
-/**
- * sde_connector_get_avr_step - get sde connector's avr_step
- * @C: Pointer to drm connector structure
- * Returns: Current cached avr_step value for given connector
- */
-#define sde_connector_get_avr_step(C) ((C) ? to_sde_connector((C))->avr_step : 0)
-
 /**
  * sde_connector_get_propinfo - get sde connector's property info pointer
  * @C: Pointer to drm connector structure

+ 19 - 28
msm/sde/sde_encoder.c

@@ -1215,40 +1215,32 @@ static void _sde_encoder_get_qsync_fps_callback(struct drm_encoder *drm_enc,
 }
 
 static int _sde_encoder_avr_step_check(struct sde_connector *sde_conn,
-		struct sde_connector_state *sde_conn_state, u32 step)
+		struct sde_connector_state *sde_conn_state)
 {
-	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(sde_conn_state->base.best_encoder);
 	u32 nom_fps = drm_mode_vrefresh(sde_conn_state->msm_mode.base);
-	u32 min_fps, req_fps = 0;
+	u32 min_fps, step_fps = 0;
 	u32 vtotal = sde_conn_state->msm_mode.base->vtotal;
-	bool has_panel_req = sde_enc->disp_info.has_avr_step_req;
 	u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
 			CONNECTOR_PROP_QSYNC_MODE);
+	u32 avr_step_state = sde_connector_get_property(&sde_conn_state->base,
+			CONNECTOR_PROP_AVR_STEP_STATE);
 
-	if (has_panel_req) {
-		if (!sde_conn->ops.get_avr_step_req) {
-			SDE_ERROR("unable to retrieve required step rate\n");
-			return -EINVAL;
-		}
+	if ((avr_step_state == AVR_STEP_NONE) || !sde_conn->ops.get_avr_step_fps)
+		return 0;
 
-		req_fps = sde_conn->ops.get_avr_step_req(sde_conn->display, nom_fps);
-		/* when qsync is enabled, the step fps *must* be set to the panel requirement */
-		if (qsync_mode && req_fps != step) {
-			SDE_ERROR("invalid avr_step %u, panel requires %u at nominal %u fps\n",
-					step, req_fps, nom_fps);
-			return -EINVAL;
-		}
+	if (!qsync_mode && avr_step_state) {
+		SDE_ERROR("invalid config: avr-step enabled without qsync\n");
+		return -EINVAL;
 	}
 
-	if (!step)
-		return 0;
+	step_fps = sde_conn->ops.get_avr_step_fps(&sde_conn_state->base);
 
 	_sde_encoder_get_qsync_fps_callback(sde_conn_state->base.best_encoder, &min_fps,
 		&sde_conn_state->base);
-	if (!min_fps || !nom_fps || step % nom_fps || step % min_fps || step < nom_fps ||
-			(vtotal * nom_fps) % step) {
+	if (!min_fps || !nom_fps || step_fps % nom_fps || step_fps % min_fps
+			|| step_fps < nom_fps || (vtotal * nom_fps) % step_fps) {
 		SDE_ERROR("invalid avr_step rate! nom:%u min:%u step:%u vtotal:%u\n", nom_fps,
-				min_fps, step, vtotal);
+				min_fps, step_fps, vtotal);
 		return -EINVAL;
 	}
 
@@ -1259,11 +1251,9 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
 		struct sde_connector_state *sde_conn_state)
 {
 	int rc = 0;
-	u32 avr_step;
 	bool qsync_dirty, has_modeset, ept;
 	struct drm_connector_state *conn_state = &sde_conn_state->base;
-	u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
-						CONNECTOR_PROP_QSYNC_MODE);
+	u32 qsync_mode;
 
 	has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc);
 	qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
@@ -1279,9 +1269,9 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
 		return -EINVAL;
 	}
 
-	avr_step = sde_connector_get_property(conn_state, CONNECTOR_PROP_AVR_STEP);
-	if (qsync_dirty || (avr_step != sde_conn->avr_step) || (qsync_mode && has_modeset))
-		rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state, avr_step);
+	qsync_mode = sde_connector_get_property(conn_state, CONNECTOR_PROP_QSYNC_MODE);
+	if (qsync_dirty || (qsync_mode && has_modeset))
+		rc =  _sde_encoder_avr_step_check(sde_conn, sde_conn_state);
 
 	return rc;
 }
@@ -4670,6 +4660,7 @@ void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc)
 	u32 avr_step_fps, min_fps = 0, qsync_mode;
 	u64 timeout_us = 0, ept;
 	struct drm_connector *drm_conn;
+	struct msm_mode_info *info = &sde_enc->mode_info;
 
 	if (!sde_enc->cur_master || !sde_enc->cur_master->connector)
 		return;
@@ -4679,13 +4670,13 @@ void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc)
 	if (!ept)
 		return;
 
-	avr_step_fps = sde_connector_get_avr_step(drm_conn);
 	qsync_mode = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_QSYNC_MODE);
 	if (qsync_mode)
 		_sde_encoder_get_qsync_fps_callback(&sde_enc->base, &min_fps, drm_conn->state);
 	/* use min qsync fps, if feature is enabled; otherwise min default fps */
 	min_fps = min_fps ? min_fps : DEFAULT_MIN_FPS;
 
+	avr_step_fps = info->avr_step_fps;
 	current_ts = ktime_get_ns();
 	/* ept is in ns and avr_step is mulitple of refresh rate */
 	ept_ts = avr_step_fps ? ept - DIV_ROUND_UP(NSEC_PER_SEC, avr_step_fps) + NSEC_PER_MSEC

+ 16 - 5
msm/sde/sde_encoder_phys_vid.c

@@ -373,19 +373,30 @@ static void _sde_encoder_phys_vid_avr_ctrl(struct sde_encoder_phys *phys_enc)
 {
 	struct intf_avr_params avr_params;
 	struct sde_encoder_phys_vid *vid_enc = to_sde_encoder_phys_vid(phys_enc);
-	u32 avr_step_fps = sde_connector_get_avr_step(phys_enc->connector);
+	struct drm_connector *conn = phys_enc->connector;
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(phys_enc->parent);
+	struct msm_mode_info *info = &sde_enc->mode_info;
+	u32 avr_step_state;
+
+	if (!conn || !conn->state)
+		return;
+
+	avr_step_state = sde_connector_get_property(conn->state, CONNECTOR_PROP_AVR_STEP_STATE);
+	if (avr_step_state == AVR_STEP_NONE)
+		return;
 
 	memset(&avr_params, 0, sizeof(avr_params));
 	avr_params.avr_mode = sde_connector_get_qsync_mode(phys_enc->connector);
-	if (avr_step_fps)
+
+	if (info->avr_step_fps && (avr_step_state == AVR_STEP_ENABLE))
 		avr_params.avr_step_lines = mult_frac(phys_enc->cached_mode.vtotal,
-				vid_enc->timing_params.vrefresh, avr_step_fps);
+				vid_enc->timing_params.vrefresh, info->avr_step_fps);
 
 	if (vid_enc->base.hw_intf->ops.avr_ctrl)
 		vid_enc->base.hw_intf->ops.avr_ctrl(vid_enc->base.hw_intf, &avr_params);
 
-	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0,
-			avr_params.avr_mode, avr_params.avr_step_lines, avr_step_fps);
+	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, avr_params.avr_mode,
+			avr_params.avr_step_lines, info->avr_step_fps, avr_step_state);
 }
 
 static void sde_encoder_phys_vid_setup_timing_engine(

+ 1 - 1
msm/sde/sde_kms.c

@@ -1829,7 +1829,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.set_allowed_mode_switch = dsi_conn_set_allowed_mode_switch,
 		.set_dyn_bit_clk = dsi_conn_set_dyn_bit_clk,
 		.get_qsync_min_fps = dsi_conn_get_qsync_min_fps,
-		.get_avr_step_req = dsi_display_get_avr_step_req_fps,
+		.get_avr_step_fps = dsi_conn_get_avr_step_fps,
 		.prepare_commit = dsi_conn_prepare_commit,
 		.set_submode_info = dsi_conn_set_submode_blob_info,
 		.get_num_lm_from_mode = dsi_conn_get_lm_from_mode,