[v7,22/23] drm/i915/icl: Ensure all cmd/data disptached to panel

Submitted by Jani Nikula on Oct. 15, 2018, 2:28 p.m.

Details

Message ID 97c565cd5ed5cd1b8c2fb8cc48d412c622605cc2.1539613303.git.jani.nikula@intel.com
State New
Headers show
Series "drm/i915/icl: dsi enabling" ( rev: 2 1 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Jani Nikula Oct. 15, 2018, 2:28 p.m.
From: Madhav Chauhan <madhav.chauhan@intel.com>

As per BSPEC, driver needs to ensure that all of commands/data
has been dispatched to panel before the transcoder is enabled.
This patch implement those steps i.e. sending NOP DCS command,
wait for header/payload credit to be released etc.

Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/icl_dsi.c | 53 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
index 5fe024dfbdb0..90188ba8a4dc 100644
--- a/drivers/gpu/drm/i915/icl_dsi.c
+++ b/drivers/gpu/drm/i915/icl_dsi.c
@@ -28,9 +28,8 @@ 
 #include <drm/drm_mipi_dsi.h>
 #include "intel_dsi.h"
 
-static void __attribute__((unused)) wait_for_dsi_hdr_credit_release(
-						struct intel_dsi *intel_dsi,
-						enum transcoder dsi_trans)
+static void wait_for_dsi_hdr_credit_release(struct intel_dsi *intel_dsi,
+					    enum transcoder dsi_trans)
 {
 	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
 
@@ -40,8 +39,7 @@  static void __attribute__((unused)) wait_for_dsi_hdr_credit_release(
 		DRM_ERROR("DSI header credits not released\n");
 }
 
-static void __attribute__((unused)) wait_for_dsi_payload_credit_release(
-						struct intel_dsi *intel_dsi,
+static void wait_for_dsi_payload_credit_release(struct intel_dsi *intel_dsi,
 						enum transcoder dsi_trans)
 {
 	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
@@ -60,6 +58,48 @@  static enum transcoder dsi_port_to_transcoder(enum port port)
 		return TRANSCODER_DSI_1;
 }
 
+static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	struct mipi_dsi_device *dsi;
+	enum port port;
+	enum transcoder dsi_trans;
+	int ret;
+
+	/* wait for header/payload credits to be released */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		dsi_trans = dsi_port_to_transcoder(port);
+		wait_for_dsi_hdr_credit_release(intel_dsi, dsi_trans);
+		wait_for_dsi_payload_credit_release(intel_dsi, dsi_trans);
+	}
+
+	/* send nop DCS command */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		dsi = intel_dsi->dsi_hosts[port]->device;
+		dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+		dsi->channel = 0;
+		ret = mipi_dsi_dcs_nop(dsi);
+		if (ret < 0)
+			DRM_ERROR("error sending DCS NOP command\n");
+	}
+
+	/* wait for header credits to be released */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		dsi_trans = dsi_port_to_transcoder(port);
+		wait_for_dsi_hdr_credit_release(intel_dsi, dsi_trans);
+	}
+
+	/* wait for LP TX in progress bit to be cleared */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		dsi_trans = dsi_port_to_transcoder(port);
+		if (wait_for_us(!(I915_READ(DSI_LP_MSG(dsi_trans)) &
+				  LPTX_IN_PROGRESS),
+				  20))
+			DRM_ERROR("LPTX bit not cleared\n");
+	}
+}
+
 static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -690,6 +730,9 @@  static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
+
+	/* ensure all panel commands dispatched before enabling transcoder */
+	wait_for_cmds_dispatched_to_panel(encoder);
 }
 
 static void __attribute__((unused))