summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorJon Mayo <jmayo@nvidia.com>2012-03-27 13:55:31 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-04-06 04:17:24 -0700
commite6839d988cdb182908636d611220abaf2f870f2b (patch)
treea9a2360829051910f7410d6f12a085901912cbf2 /drivers/video
parent4f57f3899e460628f97e106318327f5331e7463a (diff)
video: tegra: dc: avoid overflow in bw calculation
Change to using kbytes/sec to avoid overflowing 32-bit integer in bandwidth calculation. Changing efficiency adjustment to ~35%. Bug 958016 Change-Id: Ia8bdf79e4b3e4bc65517db18d9f351a5f840805e Signed-off-by: Jon Mayo <jmayo@nvidia.com> Reviewed-on: http://git-master/r/92658 Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/tegra/dc/dc.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 113e64c59563..20f80f940650 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -828,9 +828,9 @@ static void tegra_dc_set_latency_allowance(struct tegra_dc *dc,
if (w->idx == 1 && win_use_v_filter(w))
bw /= 2;
- /* our bandwidth is in bytes/sec, but LA takes MBps.
- * round up bandwidth to 1MBps */
- bw = bw / 1000000 + 1;
+ /* our bandwidth is in kbytes/sec, but LA takes MBps.
+ * round up bandwidth to next 1MBps */
+ bw = bw / 1000 + 1;
#ifdef CONFIG_TEGRA_SILICON_PLATFORM
tegra_set_latency_allowance(la_id_tab[dc->ndev->id][w->idx], bw);
@@ -914,10 +914,12 @@ static unsigned long tegra_dc_find_max_bandwidth(struct tegra_dc_win *wins[],
* pixel_clock * win_bpp * (use_v_filter ? 2 : 1)) * H_scale_factor *
* (windows_tiling ? 2 : 1)
*
- *
* note:
* (*) We use 2 tap V filter, so need double BW if use V filter
* (*) Tiling mode on T30 and DDR3 requires double BW
+ *
+ * return:
+ * bandwidth in kBps
*/
static unsigned long tegra_dc_calc_win_bandwidth(struct tegra_dc *dc,
struct tegra_dc_win *w)
@@ -941,24 +943,16 @@ static unsigned long tegra_dc_calc_win_bandwidth(struct tegra_dc *dc,
* is of the luma plane's size only. */
bpp = tegra_dc_is_yuv_planar(w->fmt) ?
2 * tegra_dc_fmt_bpp(w->fmt) : tegra_dc_fmt_bpp(w->fmt);
- /* perform calculations with most significant bits of pixel clock
- * to prevent overflow of long. */
- ret = (unsigned long)(dc->mode.pclk >> 16) *
- bpp / 8 *
- (win_use_v_filter(w) ? 2 : 1) * dfixed_trunc(w->w) / w->out_w *
+ ret = dc->mode.pclk / 1000UL * bpp / 8 * (win_use_v_filter(w) ? 2 : 1)
+ * dfixed_trunc(w->w) / w->out_w *
(WIN_IS_TILED(w) ? tiled_windows_bw_multiplier : 1);
+ /*
+ * Assuming ~35% efficiency: i.e. if we calculate we need 70MBps, we
+ * will request 200MBps from EMC.
+ */
+ ret = ret * 29 / 10;
-/*
- * Assuming 48% efficiency: i.e. if we calculate we need 70MBps, we
- * will request 147MBps from EMC.
- */
- ret = ret * 2 + ret / 10;
-
- /* if overflowed */
- if (ret > (1UL << 31))
- return ULONG_MAX;
-
- return ret << 16; /* restore the scaling we did above */
+ return ret;
}
static unsigned long tegra_dc_get_bandwidth(
@@ -972,8 +966,10 @@ static unsigned long tegra_dc_get_bandwidth(
* bandwidths */
for (i = 0; i < n; i++) {
struct tegra_dc_win *w = windows[i];
+
if (w)
- w->new_bandwidth = tegra_dc_calc_win_bandwidth(w->dc, w);
+ w->new_bandwidth =
+ tegra_dc_calc_win_bandwidth(w->dc, w);
}
return tegra_dc_find_max_bandwidth(windows, n);
@@ -1005,6 +1001,7 @@ static void tegra_dc_program_bandwidth(struct tegra_dc *dc)
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_win *w = &dc->windows[i];
+
if (w->bandwidth != w->new_bandwidth && w->new_bandwidth != 0)
tegra_dc_set_latency_allowance(dc, w);
}
@@ -1022,7 +1019,10 @@ static int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n)
/* calculate the new rate based on this POST */
new_rate = tegra_dc_get_bandwidth(windows, n);
- new_rate = EMC_BW_TO_FREQ(new_rate);
+ if (WARN_ONCE(new_rate > (ULONG_MAX / 1000), "bandwidth maxed out\n"))
+ new_rate = ULONG_MAX;
+ else
+ new_rate = EMC_BW_TO_FREQ(new_rate * 1000);
if (tegra_dc_has_multiple_dc())
new_rate = ULONG_MAX;