ソースを参照

Merge "disp: msm: sde: enable EPT feature for pineapple target"

qctecmdr 2 年 前
コミット
76f59dbdd1

+ 2 - 1
msm/msm_drv.h

@@ -1,5 +1,5 @@
 /*
- * 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.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
@@ -247,6 +247,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
 	CONNECTOR_PROP_SET_PANEL_MODE,
 	CONNECTOR_PROP_AVR_STEP,
+	CONNECTOR_PROP_EPT,
 	CONNECTOR_PROP_CACHE_STATE,
 	CONNECTOR_PROP_DSC_MODE,
 	CONNECTOR_PROP_WB_USAGE_TYPE,

+ 5 - 1
msm/sde/sde_connector.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.
  */
 
@@ -3175,6 +3175,10 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 					"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,

+ 58 - 3
msm/sde/sde_encoder.c

@@ -1241,7 +1241,7 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
 {
 	int rc = 0;
 	u32 avr_step;
-	bool qsync_dirty, has_modeset;
+	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);
@@ -1249,9 +1249,12 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
 	has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc);
 	qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
 			&sde_conn_state->property_state, CONNECTOR_PROP_QSYNC_MODE);
+	ept = msm_property_is_dirty(&sde_conn->property_info,
+				&sde_conn_state->property_state, CONNECTOR_PROP_EPT);
 
-	if (has_modeset && qsync_dirty && (msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) ||
-				msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
+	if (has_modeset && (qsync_dirty || ept) &&
+		(msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) ||
+			msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
 		SDE_ERROR("invalid qsync update during modeset priv flag:%x\n",
 				sde_conn_state->msm_mode.private_flags);
 		return -EINVAL;
@@ -4642,6 +4645,56 @@ static int _sde_encoder_prepare_for_kickoff_processing(struct drm_encoder *drm_e
 	return ret;
 }
 
+void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc)
+{
+	ktime_t current_ts, ept_ts;
+	u32 avr_step_fps, min_fps = 0, qsync_mode;
+	u64 timeout_us = 0, ept;
+	struct drm_connector *drm_conn;
+
+	if (!sde_enc->cur_master || !sde_enc->cur_master->connector)
+		return;
+
+	drm_conn = sde_enc->cur_master->connector;
+	ept = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_EPT);
+	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;
+
+	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
+				: ept - NSEC_PER_MSEC;
+
+	/* ept time already elapsed */
+	if (ept_ts <= current_ts) {
+		SDE_DEBUG("enc:%d, ept elapsed; ept:%llu, ept_ts:%llu, current_ts:%llu\n",
+				DRMID(&sde_enc->base), ept, ept_ts, current_ts);
+		return;
+	}
+
+	timeout_us = DIV_ROUND_UP((ept_ts - current_ts), 1000);
+	/* validate timeout is not beyond the min fps */
+	if (timeout_us > DIV_ROUND_UP(USEC_PER_SEC, min_fps)) {
+		SDE_ERROR("enc:%d, invalid timeout_us:%llu; ept:%llu, ept_ts:%llu, cur_ts:%llu\n",
+				DRMID(&sde_enc->base), timeout_us, ept, ept_ts, current_ts);
+		return;
+	}
+
+	SDE_ATRACE_BEGIN("schedule_timeout");
+	usleep_range(timeout_us, timeout_us + 10);
+	SDE_ATRACE_END("schedule_timeout");
+
+	SDE_EVT32(DRMID(&sde_enc->base), qsync_mode, avr_step_fps, min_fps, ktime_to_us(current_ts),
+					ktime_to_us(ept_ts), timeout_us);
+}
+
 int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
 		struct sde_encoder_kickoff_params *params)
 {
@@ -4715,6 +4768,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
 		goto end;
 	}
 
+	_sde_encoder_delay_kickoff_processing(sde_enc);
+
 	ret = _sde_encoder_prepare_for_kickoff_processing(drm_enc, params, sde_enc, sde_kms,
 			needs_hw_reset, is_cmd_mode);
 

+ 2 - 0
msm/sde/sde_encoder.h

@@ -59,6 +59,8 @@
 		((!(phys_enc) || ((idx) < 0) || ((idx) >= INTR_IDX_MAX)) ? \
 		0 : ((phys_enc)->irq[(idx)].irq_idx >= 0))
 
