[Intel-gfx] [PATCH v2 5/9] drm/i915: Add a new method to calculate the required fifo entry size
yakui.zhao at intel.com
yakui.zhao at intel.com
Wed Jan 20 10:41:14 CET 2010
From: Zhao Yakui <yakui.zhao at intel.com>
According to the spec two methods are used to calculate required entry size.
One is called as small buffer, which is already used in the function of
intel_calculate_wm.
The second is called as large buffer, which uses the following formula:
>required_size = (trunc(latency/line time)+1) * surface width *
bytes per pixel
where
line time = htotal / dotclock
Add the second method defined in spec to calculate the required entry size.
And it is also put into the function of intel_calculate_wm. They are selected
by adding a new argument for intel_calculate_wm.
Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 95 +++++++++++++++++++++++++---------
1 files changed, 70 insertions(+), 25 deletions(-)
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);
--
1.5.4.5
More information about the Intel-gfx
mailing list