Rev 2342 | Rev 3037 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2342 | Rev 3031 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | * Dave Airlie |
26 | * Dave Airlie |
27 | * Jesse Barnes |
27 | * Jesse Barnes |
28 | * Chris Wilson |
28 | * Chris Wilson |
29 | */ |
29 | */ |
Line 30... | Line -... | ||
30 | - | ||
31 | #include "intel_drv.h" |
- | |
32 | 30 | ||
33 | static inline int pci_read_config_byte(struct pci_dev *dev, int where, |
- | |
34 | u8 *val) |
- | |
35 | { |
- | |
36 | *val = PciRead8(dev->busnr, dev->devfn, where); |
- | |
37 | return 1; |
- | |
Line 38... | Line -... | ||
38 | } |
- | |
39 | 31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|
40 | static inline int pci_write_config_byte(struct pci_dev *dev, int where, |
- | |
41 | u8 val) |
- | |
42 | { |
32 | |
43 | PciWrite8(dev->busnr, dev->devfn, where, val); |
- | |
Line 44... | Line 33... | ||
44 | return 1; |
33 | #include |
Line 45... | Line 34... | ||
45 | } |
34 | #include "intel_drv.h" |
Line 60... | Line 49... | ||
60 | adjusted_mode->vsync_start = fixed_mode->vsync_start; |
49 | adjusted_mode->vsync_start = fixed_mode->vsync_start; |
61 | adjusted_mode->vsync_end = fixed_mode->vsync_end; |
50 | adjusted_mode->vsync_end = fixed_mode->vsync_end; |
62 | adjusted_mode->vtotal = fixed_mode->vtotal; |
51 | adjusted_mode->vtotal = fixed_mode->vtotal; |
Line 63... | Line 52... | ||
63 | 52 | ||
64 | adjusted_mode->clock = fixed_mode->clock; |
- | |
65 | - | ||
66 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
53 | adjusted_mode->clock = fixed_mode->clock; |
Line 67... | Line 54... | ||
67 | } |
54 | } |
68 | 55 | ||
69 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
56 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
70 | void |
57 | void |
71 | intel_pch_panel_fitting(struct drm_device *dev, |
58 | intel_pch_panel_fitting(struct drm_device *dev, |
72 | int fitting_mode, |
59 | int fitting_mode, |
73 | struct drm_display_mode *mode, |
60 | const struct drm_display_mode *mode, |
74 | struct drm_display_mode *adjusted_mode) |
61 | struct drm_display_mode *adjusted_mode) |
75 | { |
62 | { |
Line 154... | Line 141... | ||
154 | val = I915_READ(BLC_PWM_PCH_CTL2); |
141 | val = I915_READ(BLC_PWM_PCH_CTL2); |
155 | if (dev_priv->saveBLC_PWM_CTL2 == 0) { |
142 | if (dev_priv->saveBLC_PWM_CTL2 == 0) { |
156 | dev_priv->saveBLC_PWM_CTL2 = val; |
143 | dev_priv->saveBLC_PWM_CTL2 = val; |
157 | } else if (val == 0) { |
144 | } else if (val == 0) { |
158 | I915_WRITE(BLC_PWM_PCH_CTL2, |
145 | I915_WRITE(BLC_PWM_PCH_CTL2, |
159 | dev_priv->saveBLC_PWM_CTL); |
146 | dev_priv->saveBLC_PWM_CTL2); |
160 | val = dev_priv->saveBLC_PWM_CTL; |
147 | val = dev_priv->saveBLC_PWM_CTL2; |
161 | } |
148 | } |
162 | } else { |
149 | } else { |
163 | val = I915_READ(BLC_PWM_CTL); |
150 | val = I915_READ(BLC_PWM_CTL); |
164 | if (dev_priv->saveBLC_PWM_CTL == 0) { |
151 | if (dev_priv->saveBLC_PWM_CTL == 0) { |
165 | dev_priv->saveBLC_PWM_CTL = val; |
152 | dev_priv->saveBLC_PWM_CTL = val; |
Line 174... | Line 161... | ||
174 | } |
161 | } |
Line 175... | Line 162... | ||
175 | 162 | ||
176 | return val; |
163 | return val; |
Line 177... | Line 164... | ||
177 | } |
164 | } |
178 | 165 | ||
179 | u32 intel_panel_get_max_backlight(struct drm_device *dev) |
166 | static u32 _intel_panel_get_max_backlight(struct drm_device *dev) |
180 | { |
167 | { |
Line 181... | Line 168... | ||
181 | struct drm_i915_private *dev_priv = dev->dev_private; |
168 | struct drm_i915_private *dev_priv = dev->dev_private; |
182 | u32 max; |
- | |
183 | - | ||
184 | max = i915_read_blc_pwm_ctl(dev_priv); |
- | |
185 | if (max == 0) { |
- | |
186 | /* XXX add code here to query mode clock or hardware clock |
- | |
187 | * and program max PWM appropriately. |
- | |
188 | */ |
- | |
Line 189... | Line 169... | ||
189 | printk(KERN_WARNING "fixme: max PWM is zero.\n"); |
169 | u32 max; |
190 | return 1; |
170 | |
191 | } |
171 | max = i915_read_blc_pwm_ctl(dev_priv); |
192 | 172 | ||
Line 200... | Line 180... | ||
200 | 180 | ||
201 | if (is_backlight_combination_mode(dev)) |
181 | if (is_backlight_combination_mode(dev)) |
202 | max *= 0xff; |
182 | max *= 0xff; |
Line -... | Line 183... | ||
- | 183 | } |
|
- | 184 | ||
- | 185 | return max; |
|
- | 186 | } |
|
- | 187 | ||
- | 188 | u32 intel_panel_get_max_backlight(struct drm_device *dev) |
|
- | 189 | { |
|
- | 190 | u32 max; |
|
- | 191 | ||
- | 192 | max = _intel_panel_get_max_backlight(dev); |
|
- | 193 | if (max == 0) { |
|
- | 194 | /* XXX add code here to query mode clock or hardware clock |
|
- | 195 | * and program max PWM appropriately. |
|
- | 196 | */ |
|
- | 197 | printk("fixme: max PWM is zero\n"); |
|
- | 198 | return 1; |
|
203 | } |
199 | } |
204 | 200 | ||
205 | DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
201 | DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
Line -... | Line 202... | ||
- | 202 | return max; |
|
- | 203 | } |
|
- | 204 | ||
- | 205 | static int i915_panel_invert_brightness; |
|
- | 206 | MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " |
|
- | 207 | "(-1 force normal, 0 machine defaults, 1 force inversion), please " |
|
- | 208 | "report PCI device ID, subsystem vendor and subsystem device ID " |
|
- | 209 | "to dri-devel@lists.freedesktop.org, if your machine needs it. " |
|
- | 210 | "It will then be included in an upcoming module version."); |
|
- | 211 | module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
|
- | 212 | static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) |
|
- | 213 | { |
|
- | 214 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 215 | ||
- | 216 | if (i915_panel_invert_brightness < 0) |
|
- | 217 | return val; |
|
- | 218 | ||
- | 219 | if (i915_panel_invert_brightness > 0 || |
|
- | 220 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) |
|
- | 221 | return intel_panel_get_max_backlight(dev) - val; |
|
- | 222 | ||
206 | return max; |
223 | return val; |
207 | } |
224 | } |
208 | 225 | ||
209 | u32 intel_panel_get_backlight(struct drm_device *dev) |
226 | static u32 intel_panel_get_backlight(struct drm_device *dev) |
Line 210... | Line 227... | ||
210 | { |
227 | { |
Line 224... | Line 241... | ||
224 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
241 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
225 | val *= lbpc; |
242 | val *= lbpc; |
226 | } |
243 | } |
227 | } |
244 | } |
Line -... | Line 245... | ||
- | 245 | ||
228 | 246 | val = intel_panel_compute_brightness(dev, val); |
|
229 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
247 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
230 | return val; |
248 | return val; |
Line 231... | Line 249... | ||
231 | } |
249 | } |
Line 241... | Line 259... | ||
241 | { |
259 | { |
242 | struct drm_i915_private *dev_priv = dev->dev_private; |
260 | struct drm_i915_private *dev_priv = dev->dev_private; |
243 | u32 tmp; |
261 | u32 tmp; |
Line 244... | Line 262... | ||
244 | 262 | ||
- | 263 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
|
Line 245... | Line 264... | ||
245 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
264 | level = intel_panel_compute_brightness(dev, level); |
246 | 265 | ||
Line 247... | Line 266... | ||
247 | if (HAS_PCH_SPLIT(dev)) |
266 | if (HAS_PCH_SPLIT(dev)) |
Line 276... | Line 295... | ||
276 | { |
295 | { |
277 | struct drm_i915_private *dev_priv = dev->dev_private; |
296 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 278... | Line 297... | ||
278 | 297 | ||
279 | dev_priv->backlight_enabled = false; |
298 | dev_priv->backlight_enabled = false; |
- | 299 | intel_panel_actually_set_backlight(dev, 0); |
|
- | 300 | ||
- | 301 | if (INTEL_INFO(dev)->gen >= 4) { |
|
- | 302 | uint32_t reg, tmp; |
|
- | 303 | ||
- | 304 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
- | 305 | ||
- | 306 | I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); |
|
- | 307 | ||
- | 308 | if (HAS_PCH_SPLIT(dev)) { |
|
- | 309 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
|
- | 310 | tmp &= ~BLM_PCH_PWM_ENABLE; |
|
- | 311 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
|
- | 312 | } |
|
280 | intel_panel_actually_set_backlight(dev, 0); |
313 | } |
Line 281... | Line 314... | ||
281 | } |
314 | } |
- | 315 | ||
282 | 316 | void intel_panel_enable_backlight(struct drm_device *dev, |
|
283 | void intel_panel_enable_backlight(struct drm_device *dev) |
317 | enum pipe pipe) |
Line 284... | Line 318... | ||
284 | { |
318 | { |
285 | struct drm_i915_private *dev_priv = dev->dev_private; |
319 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line -... | Line 320... | ||
- | 320 | ||
- | 321 | if (dev_priv->backlight_level == 0) |
|
- | 322 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
|
- | 323 | ||
- | 324 | if (INTEL_INFO(dev)->gen >= 4) { |
|
- | 325 | uint32_t reg, tmp; |
|
- | 326 | ||
- | 327 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
- | 328 | ||
- | 329 | ||
- | 330 | tmp = I915_READ(reg); |
|
- | 331 | ||
- | 332 | /* Note that this can also get called through dpms changes. And |
|
- | 333 | * we don't track the backlight dpms state, hence check whether |
|
- | 334 | * we have to do anything first. */ |
|
- | 335 | if (tmp & BLM_PWM_ENABLE) |
|
- | 336 | goto set_level; |
|
- | 337 | ||
- | 338 | if (dev_priv->num_pipe == 3) |
|
- | 339 | tmp &= ~BLM_PIPE_SELECT_IVB; |
|
- | 340 | else |
|
- | 341 | tmp &= ~BLM_PIPE_SELECT; |
|
- | 342 | ||
- | 343 | tmp |= BLM_PIPE(pipe); |
|
- | 344 | tmp &= ~BLM_PWM_ENABLE; |
|
- | 345 | ||
- | 346 | I915_WRITE(reg, tmp); |
|
- | 347 | POSTING_READ(reg); |
|
- | 348 | I915_WRITE(reg, tmp | BLM_PWM_ENABLE); |
|
- | 349 | ||
- | 350 | if (HAS_PCH_SPLIT(dev)) { |
|
- | 351 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
|
- | 352 | tmp |= BLM_PCH_PWM_ENABLE; |
|
- | 353 | tmp &= ~BLM_PCH_OVERRIDE_ENABLE; |
|
- | 354 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
|
- | 355 | } |
|
- | 356 | } |
|
- | 357 | ||
- | 358 | set_level: |
|
286 | 359 | /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. |
|
287 | if (dev_priv->backlight_level == 0) |
360 | * BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
288 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
361 | * registers are set. |
Line 289... | Line 362... | ||
289 | 362 | */ |
|
Line 357... | Line 430... | ||
357 | else if (dev_priv->int_edp_connector) |
430 | else if (dev_priv->int_edp_connector) |
358 | connector = dev_priv->int_edp_connector; |
431 | connector = dev_priv->int_edp_connector; |
359 | else |
432 | else |
360 | return -ENODEV; |
433 | return -ENODEV; |
Line -... | Line 434... | ||
- | 434 | ||
361 | 435 | memset(&props, 0, sizeof(props)); |
|
362 | props.type = BACKLIGHT_RAW; |
436 | props.type = BACKLIGHT_RAW; |
- | 437 | props.max_brightness = _intel_panel_get_max_backlight(dev); |
|
- | 438 | if (props.max_brightness == 0) { |
|
- | 439 | DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |
|
- | 440 | return -ENODEV; |
|
363 | props.max_brightness = intel_panel_get_max_backlight(dev); |
441 | } |
364 | dev_priv->backlight = |
442 | dev_priv->backlight = |
365 | backlight_device_register("intel_backlight", |
443 | backlight_device_register("intel_backlight", |
366 | &connector->kdev, dev, |
444 | &connector->kdev, dev, |