+#define DEFAULT_MIN_FPS	10
+
 /**
  * Encoder functions and data types
  * @intfs:	Interfaces this encoder is using, INTF_MODE_NONE if unused

+ 6 - 1
msm/sde/sde_encoder_phys_cmd.c

@@ -1339,7 +1339,12 @@ static void sde_encoder_phys_cmd_tearcheck_config(
 	 * disable sde hw generated TE signal, since hw TE will arrive first.
 	 * Only caveat is if due to error, we hit wrap-around.
 	 */
-	tc_cfg.sync_cfg_height = 0xFFF0;
+	if (phys_enc->hw_intf->ops.is_te_32bit_supported
+			&& phys_enc->hw_intf->ops.is_te_32bit_supported(phys_enc->hw_intf))
+		tc_cfg.sync_cfg_height = 0xFFFFFFF0;
+	else
+		tc_cfg.sync_cfg_height = 0xFFF0;
+
 	tc_cfg.vsync_init_val = mode->vdisplay;
 	tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc);
 	tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE;

+ 1 - 0
msm/sde/sde_hw_catalog.c

@@ -5395,6 +5395,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
 		set_bit(SDE_FEATURE_SYS_CACHE_NSE, sde_cfg->features);
 		set_bit(SDE_FEATURE_SYS_CACHE_STALING, sde_cfg->features);
 		set_bit(SDE_FEATURE_WB_ROTATION, sde_cfg->features);
+		set_bit(SDE_FEATURE_EPT, sde_cfg->features);
 		sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH;
 		sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2;
 		sde_cfg->perf.min_prefill_lines = 40;

+ 2 - 0
msm/sde/sde_hw_catalog.h

@@ -767,6 +767,7 @@ enum {
  * @SDE_FEATURE_SUI_BLENDSTAGE SecureUI Blendstage supported
  * @SDE_FEATURE_SUI_NS_ALLOWED SecureUI allowed to access non-secure context banks
  * @SDE_FEATURE_TRUSTED_VM     Trusted VM supported
+ * @SDE_FEATURE_EPT            Expected present time supported
  * @SDE_FEATURE_UBWC_STATS     UBWC statistics supported
  * @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
  * @SDE_FEATURE_CTL_DONE       Support for CTL DONE irq
@@ -813,6 +814,7 @@ enum sde_mdss_features {
 	SDE_FEATURE_SUI_BLENDSTAGE,
 	SDE_FEATURE_SUI_NS_ALLOWED,
 	SDE_FEATURE_TRUSTED_VM,
+	SDE_FEATURE_EPT,
 	SDE_FEATURE_UBWC_STATS,
 	SDE_FEATURE_VBIF_CLK_SPLIT,
 	SDE_FEATURE_CTL_DONE,

+ 7 - 1
msm/sde/sde_hw_intf.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) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -1022,6 +1022,11 @@ static void sde_hw_intf_enable_wide_bus(struct sde_hw_intf *intf,
 	SDE_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
 }
 
+static bool sde_hw_intf_is_te_32bit_supported(struct sde_hw_intf *intf)
+{
+	return (intf->cap->features & BIT(SDE_INTF_TE_32BIT));
+}
+
 static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
 		unsigned long cap)
 {
@@ -1038,6 +1043,7 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
 	ops->avr_ctrl = sde_hw_intf_avr_ctrl;
 	ops->enable_compressed_input = sde_hw_intf_enable_compressed_input;
 	ops->enable_wide_bus = sde_hw_intf_enable_wide_bus;
+	ops->is_te_32bit_supported = sde_hw_intf_is_te_32bit_supported;
 
 	if (cap & BIT(SDE_INTF_STATUS))
 		ops->get_status = sde_hw_intf_v1_get_status;

+ 6 - 1
msm/sde/sde_hw_intf.h

@@ -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) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -267,6 +267,11 @@ struct sde_hw_intf_ops {
 	 */
 	void (*override_tear_rd_ptr_val)(struct sde_hw_intf *intf,
 			u32 adjusted_linecnt);
+
+	/**
+	 * Check if intf supports 32-bit registers for TE
+	 */
+	bool (*is_te_32bit_supported)(struct sde_hw_intf *intf);
 };
 
 struct sde_hw_intf {