[Intel-gfx] [PATCH] drm/i915: Adaptive backlight support

Stéphane Marchesin marcheu at chromium.org
Fri Jun 22 00:08:16 CEST 2012


On Thu, Jun 21, 2012 at 1:21 AM, Jani Nikula <jani.nikula at linux.intel.com>wrote:

> On Thu, 21 Jun 2012, Stéphane Marchesin <marcheu at chromium.org> 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.
>
> Hi Stéphane, interesting work.
>
> My understanding is that content adaptive backlight control is basically
> a function that tries to reduce backlight brightness to save power while
> adjusting gamma to ensure there is no user detectable change in
> image. Like this:
>
>    (reduced_brightness, gamma) = f(brightness, luminance)
>
> In my view, the histogram information, interrupt on its meaningful
> change, brightness and gamma setting are clearly mechanisms the driver
> should provide. I'm not at all sure if the function that defines the
> policy for brightness and gamma changes should be part of the driver.
>
>
Yes, I don't like it either, but the problem is that if we want fast
response time we have to do it from the irq handler, or at least the kernel.



> In fact, looking at the histogram_find_correction_level() and
> adaptive_backlight_compute_correction() functions below, they are filled
> with policy conditions. Usually it's preferred to have the policy in
> user space. The fixed point troubles would all go away as well in user
> space. And there's the added benefit of being able to handle the user's
> desired brightness and possible ambient light sensor based adjustment to
> brightness in a single point of truth.
>
> I guess the question is how to define sensible interfaces to the
> mechanisms in a way that the adaptive backlight function is feasible to
> implement in user space, and the power saving goal could still be
> reached. I would at least like this to be looked into first.
>
>
The issue is that if you have to wake up a user space process every time
you want to recompute the backlight, you're going to offset the backlight
savings with some CPU losses. I wanted to avoid that.

Stéphane



>
> BR,
> Jani.
>
>
>
>
> >
> > Change-Id: I9b9631cacc7d90e2801a542a3789118521bc25f0
> > Signed-off-by: Stéphane Marchesin <marcheu at chromium.org>
> > ---
> >  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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20120621/ff300dd7/attachment.html>


More information about the Intel-gfx mailing list