[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