[Intel-gfx] [PATCH] drm/i915: Adaptive backlight support
Daniel Vetter
daniel at ffwll.ch
Thu Jun 21 11:34:02 CEST 2012
On Wed, Jun 20, 2012 at 03:12:35PM -0700, Stéphane Marchesin wrote:
> This is an initial implementation of i915 adaptive backlight support.
> The intended use for the adaptive backlight is to generate interrupts
> whenever the luminance of the screen changes by some thresholds. The
> main caveat with that implementation is that those additional
> interrupts will wake up the CPU and consume more power. Instead, we
> hook into the vblank handler and handle it from there. This makes the
> implementation a little less intuitive but a lot more efficient.
> We also need to compute the gamma correction from the interrupt
> handler so we do this with a (new) fixed point module.
>
> Change-Id: I9b9631cacc7d90e2801a542a3789118521bc25f0
> Signed-off-by: Stéphane Marchesin <marcheu at chromium.org>
A few quick comments:
- I don't like setparam for this too much. Imo exposing this as an
lvds/eDP connector property makes more sense, and also makes the feature
more accessible to mere mortals. btw I think we should do the same with
the downclock stuff and expose a panel_downclock_freq plus a
panel_downclock enable which is simply initialized at driver load time
with the defaults, but could be freely changed afterwards.
- With connector properties we could also expose tuneables in an easy way,
at least partially addressing Jani's comment (like the display gamma and
maybe also other parameters).
- We need to somehow cope with front-rendering X. Yeah, I know this sucks
and all, but such is life. We already mark framebuffers as busys when
rendering into them directly, I guess we could hook into to that either
disable this feature until the next pageflip. Or switch to a different
mode. The disable needs to be gradually, obviously.
- I'm unsure whether we shouldn't move the fixed-point stuff to a common
place. Wrt all the fixed-point constant I think a little macro to
convert double to 16.16 fixed point would massively help code
readability.
Yours, Daniel
> ---
> drivers/gpu/drm/i915/Makefile | 1 +
> drivers/gpu/drm/i915/i915_dma.c | 16 ++
> drivers/gpu/drm/i915/i915_drv.h | 10 +
> drivers/gpu/drm/i915/i915_irq.c | 8 +-
> drivers/gpu/drm/i915/i915_reg.h | 22 ++
> drivers/gpu/drm/i915/intel_adaptive_backlight.c | 266 +++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_fixedpoint.h | 140 ++++++++++++
> drivers/gpu/drm/i915/intel_panel.c | 6 +
> include/drm/i915_drm.h | 2 +
> 9 files changed, 469 insertions(+), 2 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/intel_adaptive_backlight.c
> create mode 100644 drivers/gpu/drm/i915/intel_fixedpoint.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index ce7fc77..5c125c3 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -13,6 +13,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
> i915_gem_gtt.o \
> i915_gem_tiling.o \
> i915_trace_points.o \
> + intel_adaptive_backlight.o \
> intel_display.o \
> intel_crt.o \
> intel_lvds.o \
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index ba60f3c..c2626d6 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -828,6 +828,22 @@ static int i915_setparam(struct drm_device *dev, void *data,
> /* Userspace can use first N regs */
> dev_priv->fence_reg_start = param->value;
> break;
> + case I915_SETPARAM_ADAPTIVE_BACKLIGHT_ENABLE:
> + if (INTEL_INFO(dev)->gen == 6) {
> + dev_priv->adaptive_backlight_enabled = param->value;
> + } else {
> + DRM_ERROR("No adaptive backlight on !GEN6\n");
> + return -EINVAL;
> + }
> + break;
> + case I915_SETPARAM_PANEL_GAMMA:
> + if (INTEL_INFO(dev)->gen == 6) {
> + dev_priv->adaptive_backlight_panel_gamma = param->value;
> + } else {
> + DRM_ERROR("No adaptive backlight on !GEN6\n");
> + return -EINVAL;
> + }
> + break;
> default:
> DRM_DEBUG_DRIVER("unknown parameter %d\n",
> param->param);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index d89f585..f778f93 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -401,6 +401,13 @@ typedef struct drm_i915_private {
> struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
> struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
>
> + /* Adaptive backlight */
> + bool adaptive_backlight_enabled;
> + int backlight_correction_level;
> + int backlight_correction_count;
> + int backlight_correction_direction;
> + int adaptive_backlight_panel_gamma;
> +
> /* Feature bits from the VBIOS */
> unsigned int int_tv_support:1;
> unsigned int lvds_dither:1;
> @@ -1358,6 +1365,9 @@ extern int i915_restore_state(struct drm_device *dev);
> extern int i915_save_state(struct drm_device *dev);
> extern int i915_restore_state(struct drm_device *dev);
>
> +/* intel_adaptive_backlight.c */
> +extern void intel_adaptive_backlight(struct drm_device *dev, int pipe);
> +
> /* intel_i2c.c */
> extern int intel_setup_gmbus(struct drm_device *dev);
> extern void intel_teardown_gmbus(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index afd4e03..948da6b 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -619,11 +619,15 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
> intel_finish_page_flip_plane(dev, 1);
> }
>
> - if (de_iir & DE_PIPEA_VBLANK)
> + if (de_iir & DE_PIPEA_VBLANK) {
> drm_handle_vblank(dev, 0);
> + intel_adaptive_backlight(dev, 0);
> + }
>
> - if (de_iir & DE_PIPEB_VBLANK)
> + if (de_iir & DE_PIPEB_VBLANK) {
> drm_handle_vblank(dev, 1);
> + intel_adaptive_backlight(dev, 1);
> + }
>
> /* check event from PCH */
> if (de_iir & DE_PCH_EVENT) {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 552264c..2db874d 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3587,6 +3587,28 @@
> #define PWM_PIPE_B (1 << 29)
> #define BLC_PWM_CPU_CTL 0x48254
>
> +#define BLM_HIST_CTL 0x48260
> +#define ENH_HIST_ENABLE (1<<31)
> +#define ENH_MODIF_TBL_ENABLE (1<<30)
> +#define ENH_PIPE_A_SELECT (0<<29)
> +#define ENH_PIPE_B_SELECT (1<<29)
> +#define ENH_PIPE(pipe) _PIPE(pipe, ENH_PIPE_A_SELECT, ENH_PIPE_B_SELECT)
> +#define HIST_MODE_YUV (0<<24)
> +#define HIST_MODE_HSV (1<<24)
> +#define ENH_MODE_DIRECT (0<<13)
> +#define ENH_MODE_ADDITIVE (1<<13)
> +#define ENH_MODE_MULTIPLICATIVE (2<<13)
> +#define BIN_REGISTER_SET (1<<11)
> +#define ENH_NUM_BINS 32
> +
> +#define BLM_HIST_ENH 0x48264
> +
> +#define BLM_HIST_GUARD_BAND 0x48268
> +#define BLM_HIST_INTR_ENABLE (1<<31)
> +#define BLM_HIST_EVENT_STATUS (1<<30)
> +#define BLM_HIST_INTR_DELAY_MASK (0xFF<<22)
> +#define BLM_HIST_INTR_DELAY_SHIFT 22
> +
> #define BLC_PWM_PCH_CTL1 0xc8250
> #define PWM_PCH_ENABLE (1 << 31)
> #define PWM_POLARITY_ACTIVE_LOW (1 << 29)
> diff --git a/drivers/gpu/drm/i915/intel_adaptive_backlight.c b/drivers/gpu/drm/i915/intel_adaptive_backlight.c
> new file mode 100644
> index 0000000..4234962
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_adaptive_backlight.c
> @@ -0,0 +1,266 @@
> +/*
> + * Copyright 2012 The Chromium OS Authors.
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +
> +#include "drmP.h"
> +#include "drm.h"
> +#include "i915_drm.h"
> +#include "i915_drv.h"
> +#include "i915_reg.h"
> +#include "intel_drv.h"
> +#include "intel_fixedpoint.h"
> +
> +/*
> + * This function takes a histogram of buckets as input and determines an
> + * acceptable target backlight level.
> + */
> +static int histogram_find_correction_level(int *levels)
> +{
> + int i, sum = 0;
> + int ratio, distortion, prev_distortion = 0, off, final_ratio, target;
> +
> + for (i = 0; i < ENH_NUM_BINS; i++)
> + sum += levels[i];
> +
> + /* Allow 0.33/256 distortion per pixel, on average */
> + target = sum / 3;
> +
> + /* Special case where we only have less than 100 pixels
> + * outside of the darkest bin.
> + */
> + if (sum - levels[0] <= 100)
> + return 70;
> +
> + for (ratio = ENH_NUM_BINS - 1; ratio >= 0 ; ratio--) {
> + distortion = 0;
> + for (i = ratio; i < ENH_NUM_BINS; i++) {
> + int pixel_distortion = (i - ratio)*8;
> + int num_pixels = levels[i];
> + distortion += num_pixels * pixel_distortion;
> + }
> + if (distortion > target)
> + break;
> + else
> + prev_distortion = distortion;
> + }
> +
> + ratio++;
> +
> + /* If we're not exactly at the border between two buckets, extrapolate
> + * to get 3 extra bits of accuracy.
> + */
> + if (distortion - prev_distortion)
> + off = 8 * (target - prev_distortion) /
> + (distortion - prev_distortion);
> + else
> + off = 0;
> +
> + final_ratio = ratio * 255 / 31 + off;
> +
> + if (final_ratio > 255)
> + final_ratio = 255;
> +
> + /* Never aim for less than 50% of the total backlight */
> + if (final_ratio < 128)
> + final_ratio = 128;
> +
> + return final_ratio;
> +}
> +
> +static void histogram_get_levels(struct drm_device *dev, int pipe, int *levels)
> +{
> + drm_i915_private_t *dev_priv = dev->dev_private;
> + int i;
> +
> + for (i = 0; i < ENH_NUM_BINS; i++) {
> + I915_WRITE(BLM_HIST_CTL, ENH_HIST_ENABLE |
> + ENH_MODIF_TBL_ENABLE |
> + ENH_PIPE(pipe) |
> + HIST_MODE_YUV |
> + ENH_MODE_ADDITIVE |
> + i);
> + levels[i] = I915_READ(BLM_HIST_ENH);
> + }
> +}
> +
> +static void histogram_set_levels(struct drm_device *dev, int pipe, int *levels)
> +{
> + drm_i915_private_t *dev_priv = dev->dev_private;
> + int i;
> +
> + for (i = 0; i < ENH_NUM_BINS; i++) {
> + I915_WRITE(BLM_HIST_CTL, ENH_HIST_ENABLE |
> + ENH_MODIF_TBL_ENABLE |
> + ENH_PIPE(pipe) |
> + HIST_MODE_YUV |
> + ENH_MODE_ADDITIVE |
> + BIN_REGISTER_SET |
> + i);
> + I915_WRITE(BLM_HIST_ENH, levels[i]);
> + }
> +}
> +
> +/*
> + * This function computes the backlight correction level for an acceptable
> + * distortion and fills up the correction bins adequately.
> + */
> +static void
> +adaptive_backlight_compute_correction(struct drm_device *dev, int *levels)
> +{
> + drm_i915_private_t *dev_priv = dev->dev_private;
> + int correction_level;
> + int i, multiplier, one_over_gamma;
> +
> + /* Find the correction level for an acceptable distortion */
> + correction_level = histogram_find_correction_level(levels);
> +
> + /* If we're not yet at our correction target, we need to decide by how
> + * much to move.
> + */
> + if (dev_priv->backlight_correction_level != correction_level) {
> + int delta, direction;
> +
> + direction = (correction_level >
> + dev_priv->backlight_correction_level);
> +
> + if (direction == dev_priv->backlight_correction_direction) {
> + dev_priv->backlight_correction_count++;
> + } else {
> + dev_priv->backlight_correction_count = 0;
> + dev_priv->backlight_correction_direction = direction;
> + }
> +
> + delta = abs(correction_level -
> + dev_priv->backlight_correction_level)/4;
> +
> + if (delta < 1)
> + delta = 1;
> +
> + /* For increasing the brightness, we do it instantly.
> + * For lowering the brightness, we require at least 10 frames
> + * below the current value. This avoids ping-ponging of the
> + * backlight level.
> + *
> + * We also never increase the backlight by more than 6% per
> + * frame, and never lower it by more than 3% per frame, because
> + * the backlight needs time to adjust and the LCD correction
> + * would be "ahead" otherwise.
> + */
> + if (correction_level > dev_priv->backlight_correction_level) {
> + if (delta > 15)
> + delta = 15;
> + dev_priv->backlight_correction_level += delta;
> + } else if ((dev_priv->backlight_correction_count > 10) &&
> + (correction_level < dev_priv->backlight_correction_level)) {
> + if (delta > 7)
> + delta = 7;
> + dev_priv->backlight_correction_level -= delta;
> + }
> + }
> +
> + /* We need to invert the gamma correction of the LCD values,
> + * but not of the backlight which is linear.
> + */
> + one_over_gamma = intel_fixed_div(FIXED_ONE,
> + dev_priv->adaptive_backlight_panel_gamma);
> + multiplier = intel_fixed_pow(dev_priv->backlight_correction_level * 256,
> + one_over_gamma);
> +
> + for (i = 0; i < ENH_NUM_BINS; i++) {
> + int base_value = i * 8 * 4;
> + levels[i] = base_value - base_value * multiplier / 65536;
> + }
> +}
> +
> +/*
> + * A quick note about the adaptive backlight implementation:
> + * If we let it run as designed, it will generate a lot of interrupts which
> + * tends to wake the CPU up and waste power. This is a bad idea for a power
> + * saving feature. Instead, we couple it to the vblank interrupt since that
> + * means we drew something. This means that we do not react to non-vsynced GL
> + * updates, or updates to the front buffer, and also adds a little bit of
> + * extra latency. But it is an acceptable tradeoff to make.
> + */
> +void intel_adaptive_backlight(struct drm_device *dev, int pipe_vblank_event)
> +{
> + drm_i915_private_t *dev_priv = dev->dev_private;
> + int levels[ENH_NUM_BINS];
> + int pipe;
> + struct drm_connector *connector;
> + struct intel_crtc *intel_crtc;
> +
> + if (!dev_priv->adaptive_backlight_enabled)
> + return;
> +
> + /* Find the connector */
> + if (dev_priv->int_lvds_connector)
> + connector = dev_priv->int_lvds_connector;
> + else if (dev_priv->int_edp_connector)
> + connector = dev_priv->int_edp_connector;
> + else
> + return;
> +
> + if (!connector)
> + return;
> +
> + if (!connector->encoder)
> + return;
> +
> + if (!connector->encoder->crtc)
> + return;
> +
> + /* Find the pipe for the panel. */
> + intel_crtc = to_intel_crtc(connector->encoder->crtc);
> + pipe = intel_crtc->pipe;
> +
> + /* The callback happens for both pipe A & B. Now that we know which
> + * pipe we're doing adaptive backlight on, check that it's the right
> + * one. Bail if it isn't.
> + */
> + if (pipe != pipe_vblank_event)
> + return;
> +
> + /* Return if no event. */
> + if (I915_READ(BLM_HIST_GUARD_BAND) & BLM_HIST_EVENT_STATUS == 0)
> + return;
> +
> + /* Make sure we ack the previous event. Even though we do not get the
> + * IRQs (see above explanation), we must still ack the events otherwise
> + * the histogram data doesn't get updated any more.
> + */
> + I915_WRITE(BLM_HIST_GUARD_BAND, BLM_HIST_INTR_ENABLE |
> + BLM_HIST_EVENT_STATUS |
> + (1 << BLM_HIST_INTR_DELAY_SHIFT));
> +
> + histogram_get_levels(dev, pipe, levels);
> +
> + adaptive_backlight_compute_correction(dev, levels);
> +
> + histogram_set_levels(dev, pipe, levels);
> +
> + intel_panel_set_backlight(dev, dev_priv->backlight_level);
> +}
> +
> diff --git a/drivers/gpu/drm/i915/intel_fixedpoint.h b/drivers/gpu/drm/i915/intel_fixedpoint.h
> new file mode 100644
> index 0000000..fff5f0b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_fixedpoint.h
> @@ -0,0 +1,140 @@
> +/*
> + * Copyright 2012 The Chromium OS Authors.
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +/*
> + * The backlight is corrected in linear space. However the LCD correction is
> + * corrected in gama space. So to be able to compute the correction value for
> + * the LCD, we have to compute the inverse gamma. To do so, we carry this
> + * small fixed point module which allows us to use pow() to compute inverse
> + * gamma.
> + *
> + * The fixed point format used here is 16.16.
> + */
> +
> +/* intel_fixed_exp_tbl[x*32] = exp(x) * 65536 */
> +static const int intel_fixed_exp_tbl[33] = {
> +0x00010000, 0x00010820, 0x00011083, 0x00011929, 0x00012216, 0x00012b4b,
> +0x000134cc, 0x00013e99, 0x000148b6, 0x00015325, 0x00015de9, 0x00016905,
> +0x0001747a, 0x0001804d, 0x00018c80, 0x00019916, 0x0001a613, 0x0001b378,
> +0x0001c14b, 0x0001cf8e, 0x0001de45, 0x0001ed74, 0x0001fd1e, 0x00020d47,
> +0x00021df4, 0x00022f28, 0x000240e8, 0x00025338, 0x0002661d, 0x0002799b,
> +0x00028db8, 0x0002a278, 0x0002b7e1
> +};
> +
> +/* intel_fixed_log_tbl[x*32] = log(x) * 65536 */
> +static const int intel_fixed_log_tbl[33] = {
> +0x80000000, 0xfffc88c6, 0xfffd3a38, 0xfffda204, 0xfffdebaa, 0xfffe24ca,
> +0xfffe5376, 0xfffe7aed, 0xfffe9d1c, 0xfffebb43, 0xfffed63c, 0xfffeeea2,
> +0xffff04e8, 0xffff1966, 0xffff2c5f, 0xffff3e08, 0xffff4e8e, 0xffff5e13,
> +0xffff6cb5, 0xffff7a8c, 0xffff87ae, 0xffff942b, 0xffffa014, 0xffffab75,
> +0xffffb65a, 0xffffc0ce, 0xffffcad8, 0xffffd481, 0xffffddd1, 0xffffe6cd,
> +0xffffef7a, 0xfffff7df, 0xffffffff
> +};
> +
> +/* e * 65536 */
> +#define FIXED_E (intel_fixed_exp_tbl[32])
> +/* 1 * 65536 */
> +#define FIXED_ONE 65536
> +
> +static int intel_fixed_mul(int a, int b)
> +{
> + return (int) ((int64_t)a * (int64_t)b / 65536LL);
> +}
> +
> +static int intel_fixed_div(int a, int b)
> +{
> + return (int) ((int64_t)a * 65536LL / (int64_t)b);
> +}
> +
> +/*
> + * Approximate fixed point log function.
> + * Only works for inputs in [0,1[
> + */
> +static int intel_fixed_log(int val)
> +{
> + int index = val * 32 / FIXED_ONE;
> + int remainder = (val & 0x7ff) << 5;
> + int v1 = intel_fixed_log_tbl[index];
> + int v2 = intel_fixed_log_tbl[index+1];
> + int final = v1 + intel_fixed_mul(v2 - v1, remainder);
> + return final;
> +}
> +
> +/*
> + * Approximate fixed point exp function.
> + */
> +static int intel_fixed_exp(int val)
> +{
> + int count = 0;
> + int index, remainder;
> + int int_part = FIXED_ONE, frac_part;
> + int i, v, v1, v2;
> +
> + while (val < 0) {
> + val += FIXED_ONE;
> + count--;
> + }
> +
> + while (val > FIXED_ONE) {
> + val -= FIXED_ONE;
> + count++;
> + }
> +
> + index = val * 32 / FIXED_ONE;
> + remainder = (val & 0x7ff) << 5;
> +
> + v1 = intel_fixed_exp_tbl[index];
> + v2 = intel_fixed_exp_tbl[index+1];
> + frac_part = v1 + intel_fixed_mul(v2 - v1, remainder);
> +
> + if (count < 0) {
> + for (i = 0; i < -count; i++)
> + int_part = intel_fixed_mul(int_part, FIXED_E);
> +
> + v = intel_fixed_div(frac_part, int_part);
> + } else {
> + for (i = 0; i < count; i++)
> + int_part = intel_fixed_mul(int_part, FIXED_E);
> +
> + v = intel_fixed_mul(frac_part, int_part);
> + }
> + return (v >= 0) ? v : 0;
> +}
> +
> +/*
> + * Approximate fixed point pow function.
> + * Only works for x in [0,1[
> + */
> +static int intel_fixed_pow(int x, int y)
> +{
> + int e, p, r;
> + e = intel_fixed_log(x);
> + p = intel_fixed_mul(e, y);
> + r = intel_fixed_exp(p);
> + return r;
> +}
> +
> +
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 3f9249b..ae95163 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -251,6 +251,8 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level
> struct drm_i915_private *dev_priv = dev->dev_private;
> u32 tmp;
>
> + level = level * dev_priv->backlight_correction_level >> 8;
> +
> DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
>
> if (HAS_PCH_SPLIT(dev))
> @@ -306,6 +308,10 @@ static void intel_panel_init_backlight(struct drm_device *dev)
>
> dev_priv->backlight_level = intel_panel_get_backlight(dev);
> dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
> + dev_priv->adaptive_backlight_enabled = 0;
> + /* 2.2 as 16.16 fixed point */
> + dev_priv->adaptive_backlight_panel_gamma = 144179;
> + dev_priv->backlight_correction_level = 256;
> }
>
> enum drm_connector_status
> diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
> index da929bb..70c9cfc 100644
> --- a/include/drm/i915_drm.h
> +++ b/include/drm/i915_drm.h
> @@ -309,6 +309,8 @@ typedef struct drm_i915_getparam {
> #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
> #define I915_SETPARAM_ALLOW_BATCHBUFFER 3
> #define I915_SETPARAM_NUM_USED_FENCES 4
> +#define I915_SETPARAM_ADAPTIVE_BACKLIGHT_ENABLE 5
> +#define I915_SETPARAM_PANEL_GAMMA 6
>
> typedef struct drm_i915_setparam {
> int param;
> --
> 1.7.5.3.367.ga9930
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48
More information about the Intel-gfx
mailing list