@@ -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.
@@ -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;
};