diff mbox

[14/14] drm/i915: send one frame after enabling mipi cmd mode

Message ID 1443563651-11596-15-git-send-email-gaurav.k.singh@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Gaurav K Singh Sept. 29, 2015, 9:54 p.m. UTC
If MIPI is operated in command mode, and after display reset. if
not even one frame is sent after enabling the pipe and then if it
is disabled, pipe is getting stuck. This patch will fix this issue
by sending one frame after enabling the pipe.

Ideally,there should not be a case where there is mode set and no frames
are sent.

Signed-off-by: Gaurav K Singh <gaurav.k.singh@intel.com>
Signed-off-by: Yogesh Mohan Marimuthu <yogesh.mohan.marimuthu@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   47 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    6 +++++
 2 files changed, 53 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5911a333..37757bb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -44,6 +44,7 @@ 
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 #include <linux/dma_remapping.h>
+#include "intel_dsi.h"
 
 /* Primary plane formats for gen <= 3 */
 static const uint32_t i8xx_primary_formats[] = {
@@ -6016,6 +6017,7 @@  static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
+	struct intel_dsi *intel_dsi;
 	int pipe = intel_crtc->pipe;
 	bool is_dsi;
 
@@ -6071,6 +6073,25 @@  static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->type != INTEL_OUTPUT_DSI)
+			continue;
+
+		intel_dsi = enc_to_intel_dsi(&encoder->base);
+		if (intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE) {
+			/*
+			 * save the current pipe counter. During disable use
+			 * this variable to check if at least one frame has
+			 * been sent. If no frame is sent and MIPI is disabled
+			 * in command mode, then pipe gets stuck.
+			 */
+			intel_crtc->hw_frm_cnt_at_enable =
+						I915_READ(PIPEFRAME(pipe));
+		}
+		break;
+	}
+
 }
 
 static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
@@ -6148,10 +6169,36 @@  static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
+	struct intel_dsi *intel_dsi;
 	int pipe = intel_crtc->pipe;
 	bool all_pipe_disabled;
 	u32 val;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->type != INTEL_OUTPUT_DSI)
+			continue;
+
+		intel_dsi = enc_to_intel_dsi(&encoder->base);
+		if ((intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE) &&
+				(intel_crtc->hw_frm_cnt_at_enable ==
+						I915_READ(PIPEFRAME(pipe)))) {
+
+			intel_dsi_update_panel_fb(encoder);
+
+			/*
+			 * wait for ~2 frames for TE interrupt and sending one
+			 * frame.
+			 */
+			msleep(40);
+
+			if (intel_crtc->hw_frm_cnt_at_enable ==
+						I915_READ(PIPEFRAME(pipe)))
+				DRM_ERROR("Pipe is stuck for DSI cmd mode.");
+		}
+
+		break;
+	}
+
 	/*
 	 * On gen2 planes are double buffered but the pipe isn't, so we must
 	 * wait for planes to fully turn off before disabling the pipe.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 58fcd7d..9013f93 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -576,6 +576,12 @@  struct intel_crtc {
 	/* scalers available on this crtc */
 	int num_scalers;
 
+	/*
+	 * save the frame counter at enable sequence to make sure one frame has
+	 * been sent before disable sequence.
+	 */
+	u32 hw_frm_cnt_at_enable;
+
 	struct vlv_wm_state wm_state;
 };