aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_panel.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-08-22 08:18:16 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-09-08 05:23:58 -0400
commita95735569312f2ab0c80425e2cd1e5cb0b4e1870 (patch)
tree9daf28afa9b797b7f51486f4f759de9359b1e1e9 /drivers/gpu/drm/i915/intel_panel.c
parent5d607f9b038ea03f5e5b3064d2f3993f9ea67e1e (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_panel.c')
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e7f5299d9d57..30abe7afc942 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -30,6 +30,8 @@
30 30
31#include "intel_drv.h" 31#include "intel_drv.h"
32 32
33#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
34
33void 35void
34intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, 36intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
35 struct drm_display_mode *adjusted_mode) 37 struct drm_display_mode *adjusted_mode)
@@ -109,3 +111,110 @@ done:
109 dev_priv->pch_pf_pos = (x << 16) | y; 111 dev_priv->pch_pf_pos = (x << 16) | y;
110 dev_priv->pch_pf_size = (width << 16) | height; 112 dev_priv->pch_pf_size = (width << 16) | height;
111} 113}
114
115static int is_backlight_combination_mode(struct drm_device *dev)
116{
117 struct drm_i915_private *dev_priv = dev->dev_private;
118
119 if (IS_I965G(dev))
120 return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
121
122 if (IS_GEN2(dev))
123 return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
124
125 return 0;
126}
127
128u32 intel_panel_get_max_backlight(struct drm_device *dev)
129{
130 struct drm_i915_private *dev_priv = dev->dev_private;
131 u32 max;
132
133 if (HAS_PCH_SPLIT(dev)) {
134 max = I915_READ(BLC_PWM_PCH_CTL2) >> 16;
135 } else {
136 max = I915_READ(BLC_PWM_CTL);
137 if (IS_PINEVIEW(dev)) {
138 max >>= 17;
139 } else {
140 max >>= 16;
141 if (!IS_I965G(dev))
142 max &= ~1;
143 }
144
145 if (is_backlight_combination_mode(dev))
146 max *= 0xff;
147 }
148
149 if (max == 0) {
150 /* XXX add code here to query mode clock or hardware clock
151 * and program max PWM appropriately.
152 */
153 DRM_ERROR("fixme: max PWM is zero.\n");
154 max = 1;
155 }
156
157 DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
158 return max;
159}
160
161u32 intel_panel_get_backlight(struct drm_device *dev)
162{
163 struct drm_i915_private *dev_priv = dev->dev_private;
164 u32 val;
165
166 if (HAS_PCH_SPLIT(dev)) {
167 val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
168 } else {
169 val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
170 if (IS_PINEVIEW(dev))
171 val >>= 1;
172
173 if (is_backlight_combination_mode(dev)){
174 u8 lbpc;
175
176 val &= ~1;
177 pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
178 val *= lbpc;
179 val >>= 1;
180 }
181 }
182
183 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
184 return val;
185}
186
187static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
188{
189 struct drm_i915_private *dev_priv = dev->dev_private;
190 u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
191 I915_WRITE(BLC_PWM_CPU_CTL, val | level);
192}
193
194void intel_panel_set_backlight(struct drm_device *dev, u32 level)
195{
196 struct drm_i915_private *dev_priv = dev->dev_private;
197 u32 tmp;
198
199 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
200
201 if (HAS_PCH_SPLIT(dev))
202 return intel_pch_panel_set_backlight(dev, level);
203
204 if (is_backlight_combination_mode(dev)){
205 u32 max = intel_panel_get_max_backlight(dev);
206 u8 lpbc;
207
208 lpbc = level * 0xfe / max + 1;
209 level /= lpbc;
210 pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc);
211 }
212
213 tmp = I915_READ(BLC_PWM_CTL);
214 if (IS_PINEVIEW(dev)) {
215 tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
216 level <<= 1;
217 } else
218 tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
219 I915_WRITE(BLC_PWM_CTL, tmp | level);
220}