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

disp: msm: sde: allow qsync support along with VRR

Allow Qsync and VRR features to be supported independently
by display driver. Restrict the feature availability in
same composition cycle.

Change-Id: I696eb72a2b4f9451e142ffdc5acccc8987c36b6d
Signed-off-by: Kalyan Thota <[email protected]>
Signed-off-by: Jayaprakash <[email protected]>
Jayaprakash 5 жил өмнө
parent
commit
ad40a300a1

+ 8 - 7
msm/dsi/dsi_panel.c

@@ -3257,13 +3257,14 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
 	if (rc)
 		DSI_ERR("failed to parse dfps configuration, rc=%d\n", rc);
 
-	if (!(panel->dfps_caps.dfps_support)) {
-		/* qsync and dfps are mutually exclusive features */
-		rc = dsi_panel_parse_qsync_caps(panel, of_node);
-		if (rc)
-			DSI_DEBUG("failed to parse qsync features, rc=%d\n",
-					rc);
-	}
+	rc = dsi_panel_parse_qsync_caps(panel, of_node);
+	if (rc)
+		DSI_DEBUG("failed to parse qsync features, rc=%d\n", rc);
+
+	/* allow qsync support only if DFPS is with VFP approach */
+	if ((panel->dfps_caps.dfps_support) &&
+	    !(panel->dfps_caps.type == DSI_DFPS_IMMEDIATE_VFP))
+		panel->qsync_min_fps = 0;
 
 	rc = dsi_panel_parse_dyn_clk_caps(panel);
 	if (rc)

+ 37 - 6
msm/sde/sde_connector.c

@@ -621,17 +621,24 @@ void sde_connector_set_colorspace(struct sde_connector *c_conn)
 
 void sde_connector_set_qsync_params(struct drm_connector *connector)
 {
-	struct sde_connector *c_conn = to_sde_connector(connector);
-	u32 qsync_propval;
+	struct sde_connector *c_conn;
+	struct sde_connector_state *c_state;
+	u32 qsync_propval = 0;
+	bool prop_dirty;
 
 	if (!connector)
 		return;
 
+	c_conn = to_sde_connector(connector);
+	c_state = to_sde_connector_state(connector->state);
 	c_conn->qsync_updated = false;
-	qsync_propval = sde_connector_get_property(c_conn->base.state,
-			CONNECTOR_PROP_QSYNC_MODE);
 
-	if (qsync_propval != c_conn->qsync_mode) {
+	prop_dirty = msm_property_is_dirty(&c_conn->property_info,
+					&c_state->property_state,
+					CONNECTOR_PROP_QSYNC_MODE);
+	if (prop_dirty) {
+		qsync_propval = sde_connector_get_property(c_conn->base.state,
+						CONNECTOR_PROP_QSYNC_MODE);
 		SDE_DEBUG("updated qsync mode %d -> %d\n", c_conn->qsync_mode,
 				qsync_propval);
 		c_conn->qsync_updated = true;
@@ -1376,6 +1383,10 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
 		if (rc)
 			SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
 		break;
+	case CONNECTOR_PROP_QSYNC_MODE:
+		msm_property_set_dirty(&c_conn->property_info,
+				&c_state->property_state, idx);
+		break;
 	default:
 		break;
 	}
@@ -2027,13 +2038,33 @@ static int sde_connector_atomic_check(struct drm_connector *connector,
 		struct drm_connector_state *new_conn_state)
 {
 	struct sde_connector *c_conn;
+	struct sde_connector_state *c_state;
+	bool qsync_dirty = false, has_modeset = false;
 
 	if (!connector) {
 		SDE_ERROR("invalid connector\n");
-		return 0;
+		return -EINVAL;
+	}
+
+	if (!new_conn_state) {
+		SDE_ERROR("invalid connector state\n");
+		return -EINVAL;
 	}
 
 	c_conn = to_sde_connector(connector);
+	c_state = to_sde_connector_state(new_conn_state);
+
+	has_modeset = sde_crtc_atomic_check_has_modeset(new_conn_state->state,
+						new_conn_state->crtc);
+	qsync_dirty = msm_property_is_dirty(&c_conn->property_info,
+					&c_state->property_state,
+					CONNECTOR_PROP_QSYNC_MODE);
+
+	SDE_DEBUG("has_modeset %d qsync_dirty %d\n", has_modeset, qsync_dirty);
+	if (has_modeset && qsync_dirty) {
+		SDE_ERROR("invalid qsync update during modeset\n");
+		return -EINVAL;
+	}
 
 	if (c_conn->ops.atomic_check)
 		return c_conn->ops.atomic_check(connector,

+ 19 - 0
msm/sde/sde_crtc.h

@@ -714,6 +714,25 @@ static inline int sde_crtc_get_secure_level(struct drm_crtc *crtc,
 			CRTC_PROP_SECURITY_LEVEL);
 }
 
+/** sde_crtc_atomic_check_has_modeset - checks if the new_crtc_state in the
+ *	drm_atomic_state has a modeset
+ * @state : pointer to drm_atomic_state
+ * @crtc : Pointer to drm crtc structure
+ * Returns true if crtc has modeset
+ */
+static inline bool sde_crtc_atomic_check_has_modeset(
+	struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+	struct drm_crtc_state *crtc_state;
+
+	if (!state || !crtc)
+		return false;
+
+	crtc_state = drm_atomic_get_new_crtc_state(state,
+					crtc);
+	return (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state));
+}
+
 /**
  * sde_crtc_get_secure_transition - determines the operations to be
  * performed before transitioning to secure state

+ 1 - 1
msm/sde/sde_encoder_phys_vid.c

@@ -332,7 +332,7 @@ static void _sde_encoder_phys_vid_setup_avr(
 			return;
 		}
 
-		if (qsync_min_fps >= default_fps) {
+		if (qsync_min_fps > default_fps) {
 			SDE_ERROR_VIDENC(vid_enc,
 				"qsync fps %d must be less than default %d\n",
 				qsync_min_fps, default_fps);

+ 5 - 2
msm/sde/sde_hw_intf.c

@@ -129,7 +129,7 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx,
 	u32 min_fps, default_fps, diff_fps;
 	u32 vsync_period_slow;
 	u32 avr_vtotal;
-	u32 add_porches;
+	u32 add_porches = 0;
 
 	if (!ctx || !params || !avr_params) {
 		SDE_ERROR("invalid input parameter(s)\n");
@@ -146,7 +146,10 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx,
 	vsync_period = params->vsync_pulse_width +
 			params->v_back_porch + params->height +
 			params->v_front_porch;
-	add_porches = mult_frac(vsync_period, diff_fps, min_fps);
+
+	if (diff_fps)
+		add_porches = mult_frac(vsync_period, diff_fps, min_fps);
+
 	vsync_period_slow = vsync_period + add_porches;
 	avr_vtotal = vsync_period_slow * hsync_period;