2 * Copyright © 2006-2010 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
28 * Chris Wilson <chris@chris-wilson.co.uk>
31 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33 #include <linux/moduleparam.h>
34 #include "intel_drv.h"
36 #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
39 intel_fixed_panel_mode(const struct drm_display_mode
*fixed_mode
,
40 struct drm_display_mode
*adjusted_mode
)
42 drm_mode_copy(adjusted_mode
, fixed_mode
);
44 drm_mode_set_crtcinfo(adjusted_mode
, 0);
47 /* adjusted_mode has been preset to be the panel's fixed mode */
49 intel_pch_panel_fitting(struct intel_crtc
*intel_crtc
,
50 struct intel_crtc_config
*pipe_config
,
53 struct drm_display_mode
*adjusted_mode
;
54 int x
, y
, width
, height
;
56 adjusted_mode
= &pipe_config
->adjusted_mode
;
58 x
= y
= width
= height
= 0;
60 /* Native modes don't need fitting */
61 if (adjusted_mode
->hdisplay
== pipe_config
->pipe_src_w
&&
62 adjusted_mode
->vdisplay
== pipe_config
->pipe_src_h
)
65 switch (fitting_mode
) {
66 case DRM_MODE_SCALE_CENTER
:
67 width
= pipe_config
->pipe_src_w
;
68 height
= pipe_config
->pipe_src_h
;
69 x
= (adjusted_mode
->hdisplay
- width
+ 1)/2;
70 y
= (adjusted_mode
->vdisplay
- height
+ 1)/2;
73 case DRM_MODE_SCALE_ASPECT
:
74 /* Scale but preserve the aspect ratio */
76 u32 scaled_width
= adjusted_mode
->hdisplay
77 * pipe_config
->pipe_src_h
;
78 u32 scaled_height
= pipe_config
->pipe_src_w
79 * adjusted_mode
->vdisplay
;
80 if (scaled_width
> scaled_height
) { /* pillar */
81 width
= scaled_height
/ pipe_config
->pipe_src_h
;
84 x
= (adjusted_mode
->hdisplay
- width
+ 1) / 2;
86 height
= adjusted_mode
->vdisplay
;
87 } else if (scaled_width
< scaled_height
) { /* letter */
88 height
= scaled_width
/ pipe_config
->pipe_src_w
;
91 y
= (adjusted_mode
->vdisplay
- height
+ 1) / 2;
93 width
= adjusted_mode
->hdisplay
;
96 width
= adjusted_mode
->hdisplay
;
97 height
= adjusted_mode
->vdisplay
;
102 case DRM_MODE_SCALE_FULLSCREEN
:
104 width
= adjusted_mode
->hdisplay
;
105 height
= adjusted_mode
->vdisplay
;
109 WARN(1, "bad panel fit mode: %d\n", fitting_mode
);
114 pipe_config
->pch_pfit
.pos
= (x
<< 16) | y
;
115 pipe_config
->pch_pfit
.size
= (width
<< 16) | height
;
116 pipe_config
->pch_pfit
.enabled
= pipe_config
->pch_pfit
.size
!= 0;
120 centre_horizontally(struct drm_display_mode
*mode
,
123 u32 border
, sync_pos
, blank_width
, sync_width
;
125 /* keep the hsync and hblank widths constant */
126 sync_width
= mode
->crtc_hsync_end
- mode
->crtc_hsync_start
;
127 blank_width
= mode
->crtc_hblank_end
- mode
->crtc_hblank_start
;
128 sync_pos
= (blank_width
- sync_width
+ 1) / 2;
130 border
= (mode
->hdisplay
- width
+ 1) / 2;
131 border
+= border
& 1; /* make the border even */
133 mode
->crtc_hdisplay
= width
;
134 mode
->crtc_hblank_start
= width
+ border
;
135 mode
->crtc_hblank_end
= mode
->crtc_hblank_start
+ blank_width
;
137 mode
->crtc_hsync_start
= mode
->crtc_hblank_start
+ sync_pos
;
138 mode
->crtc_hsync_end
= mode
->crtc_hsync_start
+ sync_width
;
142 centre_vertically(struct drm_display_mode
*mode
,
145 u32 border
, sync_pos
, blank_width
, sync_width
;
147 /* keep the vsync and vblank widths constant */
148 sync_width
= mode
->crtc_vsync_end
- mode
->crtc_vsync_start
;
149 blank_width
= mode
->crtc_vblank_end
- mode
->crtc_vblank_start
;
150 sync_pos
= (blank_width
- sync_width
+ 1) / 2;
152 border
= (mode
->vdisplay
- height
+ 1) / 2;
154 mode
->crtc_vdisplay
= height
;
155 mode
->crtc_vblank_start
= height
+ border
;
156 mode
->crtc_vblank_end
= mode
->crtc_vblank_start
+ blank_width
;
158 mode
->crtc_vsync_start
= mode
->crtc_vblank_start
+ sync_pos
;
159 mode
->crtc_vsync_end
= mode
->crtc_vsync_start
+ sync_width
;
162 static inline u32
panel_fitter_scaling(u32 source
, u32 target
)
165 * Floating point operation is not supported. So the FACTOR
166 * is defined, which can avoid the floating point computation
167 * when calculating the panel ratio.
170 #define FACTOR (1 << ACCURACY)
171 u32 ratio
= source
* FACTOR
/ target
;
172 return (FACTOR
* ratio
+ FACTOR
/2) / FACTOR
;
175 static void i965_scale_aspect(struct intel_crtc_config
*pipe_config
,
178 struct drm_display_mode
*adjusted_mode
= &pipe_config
->adjusted_mode
;
179 u32 scaled_width
= adjusted_mode
->hdisplay
*
180 pipe_config
->pipe_src_h
;
181 u32 scaled_height
= pipe_config
->pipe_src_w
*
182 adjusted_mode
->vdisplay
;
184 /* 965+ is easy, it does everything in hw */
185 if (scaled_width
> scaled_height
)
186 *pfit_control
|= PFIT_ENABLE
|
188 else if (scaled_width
< scaled_height
)
189 *pfit_control
|= PFIT_ENABLE
|
191 else if (adjusted_mode
->hdisplay
!= pipe_config
->pipe_src_w
)
192 *pfit_control
|= PFIT_ENABLE
| PFIT_SCALING_AUTO
;
195 static void i9xx_scale_aspect(struct intel_crtc_config
*pipe_config
,
196 u32
*pfit_control
, u32
*pfit_pgm_ratios
,
199 struct drm_display_mode
*adjusted_mode
= &pipe_config
->adjusted_mode
;
200 u32 scaled_width
= adjusted_mode
->hdisplay
*
201 pipe_config
->pipe_src_h
;
202 u32 scaled_height
= pipe_config
->pipe_src_w
*
203 adjusted_mode
->vdisplay
;
207 * For earlier chips we have to calculate the scaling
208 * ratio by hand and program it into the
209 * PFIT_PGM_RATIO register
211 if (scaled_width
> scaled_height
) { /* pillar */
212 centre_horizontally(adjusted_mode
,
214 pipe_config
->pipe_src_h
);
216 *border
= LVDS_BORDER_ENABLE
;
217 if (pipe_config
->pipe_src_h
!= adjusted_mode
->vdisplay
) {
218 bits
= panel_fitter_scaling(pipe_config
->pipe_src_h
,
219 adjusted_mode
->vdisplay
);
221 *pfit_pgm_ratios
|= (bits
<< PFIT_HORIZ_SCALE_SHIFT
|
222 bits
<< PFIT_VERT_SCALE_SHIFT
);
223 *pfit_control
|= (PFIT_ENABLE
|
224 VERT_INTERP_BILINEAR
|
225 HORIZ_INTERP_BILINEAR
);
227 } else if (scaled_width
< scaled_height
) { /* letter */
228 centre_vertically(adjusted_mode
,
230 pipe_config
->pipe_src_w
);
232 *border
= LVDS_BORDER_ENABLE
;
233 if (pipe_config
->pipe_src_w
!= adjusted_mode
->hdisplay
) {
234 bits
= panel_fitter_scaling(pipe_config
->pipe_src_w
,
235 adjusted_mode
->hdisplay
);
237 *pfit_pgm_ratios
|= (bits
<< PFIT_HORIZ_SCALE_SHIFT
|
238 bits
<< PFIT_VERT_SCALE_SHIFT
);
239 *pfit_control
|= (PFIT_ENABLE
|
240 VERT_INTERP_BILINEAR
|
241 HORIZ_INTERP_BILINEAR
);
244 /* Aspects match, Let hw scale both directions */
245 *pfit_control
|= (PFIT_ENABLE
|
246 VERT_AUTO_SCALE
| HORIZ_AUTO_SCALE
|
247 VERT_INTERP_BILINEAR
|
248 HORIZ_INTERP_BILINEAR
);
252 void intel_gmch_panel_fitting(struct intel_crtc
*intel_crtc
,
253 struct intel_crtc_config
*pipe_config
,
256 struct drm_device
*dev
= intel_crtc
->base
.dev
;
257 u32 pfit_control
= 0, pfit_pgm_ratios
= 0, border
= 0;
258 struct drm_display_mode
*adjusted_mode
;
260 adjusted_mode
= &pipe_config
->adjusted_mode
;
262 /* Native modes don't need fitting */
263 if (adjusted_mode
->hdisplay
== pipe_config
->pipe_src_w
&&
264 adjusted_mode
->vdisplay
== pipe_config
->pipe_src_h
)
267 switch (fitting_mode
) {
268 case DRM_MODE_SCALE_CENTER
:
270 * For centered modes, we have to calculate border widths &
271 * heights and modify the values programmed into the CRTC.
273 centre_horizontally(adjusted_mode
, pipe_config
->pipe_src_w
);
274 centre_vertically(adjusted_mode
, pipe_config
->pipe_src_h
);
275 border
= LVDS_BORDER_ENABLE
;
277 case DRM_MODE_SCALE_ASPECT
:
278 /* Scale but preserve the aspect ratio */
279 if (INTEL_INFO(dev
)->gen
>= 4)
280 i965_scale_aspect(pipe_config
, &pfit_control
);
282 i9xx_scale_aspect(pipe_config
, &pfit_control
,
283 &pfit_pgm_ratios
, &border
);
285 case DRM_MODE_SCALE_FULLSCREEN
:
287 * Full scaling, even if it changes the aspect ratio.
288 * Fortunately this is all done for us in hw.
290 if (pipe_config
->pipe_src_h
!= adjusted_mode
->vdisplay
||
291 pipe_config
->pipe_src_w
!= adjusted_mode
->hdisplay
) {
292 pfit_control
|= PFIT_ENABLE
;
293 if (INTEL_INFO(dev
)->gen
>= 4)
294 pfit_control
|= PFIT_SCALING_AUTO
;
296 pfit_control
|= (VERT_AUTO_SCALE
|
297 VERT_INTERP_BILINEAR
|
299 HORIZ_INTERP_BILINEAR
);
303 WARN(1, "bad panel fit mode: %d\n", fitting_mode
);
307 /* 965+ wants fuzzy fitting */
308 /* FIXME: handle multiple panels by failing gracefully */
309 if (INTEL_INFO(dev
)->gen
>= 4)
310 pfit_control
|= ((intel_crtc
->pipe
<< PFIT_PIPE_SHIFT
) |
314 if ((pfit_control
& PFIT_ENABLE
) == 0) {
319 /* Make sure pre-965 set dither correctly for 18bpp panels. */
320 if (INTEL_INFO(dev
)->gen
< 4 && pipe_config
->pipe_bpp
== 18)
321 pfit_control
|= PANEL_8TO6_DITHER_ENABLE
;
323 pipe_config
->gmch_pfit
.control
= pfit_control
;
324 pipe_config
->gmch_pfit
.pgm_ratios
= pfit_pgm_ratios
;
325 pipe_config
->gmch_pfit
.lvds_border_bits
= border
;
328 static int is_backlight_combination_mode(struct drm_device
*dev
)
330 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
333 return I915_READ(BLC_PWM_CTL2
) & BLM_COMBINATION_MODE
;
336 return I915_READ(BLC_PWM_CTL
) & BLM_LEGACY_MODE
;
341 static u32
pch_get_max_backlight(struct intel_connector
*connector
)
343 struct drm_device
*dev
= connector
->base
.dev
;
344 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
347 val
= I915_READ(BLC_PWM_PCH_CTL2
);
348 if (dev_priv
->regfile
.saveBLC_PWM_CTL2
== 0) {
349 dev_priv
->regfile
.saveBLC_PWM_CTL2
= val
;
350 } else if (val
== 0) {
351 val
= dev_priv
->regfile
.saveBLC_PWM_CTL2
;
352 I915_WRITE(BLC_PWM_PCH_CTL2
, val
);
360 static u32
i9xx_get_max_backlight(struct intel_connector
*connector
)
362 struct drm_device
*dev
= connector
->base
.dev
;
363 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
366 val
= I915_READ(BLC_PWM_CTL
);
367 if (dev_priv
->regfile
.saveBLC_PWM_CTL
== 0) {
368 dev_priv
->regfile
.saveBLC_PWM_CTL
= val
;
369 } else if (val
== 0) {
370 val
= dev_priv
->regfile
.saveBLC_PWM_CTL
;
371 I915_WRITE(BLC_PWM_CTL
, val
);
376 if (is_backlight_combination_mode(dev
))
382 static u32
i965_get_max_backlight(struct intel_connector
*connector
)
384 struct drm_device
*dev
= connector
->base
.dev
;
385 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
388 val
= I915_READ(BLC_PWM_CTL
);
389 if (dev_priv
->regfile
.saveBLC_PWM_CTL
== 0) {
390 dev_priv
->regfile
.saveBLC_PWM_CTL
= val
;
391 dev_priv
->regfile
.saveBLC_PWM_CTL2
= I915_READ(BLC_PWM_CTL2
);
392 } else if (val
== 0) {
393 val
= dev_priv
->regfile
.saveBLC_PWM_CTL
;
394 I915_WRITE(BLC_PWM_CTL
, val
);
395 I915_WRITE(BLC_PWM_CTL2
, dev_priv
->regfile
.saveBLC_PWM_CTL2
);
400 if (is_backlight_combination_mode(dev
))
406 static u32
_vlv_get_max_backlight(struct drm_device
*dev
, enum pipe pipe
)
408 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
411 val
= I915_READ(VLV_BLC_PWM_CTL(pipe
));
412 if (dev_priv
->regfile
.saveBLC_PWM_CTL
== 0) {
413 dev_priv
->regfile
.saveBLC_PWM_CTL
= val
;
414 dev_priv
->regfile
.saveBLC_PWM_CTL2
=
415 I915_READ(VLV_BLC_PWM_CTL2(pipe
));
416 } else if (val
== 0) {
417 val
= dev_priv
->regfile
.saveBLC_PWM_CTL
;
418 I915_WRITE(VLV_BLC_PWM_CTL(pipe
), val
);
419 I915_WRITE(VLV_BLC_PWM_CTL2(pipe
),
420 dev_priv
->regfile
.saveBLC_PWM_CTL2
);
431 static u32
vlv_get_max_backlight(struct intel_connector
*connector
)
433 struct drm_device
*dev
= connector
->base
.dev
;
434 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
436 return _vlv_get_max_backlight(dev
, pipe
);
439 static u32
intel_panel_get_max_backlight(struct intel_connector
*connector
)
441 struct drm_device
*dev
= connector
->base
.dev
;
442 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
445 WARN_ON_SMP(!spin_is_locked(&dev_priv
->backlight_lock
));
447 max
= dev_priv
->display
.get_max_backlight(connector
);
449 DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max
);
454 static int i915_panel_invert_brightness
;
455 MODULE_PARM_DESC(invert_brightness
, "Invert backlight brightness "
456 "(-1 force normal, 0 machine defaults, 1 force inversion), please "
457 "report PCI device ID, subsystem vendor and subsystem device ID "
458 "to dri-devel@lists.freedesktop.org, if your machine needs it. "
459 "It will then be included in an upcoming module version.");
460 module_param_named(invert_brightness
, i915_panel_invert_brightness
, int, 0600);
461 static u32
intel_panel_compute_brightness(struct intel_connector
*connector
,
464 struct drm_device
*dev
= connector
->base
.dev
;
465 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
466 struct intel_panel
*panel
= &connector
->panel
;
468 WARN_ON(panel
->backlight
.max
== 0);
470 if (i915_panel_invert_brightness
< 0)
473 if (i915_panel_invert_brightness
> 0 ||
474 dev_priv
->quirks
& QUIRK_INVERT_BRIGHTNESS
) {
475 return panel
->backlight
.max
- val
;
481 static u32
pch_get_backlight(struct intel_connector
*connector
)
483 struct drm_device
*dev
= connector
->base
.dev
;
484 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
486 return I915_READ(BLC_PWM_CPU_CTL
) & BACKLIGHT_DUTY_CYCLE_MASK
;
489 static u32
i9xx_get_backlight(struct intel_connector
*connector
)
491 struct drm_device
*dev
= connector
->base
.dev
;
492 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
493 struct intel_panel
*panel
= &connector
->panel
;
496 val
= I915_READ(BLC_PWM_CTL
) & BACKLIGHT_DUTY_CYCLE_MASK
;
497 if (INTEL_INFO(dev
)->gen
< 4)
500 if (panel
->backlight
.combination_mode
) {
503 pci_read_config_byte(dev
->pdev
, PCI_LBPC
, &lbpc
);
510 static u32
_vlv_get_backlight(struct drm_device
*dev
, enum pipe pipe
)
512 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
514 return I915_READ(VLV_BLC_PWM_CTL(pipe
)) & BACKLIGHT_DUTY_CYCLE_MASK
;
517 static u32
vlv_get_backlight(struct intel_connector
*connector
)
519 struct drm_device
*dev
= connector
->base
.dev
;
520 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
522 return _vlv_get_backlight(dev
, pipe
);
525 static u32
intel_panel_get_backlight(struct intel_connector
*connector
)
527 struct drm_device
*dev
= connector
->base
.dev
;
528 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
532 spin_lock_irqsave(&dev_priv
->backlight_lock
, flags
);
534 val
= dev_priv
->display
.get_backlight(connector
);
535 val
= intel_panel_compute_brightness(connector
, val
);
537 spin_unlock_irqrestore(&dev_priv
->backlight_lock
, flags
);
539 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val
);
543 static void pch_set_backlight(struct intel_connector
*connector
, u32 level
)
545 struct drm_device
*dev
= connector
->base
.dev
;
546 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
549 tmp
= I915_READ(BLC_PWM_CPU_CTL
) & ~BACKLIGHT_DUTY_CYCLE_MASK
;
550 I915_WRITE(BLC_PWM_CPU_CTL
, tmp
| level
);
553 static void i9xx_set_backlight(struct intel_connector
*connector
, u32 level
)
555 struct drm_device
*dev
= connector
->base
.dev
;
556 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
557 struct intel_panel
*panel
= &connector
->panel
;
560 WARN_ON(panel
->backlight
.max
== 0);
562 if (panel
->backlight
.combination_mode
) {
565 lbpc
= level
* 0xfe / panel
->backlight
.max
+ 1;
567 pci_write_config_byte(dev
->pdev
, PCI_LBPC
, lbpc
);
571 mask
= BACKLIGHT_DUTY_CYCLE_MASK
;
574 mask
= BACKLIGHT_DUTY_CYCLE_MASK_PNV
;
577 tmp
= I915_READ(BLC_PWM_CTL
) & ~mask
;
578 I915_WRITE(BLC_PWM_CTL
, tmp
| level
);
581 static void vlv_set_backlight(struct intel_connector
*connector
, u32 level
)
583 struct drm_device
*dev
= connector
->base
.dev
;
584 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
585 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
588 tmp
= I915_READ(VLV_BLC_PWM_CTL(pipe
)) & ~BACKLIGHT_DUTY_CYCLE_MASK
;
589 I915_WRITE(VLV_BLC_PWM_CTL(pipe
), tmp
| level
);
593 intel_panel_actually_set_backlight(struct intel_connector
*connector
, u32 level
)
595 struct drm_device
*dev
= connector
->base
.dev
;
596 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
598 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level
);
600 level
= intel_panel_compute_brightness(connector
, level
);
601 dev_priv
->display
.set_backlight(connector
, level
);
604 /* set backlight brightness to level in range [0..max] */
605 void intel_panel_set_backlight(struct intel_connector
*connector
, u32 level
,
608 struct drm_device
*dev
= connector
->base
.dev
;
609 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
610 struct intel_panel
*panel
= &connector
->panel
;
611 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
615 if (pipe
== INVALID_PIPE
)
618 spin_lock_irqsave(&dev_priv
->backlight_lock
, flags
);
620 WARN_ON(panel
->backlight
.max
== 0);
622 /* scale to hardware max, but be careful to not overflow */
623 freq
= panel
->backlight
.max
;
625 level
= level
* freq
/ max
;
627 level
= freq
/ max
* level
;
629 panel
->backlight
.level
= level
;
630 if (panel
->backlight
.device
)
631 panel
->backlight
.device
->props
.brightness
= level
;
633 if (panel
->backlight
.enabled
)
634 intel_panel_actually_set_backlight(connector
, level
);
636 spin_unlock_irqrestore(&dev_priv
->backlight_lock
, flags
);
639 static void pch_disable_backlight(struct intel_connector
*connector
)
641 struct drm_device
*dev
= connector
->base
.dev
;
642 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
645 intel_panel_actually_set_backlight(connector
, 0);
647 tmp
= I915_READ(BLC_PWM_CPU_CTL2
);
648 I915_WRITE(BLC_PWM_CPU_CTL2
, tmp
& ~BLM_PWM_ENABLE
);
650 tmp
= I915_READ(BLC_PWM_PCH_CTL1
);
651 I915_WRITE(BLC_PWM_PCH_CTL1
, tmp
& ~BLM_PCH_PWM_ENABLE
);
654 static void i9xx_disable_backlight(struct intel_connector
*connector
)
656 intel_panel_actually_set_backlight(connector
, 0);
659 static void i965_disable_backlight(struct intel_connector
*connector
)
661 struct drm_device
*dev
= connector
->base
.dev
;
662 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
665 intel_panel_actually_set_backlight(connector
, 0);
667 tmp
= I915_READ(BLC_PWM_CTL2
);
668 I915_WRITE(BLC_PWM_CTL2
, tmp
& ~BLM_PWM_ENABLE
);
671 static void vlv_disable_backlight(struct intel_connector
*connector
)
673 struct drm_device
*dev
= connector
->base
.dev
;
674 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
675 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
678 intel_panel_actually_set_backlight(connector
, 0);
680 tmp
= I915_READ(VLV_BLC_PWM_CTL2(pipe
));
681 I915_WRITE(VLV_BLC_PWM_CTL2(pipe
), tmp
& ~BLM_PWM_ENABLE
);
684 void intel_panel_disable_backlight(struct intel_connector
*connector
)
686 struct drm_device
*dev
= connector
->base
.dev
;
687 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
688 struct intel_panel
*panel
= &connector
->panel
;
689 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
692 if (pipe
== INVALID_PIPE
)
696 * Do not disable backlight on the vgaswitcheroo path. When switching
697 * away from i915, the other client may depend on i915 to handle the
698 * backlight. This will leave the backlight on unnecessarily when
699 * another client is not activated.
701 if (dev
->switch_power_state
== DRM_SWITCH_POWER_CHANGING
) {
702 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
706 spin_lock_irqsave(&dev_priv
->backlight_lock
, flags
);
708 panel
->backlight
.enabled
= false;
709 dev_priv
->display
.disable_backlight(connector
);
711 spin_unlock_irqrestore(&dev_priv
->backlight_lock
, flags
);
714 static void pch_enable_backlight(struct intel_connector
*connector
)
716 struct drm_device
*dev
= connector
->base
.dev
;
717 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
718 struct intel_panel
*panel
= &connector
->panel
;
719 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
720 enum transcoder cpu_transcoder
=
721 intel_pipe_to_cpu_transcoder(dev_priv
, pipe
);
722 u32 cpu_ctl2
, pch_ctl1
, pch_ctl2
;
724 cpu_ctl2
= I915_READ(BLC_PWM_CPU_CTL2
);
725 if (cpu_ctl2
& BLM_PWM_ENABLE
) {
726 WARN(1, "cpu backlight already enabled\n");
727 cpu_ctl2
&= ~BLM_PWM_ENABLE
;
728 I915_WRITE(BLC_PWM_CPU_CTL2
, cpu_ctl2
);
731 pch_ctl1
= I915_READ(BLC_PWM_PCH_CTL1
);
732 if (pch_ctl1
& BLM_PCH_PWM_ENABLE
) {
733 DRM_DEBUG_KMS("pch backlight already enabled\n");
734 pch_ctl1
&= ~BLM_PCH_PWM_ENABLE
;
735 I915_WRITE(BLC_PWM_PCH_CTL1
, pch_ctl1
);
738 if (cpu_transcoder
== TRANSCODER_EDP
)
739 cpu_ctl2
= BLM_TRANSCODER_EDP
;
741 cpu_ctl2
= BLM_PIPE(cpu_transcoder
);
742 I915_WRITE(BLC_PWM_CPU_CTL2
, cpu_ctl2
);
743 POSTING_READ(BLC_PWM_CPU_CTL2
);
744 I915_WRITE(BLC_PWM_CPU_CTL2
, cpu_ctl2
| BLM_PWM_ENABLE
);
746 /* This won't stick until the above enable. */
747 intel_panel_actually_set_backlight(connector
, panel
->backlight
.level
);
749 pch_ctl2
= panel
->backlight
.max
<< 16;
750 I915_WRITE(BLC_PWM_PCH_CTL2
, pch_ctl2
);
752 /* XXX: transitional */
753 if (dev_priv
->quirks
& QUIRK_NO_PCH_PWM_ENABLE
)
757 if (panel
->backlight
.active_low_pwm
)
758 pch_ctl1
|= BLM_PCH_POLARITY
;
759 I915_WRITE(BLC_PWM_PCH_CTL1
, pch_ctl1
);
760 POSTING_READ(BLC_PWM_PCH_CTL1
);
761 I915_WRITE(BLC_PWM_PCH_CTL1
, pch_ctl1
| BLM_PCH_PWM_ENABLE
);
764 static void i9xx_enable_backlight(struct intel_connector
*connector
)
766 struct drm_device
*dev
= connector
->base
.dev
;
767 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
768 struct intel_panel
*panel
= &connector
->panel
;
771 ctl
= I915_READ(BLC_PWM_CTL
);
772 if (ctl
& BACKLIGHT_DUTY_CYCLE_MASK_PNV
) {
773 WARN(1, "backlight already enabled\n");
774 I915_WRITE(BLC_PWM_CTL
, 0);
777 freq
= panel
->backlight
.max
;
778 if (panel
->backlight
.combination_mode
)
782 if (IS_GEN2(dev
) && panel
->backlight
.combination_mode
)
783 ctl
|= BLM_LEGACY_MODE
;
784 if (IS_PINEVIEW(dev
) && panel
->backlight
.active_low_pwm
)
785 ctl
|= BLM_POLARITY_PNV
;
787 I915_WRITE(BLC_PWM_CTL
, ctl
);
788 POSTING_READ(BLC_PWM_CTL
);
790 /* XXX: combine this into above write? */
791 intel_panel_actually_set_backlight(connector
, panel
->backlight
.level
);
794 static void i965_enable_backlight(struct intel_connector
*connector
)
796 struct drm_device
*dev
= connector
->base
.dev
;
797 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
798 struct intel_panel
*panel
= &connector
->panel
;
799 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
802 ctl2
= I915_READ(BLC_PWM_CTL2
);
803 if (ctl2
& BLM_PWM_ENABLE
) {
804 WARN(1, "backlight already enabled\n");
805 ctl2
&= ~BLM_PWM_ENABLE
;
806 I915_WRITE(BLC_PWM_CTL2
, ctl2
);
809 freq
= panel
->backlight
.max
;
810 if (panel
->backlight
.combination_mode
)
814 I915_WRITE(BLC_PWM_CTL
, ctl
);
816 /* XXX: combine this into above write? */
817 intel_panel_actually_set_backlight(connector
, panel
->backlight
.level
);
819 ctl2
= BLM_PIPE(pipe
);
820 if (panel
->backlight
.combination_mode
)
821 ctl2
|= BLM_COMBINATION_MODE
;
822 if (panel
->backlight
.active_low_pwm
)
823 ctl2
|= BLM_POLARITY_I965
;
824 I915_WRITE(BLC_PWM_CTL2
, ctl2
);
825 POSTING_READ(BLC_PWM_CTL2
);
826 I915_WRITE(BLC_PWM_CTL2
, ctl2
| BLM_PWM_ENABLE
);
829 static void vlv_enable_backlight(struct intel_connector
*connector
)
831 struct drm_device
*dev
= connector
->base
.dev
;
832 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
833 struct intel_panel
*panel
= &connector
->panel
;
834 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
837 ctl2
= I915_READ(VLV_BLC_PWM_CTL2(pipe
));
838 if (ctl2
& BLM_PWM_ENABLE
) {
839 WARN(1, "backlight already enabled\n");
840 ctl2
&= ~BLM_PWM_ENABLE
;
841 I915_WRITE(VLV_BLC_PWM_CTL2(pipe
), ctl2
);
844 ctl
= panel
->backlight
.max
<< 16;
845 I915_WRITE(VLV_BLC_PWM_CTL(pipe
), ctl
);
847 /* XXX: combine this into above write? */
848 intel_panel_actually_set_backlight(connector
, panel
->backlight
.level
);
851 if (panel
->backlight
.active_low_pwm
)
852 ctl2
|= BLM_POLARITY_I965
;
853 I915_WRITE(VLV_BLC_PWM_CTL2(pipe
), ctl2
);
854 POSTING_READ(VLV_BLC_PWM_CTL2(pipe
));
855 I915_WRITE(VLV_BLC_PWM_CTL2(pipe
), ctl2
| BLM_PWM_ENABLE
);
858 void intel_panel_enable_backlight(struct intel_connector
*connector
)
860 struct drm_device
*dev
= connector
->base
.dev
;
861 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
862 struct intel_panel
*panel
= &connector
->panel
;
863 enum pipe pipe
= intel_get_pipe_from_connector(connector
);
866 if (pipe
== INVALID_PIPE
)
869 DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe
));
871 spin_lock_irqsave(&dev_priv
->backlight_lock
, flags
);
873 /* XXX: transitional, call to make sure freq is set */
874 intel_panel_get_max_backlight(connector
);
876 WARN_ON(panel
->backlight
.max
== 0);
878 if (panel
->backlight
.level
== 0) {
879 panel
->backlight
.level
= panel
->backlight
.max
;
880 if (panel
->backlight
.device
)
881 panel
->backlight
.device
->props
.brightness
=
882 panel
->backlight
.level
;
885 dev_priv
->display
.enable_backlight(connector
);
886 panel
->backlight
.enabled
= true;
888 spin_unlock_irqrestore(&dev_priv
->backlight_lock
, flags
);
891 enum drm_connector_status
892 intel_panel_detect(struct drm_device
*dev
)
894 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
896 /* Assume that the BIOS does not lie through the OpRegion... */
897 if (!i915_panel_ignore_lid
&& dev_priv
->opregion
.lid_state
) {
898 return ioread32(dev_priv
->opregion
.lid_state
) & 0x1 ?
899 connector_status_connected
:
900 connector_status_disconnected
;
903 switch (i915_panel_ignore_lid
) {
905 return connector_status_connected
;
907 return connector_status_disconnected
;
909 return connector_status_unknown
;
913 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
914 static int intel_backlight_device_update_status(struct backlight_device
*bd
)
916 struct intel_connector
*connector
= bl_get_data(bd
);
917 struct drm_device
*dev
= connector
->base
.dev
;
919 mutex_lock(&dev
->mode_config
.mutex
);
920 DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
921 bd
->props
.brightness
, bd
->props
.max_brightness
);
922 intel_panel_set_backlight(connector
, bd
->props
.brightness
,
923 bd
->props
.max_brightness
);
924 mutex_unlock(&dev
->mode_config
.mutex
);
928 static int intel_backlight_device_get_brightness(struct backlight_device
*bd
)
930 struct intel_connector
*connector
= bl_get_data(bd
);
931 struct drm_device
*dev
= connector
->base
.dev
;
934 mutex_lock(&dev
->mode_config
.mutex
);
935 ret
= intel_panel_get_backlight(connector
);
936 mutex_unlock(&dev
->mode_config
.mutex
);
941 static const struct backlight_ops intel_backlight_device_ops
= {
942 .update_status
= intel_backlight_device_update_status
,
943 .get_brightness
= intel_backlight_device_get_brightness
,
946 static int intel_backlight_device_register(struct intel_connector
*connector
)
948 struct intel_panel
*panel
= &connector
->panel
;
949 struct backlight_properties props
;
951 if (WARN_ON(panel
->backlight
.device
))
954 BUG_ON(panel
->backlight
.max
== 0);
956 memset(&props
, 0, sizeof(props
));
957 props
.type
= BACKLIGHT_RAW
;
958 props
.brightness
= panel
->backlight
.level
;
959 props
.max_brightness
= panel
->backlight
.max
;
962 * Note: using the same name independent of the connector prevents
963 * registration of multiple backlight devices in the driver.
965 panel
->backlight
.device
=
966 backlight_device_register("intel_backlight",
967 connector
->base
.kdev
,
969 &intel_backlight_device_ops
, &props
);
971 if (IS_ERR(panel
->backlight
.device
)) {
972 DRM_ERROR("Failed to register backlight: %ld\n",
973 PTR_ERR(panel
->backlight
.device
));
974 panel
->backlight
.device
= NULL
;
980 static void intel_backlight_device_unregister(struct intel_connector
*connector
)
982 struct intel_panel
*panel
= &connector
->panel
;
984 if (panel
->backlight
.device
) {
985 backlight_device_unregister(panel
->backlight
.device
);
986 panel
->backlight
.device
= NULL
;
989 #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
990 static int intel_backlight_device_register(struct intel_connector
*connector
)
994 static void intel_backlight_device_unregister(struct intel_connector
*connector
)
997 #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1000 * Note: The setup hooks can't assume pipe is set!
1002 * XXX: Query mode clock or hardware clock and program PWM modulation frequency
1003 * appropriately when it's 0. Use VBT and/or sane defaults.
1005 static int pch_setup_backlight(struct intel_connector
*connector
)
1007 struct drm_device
*dev
= connector
->base
.dev
;
1008 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1009 struct intel_panel
*panel
= &connector
->panel
;
1010 u32 cpu_ctl2
, pch_ctl1
, pch_ctl2
, val
;
1012 pch_ctl1
= I915_READ(BLC_PWM_PCH_CTL1
);
1013 panel
->backlight
.active_low_pwm
= pch_ctl1
& BLM_PCH_POLARITY
;
1015 pch_ctl2
= I915_READ(BLC_PWM_PCH_CTL2
);
1016 panel
->backlight
.max
= pch_ctl2
>> 16;
1017 if (!panel
->backlight
.max
)
1020 val
= pch_get_backlight(connector
);
1021 panel
->backlight
.level
= intel_panel_compute_brightness(connector
, val
);
1023 cpu_ctl2
= I915_READ(BLC_PWM_CPU_CTL2
);
1024 panel
->backlight
.enabled
= (cpu_ctl2
& BLM_PWM_ENABLE
) &&
1025 (pch_ctl1
& BLM_PCH_PWM_ENABLE
) && panel
->backlight
.level
!= 0;
1030 static int i9xx_setup_backlight(struct intel_connector
*connector
)
1032 struct drm_device
*dev
= connector
->base
.dev
;
1033 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1034 struct intel_panel
*panel
= &connector
->panel
;
1037 ctl
= I915_READ(BLC_PWM_CTL
);
1040 panel
->backlight
.combination_mode
= ctl
& BLM_LEGACY_MODE
;
1042 if (IS_PINEVIEW(dev
))
1043 panel
->backlight
.active_low_pwm
= ctl
& BLM_POLARITY_PNV
;
1045 panel
->backlight
.max
= ctl
>> 17;
1046 if (panel
->backlight
.combination_mode
)
1047 panel
->backlight
.max
*= 0xff;
1049 if (!panel
->backlight
.max
)
1052 val
= i9xx_get_backlight(connector
);
1053 panel
->backlight
.level
= intel_panel_compute_brightness(connector
, val
);
1055 panel
->backlight
.enabled
= panel
->backlight
.level
!= 0;
1060 static int i965_setup_backlight(struct intel_connector
*connector
)
1062 struct drm_device
*dev
= connector
->base
.dev
;
1063 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1064 struct intel_panel
*panel
= &connector
->panel
;
1067 ctl2
= I915_READ(BLC_PWM_CTL2
);
1068 panel
->backlight
.combination_mode
= ctl2
& BLM_COMBINATION_MODE
;
1069 panel
->backlight
.active_low_pwm
= ctl2
& BLM_POLARITY_I965
;
1071 ctl
= I915_READ(BLC_PWM_CTL
);
1072 panel
->backlight
.max
= ctl
>> 16;
1073 if (panel
->backlight
.combination_mode
)
1074 panel
->backlight
.max
*= 0xff;
1076 if (!panel
->backlight
.max
)
1079 val
= i9xx_get_backlight(connector
);
1080 panel
->backlight
.level
= intel_panel_compute_brightness(connector
, val
);
1082 panel
->backlight
.enabled
= (ctl2
& BLM_PWM_ENABLE
) &&
1083 panel
->backlight
.level
!= 0;
1088 static int vlv_setup_backlight(struct intel_connector
*connector
)
1090 struct drm_device
*dev
= connector
->base
.dev
;
1091 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1092 struct intel_panel
*panel
= &connector
->panel
;
1096 for_each_pipe(pipe
) {
1097 u32 cur_val
= I915_READ(VLV_BLC_PWM_CTL(pipe
));
1099 /* Skip if the modulation freq is already set */
1100 if (cur_val
& ~BACKLIGHT_DUTY_CYCLE_MASK
)
1103 cur_val
&= BACKLIGHT_DUTY_CYCLE_MASK
;
1104 I915_WRITE(VLV_BLC_PWM_CTL(pipe
), (0xf42 << 16) |
1108 ctl2
= I915_READ(VLV_BLC_PWM_CTL2(PIPE_A
));
1109 panel
->backlight
.active_low_pwm
= ctl2
& BLM_POLARITY_I965
;
1111 ctl
= I915_READ(VLV_BLC_PWM_CTL(PIPE_A
));
1112 panel
->backlight
.max
= ctl
>> 16;
1113 if (!panel
->backlight
.max
)
1116 val
= _vlv_get_backlight(dev
, PIPE_A
);
1117 panel
->backlight
.level
= intel_panel_compute_brightness(connector
, val
);
1119 panel
->backlight
.enabled
= (ctl2
& BLM_PWM_ENABLE
) &&
1120 panel
->backlight
.level
!= 0;
1125 int intel_panel_setup_backlight(struct drm_connector
*connector
)
1127 struct drm_device
*dev
= connector
->dev
;
1128 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1129 struct intel_connector
*intel_connector
= to_intel_connector(connector
);
1130 struct intel_panel
*panel
= &intel_connector
->panel
;
1131 unsigned long flags
;
1134 /* set level and max in panel struct */
1135 spin_lock_irqsave(&dev_priv
->backlight_lock
, flags
);
1136 ret
= dev_priv
->display
.setup_backlight(intel_connector
);
1137 spin_unlock_irqrestore(&dev_priv
->backlight_lock
, flags
);
1140 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1141 drm_get_connector_name(connector
));
1145 intel_backlight_device_register(intel_connector
);
1147 panel
->backlight
.present
= true;
1149 DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
1150 "sysfs interface %sregistered\n",
1151 panel
->backlight
.enabled
? "enabled" : "disabled",
1152 panel
->backlight
.level
, panel
->backlight
.max
,
1153 panel
->backlight
.device
? "" : "not ");
1158 void intel_panel_destroy_backlight(struct drm_connector
*connector
)
1160 struct intel_connector
*intel_connector
= to_intel_connector(connector
);
1161 struct intel_panel
*panel
= &intel_connector
->panel
;
1163 panel
->backlight
.present
= false;
1164 intel_backlight_device_unregister(intel_connector
);
1167 /* Set up chip specific backlight functions */
1168 void intel_panel_init_backlight_funcs(struct drm_device
*dev
)
1170 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
1172 if (HAS_PCH_SPLIT(dev
)) {
1173 dev_priv
->display
.setup_backlight
= pch_setup_backlight
;
1174 dev_priv
->display
.enable_backlight
= pch_enable_backlight
;
1175 dev_priv
->display
.disable_backlight
= pch_disable_backlight
;
1176 dev_priv
->display
.set_backlight
= pch_set_backlight
;
1177 dev_priv
->display
.get_backlight
= pch_get_backlight
;
1178 dev_priv
->display
.get_max_backlight
= pch_get_max_backlight
;
1179 } else if (IS_VALLEYVIEW(dev
)) {
1180 dev_priv
->display
.setup_backlight
= vlv_setup_backlight
;
1181 dev_priv
->display
.enable_backlight
= vlv_enable_backlight
;
1182 dev_priv
->display
.disable_backlight
= vlv_disable_backlight
;
1183 dev_priv
->display
.set_backlight
= vlv_set_backlight
;
1184 dev_priv
->display
.get_backlight
= vlv_get_backlight
;
1185 dev_priv
->display
.get_max_backlight
= vlv_get_max_backlight
;
1186 } else if (IS_GEN4(dev
)) {
1187 dev_priv
->display
.setup_backlight
= i965_setup_backlight
;
1188 dev_priv
->display
.enable_backlight
= i965_enable_backlight
;
1189 dev_priv
->display
.disable_backlight
= i965_disable_backlight
;
1190 dev_priv
->display
.set_backlight
= i9xx_set_backlight
;
1191 dev_priv
->display
.get_backlight
= i9xx_get_backlight
;
1192 dev_priv
->display
.get_max_backlight
= i965_get_max_backlight
;
1194 dev_priv
->display
.setup_backlight
= i9xx_setup_backlight
;
1195 dev_priv
->display
.enable_backlight
= i9xx_enable_backlight
;
1196 dev_priv
->display
.disable_backlight
= i9xx_disable_backlight
;
1197 dev_priv
->display
.set_backlight
= i9xx_set_backlight
;
1198 dev_priv
->display
.get_backlight
= i9xx_get_backlight
;
1199 dev_priv
->display
.get_max_backlight
= i9xx_get_max_backlight
;
1203 int intel_panel_init(struct intel_panel
*panel
,
1204 struct drm_display_mode
*fixed_mode
)
1206 panel
->fixed_mode
= fixed_mode
;
1211 void intel_panel_fini(struct intel_panel
*panel
)
1213 struct intel_connector
*intel_connector
=
1214 container_of(panel
, struct intel_connector
, panel
);
1216 if (panel
->fixed_mode
)
1217 drm_mode_destroy(intel_connector
->base
.dev
, panel
->fixed_mode
);