28,23 → 28,12 |
* Chris Wilson <chris@chris-wilson.co.uk> |
*/ |
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|
#include <linux/moduleparam.h> |
#include "intel_drv.h" |
|
static inline int pci_read_config_byte(struct pci_dev *dev, int where, |
u8 *val) |
{ |
*val = PciRead8(dev->busnr, dev->devfn, where); |
return 1; |
} |
|
static inline int pci_write_config_byte(struct pci_dev *dev, int where, |
u8 val) |
{ |
PciWrite8(dev->busnr, dev->devfn, where, val); |
return 1; |
} |
|
|
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ |
|
void |
62,8 → 51,6 |
adjusted_mode->vtotal = fixed_mode->vtotal; |
|
adjusted_mode->clock = fixed_mode->clock; |
|
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
} |
|
/* adjusted_mode has been preset to be the panel's fixed mode */ |
70,7 → 57,7 |
void |
intel_pch_panel_fitting(struct drm_device *dev, |
int fitting_mode, |
struct drm_display_mode *mode, |
const struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
156,8 → 143,8 |
dev_priv->saveBLC_PWM_CTL2 = val; |
} else if (val == 0) { |
I915_WRITE(BLC_PWM_PCH_CTL2, |
dev_priv->saveBLC_PWM_CTL); |
val = dev_priv->saveBLC_PWM_CTL; |
dev_priv->saveBLC_PWM_CTL2); |
val = dev_priv->saveBLC_PWM_CTL2; |
} |
} else { |
val = I915_READ(BLC_PWM_CTL); |
176,19 → 163,12 |
return val; |
} |
|
u32 intel_panel_get_max_backlight(struct drm_device *dev) |
static u32 _intel_panel_get_max_backlight(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 max; |
|
max = i915_read_blc_pwm_ctl(dev_priv); |
if (max == 0) { |
/* XXX add code here to query mode clock or hardware clock |
* and program max PWM appropriately. |
*/ |
printk(KERN_WARNING "fixme: max PWM is zero.\n"); |
return 1; |
} |
|
if (HAS_PCH_SPLIT(dev)) { |
max >>= 16; |
202,13 → 182,50 |
max *= 0xff; |
} |
|
return max; |
} |
|
u32 intel_panel_get_max_backlight(struct drm_device *dev) |
{ |
u32 max; |
|
max = _intel_panel_get_max_backlight(dev); |
if (max == 0) { |
/* XXX add code here to query mode clock or hardware clock |
* and program max PWM appropriately. |
*/ |
printk("fixme: max PWM is zero\n"); |
return 1; |
} |
|
DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
return max; |
} |
|
u32 intel_panel_get_backlight(struct drm_device *dev) |
static int i915_panel_invert_brightness; |
MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " |
"(-1 force normal, 0 machine defaults, 1 force inversion), please " |
"report PCI device ID, subsystem vendor and subsystem device ID " |
"to dri-devel@lists.freedesktop.org, if your machine needs it. " |
"It will then be included in an upcoming module version."); |
module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (i915_panel_invert_brightness < 0) |
return val; |
|
if (i915_panel_invert_brightness > 0 || |
dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) |
return intel_panel_get_max_backlight(dev) - val; |
|
return val; |
} |
|
static u32 intel_panel_get_backlight(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val; |
|
if (HAS_PCH_SPLIT(dev)) { |
226,6 → 243,7 |
} |
} |
|
val = intel_panel_compute_brightness(dev, val); |
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
return val; |
} |
243,6 → 261,7 |
u32 tmp; |
|
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
level = intel_panel_compute_brightness(dev, level); |
|
if (HAS_PCH_SPLIT(dev)) |
return intel_pch_panel_set_backlight(dev, level); |
278,9 → 297,24 |
|
dev_priv->backlight_enabled = false; |
intel_panel_actually_set_backlight(dev, 0); |
|
if (INTEL_INFO(dev)->gen >= 4) { |
uint32_t reg, tmp; |
|
reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); |
|
if (HAS_PCH_SPLIT(dev)) { |
tmp = I915_READ(BLC_PWM_PCH_CTL1); |
tmp &= ~BLM_PCH_PWM_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
} |
} |
} |
|
void intel_panel_enable_backlight(struct drm_device *dev) |
void intel_panel_enable_backlight(struct drm_device *dev, |
enum pipe pipe) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
287,6 → 321,45 |
if (dev_priv->backlight_level == 0) |
dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
|
if (INTEL_INFO(dev)->gen >= 4) { |
uint32_t reg, tmp; |
|
reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
|
tmp = I915_READ(reg); |
|
/* Note that this can also get called through dpms changes. And |
* we don't track the backlight dpms state, hence check whether |
* we have to do anything first. */ |
if (tmp & BLM_PWM_ENABLE) |
goto set_level; |
|
if (dev_priv->num_pipe == 3) |
tmp &= ~BLM_PIPE_SELECT_IVB; |
else |
tmp &= ~BLM_PIPE_SELECT; |
|
tmp |= BLM_PIPE(pipe); |
tmp &= ~BLM_PWM_ENABLE; |
|
I915_WRITE(reg, tmp); |
POSTING_READ(reg); |
I915_WRITE(reg, tmp | BLM_PWM_ENABLE); |
|
if (HAS_PCH_SPLIT(dev)) { |
tmp = I915_READ(BLC_PWM_PCH_CTL1); |
tmp |= BLM_PCH_PWM_ENABLE; |
tmp &= ~BLM_PCH_OVERRIDE_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
} |
} |
|
set_level: |
/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. |
* BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
* registers are set. |
*/ |
dev_priv->backlight_enabled = true; |
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); |
} |
359,8 → 432,13 |
else |
return -ENODEV; |
|
memset(&props, 0, sizeof(props)); |
props.type = BACKLIGHT_RAW; |
props.max_brightness = intel_panel_get_max_backlight(dev); |
props.max_brightness = _intel_panel_get_max_backlight(dev); |
if (props.max_brightness == 0) { |
DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |
return -ENODEV; |
} |
dev_priv->backlight = |
backlight_device_register("intel_backlight", |
&connector->kdev, dev, |