return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
 }
 
+/*
+ * On certain encoders on certain platforms, pipe
+ * scanline register will not work to get the scanline,
+ * since the timings are driven from the PORT or issues
+ * with scanline register updates.
+ * This function will use Framestamp and current
+ * timestamp registers to calculate the scanline.
+ */
+static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct drm_vblank_crtc *vblank =
+               &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)];
+       const struct drm_display_mode *mode = &vblank->hwmode;
+       u32 vblank_start = mode->crtc_vblank_start;
+       u32 vtotal = mode->crtc_vtotal;
+       u32 htotal = mode->crtc_htotal;
+       u32 clock = mode->crtc_clock;
+       u32 scanline, scan_prev_time, scan_curr_time, scan_post_time;
+
+       /*
+        * To avoid the race condition where we might cross into the
+        * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR
+        * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR
+        * during the same frame.
+        */
+       do {
+               /*
+                * This field provides read back of the display
+                * pipe frame time stamp. The time stamp value
+                * is sampled at every start of vertical blank.
+                */
+               scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe));
+
+               /*
+                * The TIMESTAMP_CTR register has the current
+                * time stamp value.
+                */
+               scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR);
+
+               scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe));
+       } while (scan_post_time != scan_prev_time);
+
+       scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time,
+                                       clock), 1000 * htotal);
+       scanline = min(scanline, vtotal - 1);
+       scanline = (scanline + vblank_start) % vtotal;
+
+       return scanline;
+}
+
 /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */
 static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 {
        vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)];
        mode = &vblank->hwmode;
 
+       if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP)
+               return __intel_get_crtc_scanline_from_timestamp(crtc);
+
        vtotal = mode->crtc_vtotal;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                vtotal /= 2;
 
 #define MIPIO_TXESC_CLK_DIV2                   _MMIO(0x160008)
 #define  GLK_TX_ESC_CLK_DIV2_MASK                      0x3FF
 
+/* Gen4+ Timestamp and Pipe Frame time stamp registers */
+#define GEN4_TIMESTAMP         _MMIO(0x2358)
+#define ILK_TIMESTAMP_HI       _MMIO(0x70070)
+#define IVB_TIMESTAMP_CTR      _MMIO(0x44070)
+
+#define _PIPE_FRMTMSTMP_A              0x70048
+#define PIPE_FRMTMSTMP(pipe)           \
+                       _MMIO_PIPE2(pipe, _PIPE_FRMTMSTMP_A)
+
 /* BXT MIPI clock controls */
 #define BXT_MAX_VAR_OUTPUT_KHZ                 39500
 
 
        adjusted_mode->flags = 0;
 
        if (IS_GEN9_LP(dev_priv)) {
+               /* Enable Frame time stamp based scanline reporting */
+               adjusted_mode->private_flags |=
+                       I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
+
                /* Dual link goes to DSI transcoder A. */
                if (intel_dsi->ports == BIT(PORT_C))
                        pipe_config->cpu_transcoder = TRANSCODER_DSI_C;
                                pixel_format_from_register_bits(fmt));
        bpp = pipe_config->pipe_bpp;
 
+       /* Enable Frame time stamo based scanline reporting */
+       adjusted_mode->private_flags |=
+                       I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
+
        /* In terms of pixels */
        adjusted_mode->crtc_hdisplay =
                                I915_READ(BXT_MIPI_TRANS_HACTIVE(port));