diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 167b35a..fbfe942 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2136,6 +2136,10 @@ enum wm_fifo_type {
 	WM_USE_OFFSET = 0,
 	WM_USE_ENTRY_COUNT,
 };
+enum wm_calc_method {
+	WM_USE_NORMAL = 0,
+	WM_USE_LARGE_BUFFER,
+};
 
 struct intel_watermark_params {
 	unsigned long fifo_size;
@@ -2224,10 +2228,11 @@ static struct intel_watermark_params i830_wm_info = {
 
 /**
  * intel_calculate_wm - calculate watermark level
- * @clock_in_khz: pixel clock
  * @wm: chip FIFO params
+ * @crtc_mode: the display mode for the crtc
  * @pixel_size: display pixel size
  * @latency_ns: memory latency for the platform
+ * @calc_method: the used method to calculate the watermark
  *
  * Calculate the watermark level (the level at which the display plane will
  * start fetching from memory again).  Each chip has a different display
@@ -2239,23 +2244,50 @@ static struct intel_watermark_params i830_wm_info = {
  * fetching FIFO line sized based chunks from memory until the FIFO fills
  * past the watermark point.  If the FIFO drains completely, a FIFO underrun
  * will occur, and a display engine hang could result.
+ *
+ * calc_method: This is to indicate which method is used to calculate the
+ * watermark.
+ * WM_USE_NORMAL is the normal calculation(called as small buffer).
+ * WM_USE_LARGE_BUFFER is the SR calculatiion (called as the large buffer).
+ *    The normal calculation is:
+ *     watermark = dotclock * bytes per pixel * latency
+ *   where latency is platform & configuration dependent (we assume pessimal
+ *   values here).
+ *
+ *   The SR calculation is:
+ *     watermark = (trunc(latency/line time)+1) * surface width *
+ *       bytes per pixel
+ *   where
+ *     line time = htotal / dotclock
+ *
  */
-static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
-					struct intel_watermark_params *wm,
+static unsigned long intel_calculate_wm(struct intel_watermark_params *wm,
+					struct drm_display_mode *crtc_mode,
 					int pixel_size,
-					unsigned long latency_ns)
+					unsigned long latency_ns,
+					enum wm_calc_method calc_method)
 {
 	long entries_required, wm_size;
-	int sr_entries;
+	int sr_entries, hdisplay;
+	unsigned long line_time_us;
 
+	hdisplay = crtc_mode->hdisplay;
 	/*
 	 * Note: we need to make sure we don't overflow for various clock &
 	 * latency values.
 	 * clocks go from a few thousand to several hundred thousand.
 	 * latency is usually a few thousand
 	 */
-	entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
-		1000;
+	if (calc_method == WM_USE_LARGE_BUFFER) {
+		/* calculate the line time. The unit is us */
+		line_time_us = (crtc_mode->htotal * 1000) / crtc_mode->clock;
+
+		/* Use ns/us then divide to preserve precision */
+		entries_required = (((latency_ns / line_time_us) + 1000) /
+			1000) * pixel_size * hdisplay;
+	} else
+		entries_required = ((crtc_mode->clock / 1000) * pixel_size *
+			latency_ns) / 1000;
 	/* Round up to the next cacheline boundary */
 	sr_entries = DIV_ROUND_UP(entries_required, wm->cacheline_size);
 
@@ -2458,14 +2490,16 @@ static void pineview_update_wm(struct drm_device *dev,
 	 * We don't touch the watermark for display C.
 	 */
 	if (crtc_modea->clock)
-		planea_wm = intel_calculate_wm(crtc_modea->clock,
-				&planea_params, pixel_size, latency_ns);
+		planea_wm = intel_calculate_wm(&planea_params, crtc_modea,
+						pixel_size, latency_ns,
+						WM_USE_NORMAL);
 	else
 		planea_wm = 15;
 
 	if (crtc_modeb->clock)
-		planeb_wm = intel_calculate_wm(crtc_modeb->clock,
-				&planeb_params, pixel_size, latency_ns);
+		planeb_wm = intel_calculate_wm(&planeb_params, crtc_modeb,
+						pixel_size, latency_ns,
+						WM_USE_NORMAL);
 	else
 		planeb_wm = 15;
 
@@ -2490,14 +2524,18 @@ static void pineview_update_wm(struct drm_device *dev,
 	 */
 
 	if (!crtc_modea->clock || !crtc_modeb->clock) {
+		struct drm_display_mode *crtc_mode;
 		if (crtc_modea->clock) {
 			sr_clock = crtc_modea->clock;
+			crtc_mode = crtc_modea;
 		} else {
 			sr_clock = crtc_modeb->clock;
+			crtc_mode = crtc_modeb;
 		}
 		/* Display SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_wm,
-				pixel_size, latency->display_sr);
+		wm = intel_calculate_wm(&pineview_display_wm, crtc_mode,
+				pixel_size, latency->display_sr,
+				WM_USE_NORMAL);
 		reg = I915_READ(DSPFW1);
 		reg &= 0x7fffff;
 		reg |= wm << 23;
@@ -2505,24 +2543,28 @@ static void pineview_update_wm(struct drm_device *dev,
 		DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
 
 		/* cursor SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_wm,
-				pixel_size, latency->cursor_sr);
+		wm = intel_calculate_wm(&pineview_cursor_wm, crtc_mode,
+				pixel_size, latency->cursor_sr,
+				WM_USE_NORMAL);
 		reg = I915_READ(DSPFW3);
 		reg &= ~(0x3f << 24);
 		reg |= (wm & 0x3f) << 24;
 		I915_WRITE(DSPFW3, reg);
 
 		/* Display HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_hplloff_wm,
-			pixel_size, latency->display_hpll_disable);
+		wm = intel_calculate_wm(&pineview_display_hplloff_wm,
+					crtc_mode, pixel_size,
+					latency->display_hpll_disable,
+					WM_USE_NORMAL);
 		reg = I915_READ(DSPFW3);
 		reg &= 0xfffffe00;
 		reg |= wm & 0x1ff;
 		I915_WRITE(DSPFW3, reg);
 
 		/* cursor HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_hplloff_wm,
-				pixel_size, latency->cursor_hpll_disable);
+		wm = intel_calculate_wm(&pineview_cursor_hplloff_wm, crtc_mode,
+				pixel_size, latency->cursor_hpll_disable,
+				WM_USE_NORMAL);
 		reg = I915_READ(DSPFW3);
 		reg &= ~(0x3f << 16);
 		reg |= (wm & 0x3f) << 16;
@@ -2699,14 +2741,16 @@ static void i9xx_update_wm(struct drm_device *dev,
 	planeb_params.fifo_size = dev_priv->display.get_fifo_size(dev, 1);
 
 	if (crtc_modea->clock)
-		planea_wm = intel_calculate_wm(crtc_modea->clock,
-				&planea_params, pixel_size, latency_ns);
+		planea_wm = intel_calculate_wm(&planea_params, crtc_modea,
+						pixel_size, latency_ns,
+						WM_USE_NORMAL);
 	else
 		planea_wm = 8;
 
 	if (crtc_modeb->clock)
-		planeb_wm = intel_calculate_wm(crtc_modeb->clock,
-				&planeb_params, pixel_size, latency_ns);
+		planeb_wm = intel_calculate_wm(&planeb_params, crtc_modeb,
+						pixel_size, latency_ns,
+						WM_USE_NORMAL);
 	else
 		planeb_wm = 8;
 	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
@@ -2771,8 +2815,9 @@ static void i830_update_wm(struct drm_device *dev,
 
 	i830_wm_info.fifo_size = dev_priv->display.get_fifo_size(dev, 0);
 
-	planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
-				       pixel_size, latency_ns);
+	planea_wm = intel_calculate_wm(&i830_wm_info, crtc_modea,
+				       pixel_size, latency_ns,
+					WM_USE_NORMAL);
 	fwater_lo |= (3<<8) | planea_wm;
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
