aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorU. Artie Eoff <ullysses.a.eoff@intel.com>2014-09-29 18:49:32 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-10-06 10:47:24 -0400
commit673e7bbdb3920b62cfc6c710bea626b0a9b0f43a (patch)
tree374688115b4c6f01df23a1a8c08841b0e8cdd3e9 /drivers/gpu
parentebb69c95175609990af708ec90c46530f5a2c819 (diff)
drm/i915: intel_backlight scale() math WA
Improper truncated integer division in the scale() function causes actual_brightness != brightness. This (partial) work-around should be sufficient for a majority of use-cases, but it is by no means a complete solution. TODO: Determine how best to scale "user" values to "hw" values, and vice-versa, when the ranges are of different sizes. That would be a buggy scenario even with this work-around. The issue was introduced in the following (v3.17-rc1) commit: 6dda730 drm/i915: respect the VBT minimum backlight brightness Note that for easier backporting this commit adds a duplicated macro. A follow-up cleanup patch rectifies this for 3.18+ v2: (thanks to Chris Wilson) clarify commit message, use rounded division macro v3: -DIV_ROUND_CLOSEST() fails to build with CONFIG_X86_32=y. (Jani) -Use DIV_ROUND_CLOSEST_ULL() instead. (Damien) -v1 and v2 originally authored by Joe Konno. Signed-off-by: U. Artie Eoff <ullysses.a.eoff@intel.com> Cc: stable@vger.kernel.org Reviewed-By: Joe Konno <joe.konno@intel.com> [danvet: Add backporting note.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 18784470a760..97ff71f40dd3 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -398,6 +398,9 @@ intel_panel_detect(struct drm_device *dev)
398 } 398 }
399} 399}
400 400
401#define DIV_ROUND_CLOSEST_ULL(ll, d) \
402({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
403
401/** 404/**
402 * scale - scale values from one range to another 405 * scale - scale values from one range to another
403 * 406 *
@@ -419,9 +422,8 @@ static uint32_t scale(uint32_t source_val,
419 source_val = clamp(source_val, source_min, source_max); 422 source_val = clamp(source_val, source_min, source_max);
420 423
421 /* avoid overflows */ 424 /* avoid overflows */
422 target_val = (uint64_t)(source_val - source_min) * 425 target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) *
423 (target_max - target_min); 426 (target_max - target_min), source_max - source_min);
424 do_div(target_val, source_max - source_min);
425 target_val += target_min; 427 target_val += target_min;
426 428
427 return target_val; 429 return target_val;