diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-08-22 08:18:16 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-08 05:23:58 -0400 |
commit | a95735569312f2ab0c80425e2cd1e5cb0b4e1870 (patch) | |
tree | 9daf28afa9b797b7f51486f4f759de9359b1e1e9 /drivers/gpu/drm/i915/intel_opregion.c | |
parent | 5d607f9b038ea03f5e5b3064d2f3993f9ea67e1e (diff) |
drm/i915: Refactor panel backlight controls
There were two instances of code to control the panel backlight and
neither handled the complete set of device variations.
Fixes:
Bug 29716 - [GM965] Regression: Backlight resets to minimum when changing resolution
https://bugs.freedesktop.org/show_bug.cgi?id=29716
And a bug on one of my PineView boxes which overflowed the backlight
value.
Incorporates part of a similar patch by Matthew Garrett that exposes a
native Intel backlight controller.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_opregion.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 61 |
1 files changed, 6 insertions, 55 deletions
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 3cb13237ba58..917c7dc3cd6b 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -31,9 +31,9 @@ | |||
31 | #include "drmP.h" | 31 | #include "drmP.h" |
32 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
33 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
34 | #include "intel_drv.h" | ||
34 | 35 | ||
35 | #define PCI_ASLE 0xe4 | 36 | #define PCI_ASLE 0xe4 |
36 | #define PCI_LBPC 0xf4 | ||
37 | #define PCI_ASLS 0xfc | 37 | #define PCI_ASLS 0xfc |
38 | 38 | ||
39 | #define OPREGION_HEADER_OFFSET 0 | 39 | #define OPREGION_HEADER_OFFSET 0 |
@@ -147,36 +147,17 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | |||
147 | { | 147 | { |
148 | struct drm_i915_private *dev_priv = dev->dev_private; | 148 | struct drm_i915_private *dev_priv = dev->dev_private; |
149 | struct opregion_asle *asle = dev_priv->opregion.asle; | 149 | struct opregion_asle *asle = dev_priv->opregion.asle; |
150 | u32 blc_pwm_ctl, blc_pwm_ctl2; | 150 | u32 max; |
151 | u32 max_backlight, level, shift; | ||
152 | 151 | ||
153 | if (!(bclp & ASLE_BCLP_VALID)) | 152 | if (!(bclp & ASLE_BCLP_VALID)) |
154 | return ASLE_BACKLIGHT_FAILED; | 153 | return ASLE_BACKLIGHT_FAILED; |
155 | 154 | ||
156 | bclp &= ASLE_BCLP_MSK; | 155 | bclp &= ASLE_BCLP_MSK; |
157 | if (bclp < 0 || bclp > 255) | 156 | if (bclp > 255) |
158 | return ASLE_BACKLIGHT_FAILED; | 157 | return ASLE_BACKLIGHT_FAILED; |
159 | 158 | ||
160 | blc_pwm_ctl = I915_READ(BLC_PWM_CTL); | 159 | max = intel_panel_get_max_backlight(dev); |
161 | blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2); | 160 | intel_panel_set_backlight(dev, bclp * max / 255); |
162 | |||
163 | if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) | ||
164 | pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); | ||
165 | else { | ||
166 | if (IS_PINEVIEW(dev)) { | ||
167 | blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); | ||
168 | max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
169 | BACKLIGHT_MODULATION_FREQ_SHIFT; | ||
170 | shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1; | ||
171 | } else { | ||
172 | blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
173 | max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
174 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | ||
175 | shift = BACKLIGHT_DUTY_CYCLE_SHIFT; | ||
176 | } | ||
177 | level = (bclp * max_backlight) / 255; | ||
178 | I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift)); | ||
179 | } | ||
180 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | 161 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; |
181 | 162 | ||
182 | return 0; | 163 | return 0; |
@@ -243,36 +224,6 @@ void intel_opregion_asle_intr(struct drm_device *dev) | |||
243 | asle->aslc = asle_stat; | 224 | asle->aslc = asle_stat; |
244 | } | 225 | } |
245 | 226 | ||
246 | static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) | ||
247 | { | ||
248 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
249 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
250 | u32 cpu_pwm_ctl, pch_pwm_ctl2; | ||
251 | u32 max_backlight, level; | ||
252 | |||
253 | if (!(bclp & ASLE_BCLP_VALID)) | ||
254 | return ASLE_BACKLIGHT_FAILED; | ||
255 | |||
256 | bclp &= ASLE_BCLP_MSK; | ||
257 | if (bclp < 0 || bclp > 255) | ||
258 | return ASLE_BACKLIGHT_FAILED; | ||
259 | |||
260 | cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL); | ||
261 | pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); | ||
262 | /* get the max PWM frequency */ | ||
263 | max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
264 | /* calculate the expected PMW frequency */ | ||
265 | level = (bclp * max_backlight) / 255; | ||
266 | /* reserve the high 16 bits */ | ||
267 | cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK); | ||
268 | /* write the updated PWM frequency */ | ||
269 | I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level); | ||
270 | |||
271 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* Only present on Ironlake+ */ | 227 | /* Only present on Ironlake+ */ |
277 | void intel_opregion_gse_intr(struct drm_device *dev) | 228 | void intel_opregion_gse_intr(struct drm_device *dev) |
278 | { | 229 | { |
@@ -297,7 +248,7 @@ void intel_opregion_gse_intr(struct drm_device *dev) | |||
297 | } | 248 | } |
298 | 249 | ||
299 | if (asle_req & ASLE_SET_BACKLIGHT) | 250 | if (asle_req & ASLE_SET_BACKLIGHT) |
300 | asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp); | 251 | asle_stat |= asle_set_backlight(dev, asle->bclp); |
301 | 252 | ||
302 | if (asle_req & ASLE_SET_PFIT) { | 253 | if (asle_req & ASLE_SET_PFIT) { |
303 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); | 254 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); |