]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/i915/intel_panel.c
drm/i915: vlv does not have pipe field in backlight registers
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / i915 / intel_panel.c
CommitLineData
1d8e1c75
CW
1/*
2 * Copyright © 2006-2010 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
4 *
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:
11 *
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
14 * Software.
15 *
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.
23 *
24 * Authors:
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>
29 */
30
a70491cc
JP
31#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
7bd90909 33#include <linux/moduleparam.h>
1d8e1c75
CW
34#include "intel_drv.h"
35
ba3820ad
TI
36#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
37
1d8e1c75 38void
4c6df4b4 39intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
1d8e1c75
CW
40 struct drm_display_mode *adjusted_mode)
41{
4c6df4b4 42 drm_mode_copy(adjusted_mode, fixed_mode);
a52690e4
ID
43
44 drm_mode_set_crtcinfo(adjusted_mode, 0);
1d8e1c75
CW
45}
46
47/* adjusted_mode has been preset to be the panel's fixed mode */
48void
b074cec8
JB
49intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
50 struct intel_crtc_config *pipe_config,
51 int fitting_mode)
1d8e1c75 52{
37327abd 53 struct drm_display_mode *adjusted_mode;
1d8e1c75
CW
54 int x, y, width, height;
55
b074cec8
JB
56 adjusted_mode = &pipe_config->adjusted_mode;
57
1d8e1c75
CW
58 x = y = width = height = 0;
59
60 /* Native modes don't need fitting */
37327abd
VS
61 if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
62 adjusted_mode->vdisplay == pipe_config->pipe_src_h)
1d8e1c75
CW
63 goto done;
64
65 switch (fitting_mode) {
66 case DRM_MODE_SCALE_CENTER:
37327abd
VS
67 width = pipe_config->pipe_src_w;
68 height = pipe_config->pipe_src_h;
1d8e1c75
CW
69 x = (adjusted_mode->hdisplay - width + 1)/2;
70 y = (adjusted_mode->vdisplay - height + 1)/2;
71 break;
72
73 case DRM_MODE_SCALE_ASPECT:
74 /* Scale but preserve the aspect ratio */
75 {
9084e7d2
DV
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;
1d8e1c75 80 if (scaled_width > scaled_height) { /* pillar */
37327abd 81 width = scaled_height / pipe_config->pipe_src_h;
302983e9 82 if (width & 1)
0206e353 83 width++;
1d8e1c75
CW
84 x = (adjusted_mode->hdisplay - width + 1) / 2;
85 y = 0;
86 height = adjusted_mode->vdisplay;
87 } else if (scaled_width < scaled_height) { /* letter */
37327abd 88 height = scaled_width / pipe_config->pipe_src_w;
302983e9
AJ
89 if (height & 1)
90 height++;
1d8e1c75
CW
91 y = (adjusted_mode->vdisplay - height + 1) / 2;
92 x = 0;
93 width = adjusted_mode->hdisplay;
94 } else {
95 x = y = 0;
96 width = adjusted_mode->hdisplay;
97 height = adjusted_mode->vdisplay;
98 }
99 }
100 break;
101
1d8e1c75
CW
102 case DRM_MODE_SCALE_FULLSCREEN:
103 x = y = 0;
104 width = adjusted_mode->hdisplay;
105 height = adjusted_mode->vdisplay;
106 break;
ab3e67f4
JB
107
108 default:
109 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
110 return;
1d8e1c75
CW
111 }
112
113done:
b074cec8
JB
114 pipe_config->pch_pfit.pos = (x << 16) | y;
115 pipe_config->pch_pfit.size = (width << 16) | height;
fd4daa9c 116 pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
1d8e1c75 117}
a9573556 118
2dd24552
JB
119static void
120centre_horizontally(struct drm_display_mode *mode,
121 int width)
122{
123 u32 border, sync_pos, blank_width, sync_width;
124
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;
129
130 border = (mode->hdisplay - width + 1) / 2;
131 border += border & 1; /* make the border even */
132
133 mode->crtc_hdisplay = width;
134 mode->crtc_hblank_start = width + border;
135 mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
136
137 mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
138 mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
139}
140
141static void
142centre_vertically(struct drm_display_mode *mode,
143 int height)
144{
145 u32 border, sync_pos, blank_width, sync_width;
146
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;
151
152 border = (mode->vdisplay - height + 1) / 2;
153
154 mode->crtc_vdisplay = height;
155 mode->crtc_vblank_start = height + border;
156 mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
157
158 mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
159 mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
160}
161
162static inline u32 panel_fitter_scaling(u32 source, u32 target)
163{
164 /*
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.
168 */
169#define ACCURACY 12
170#define FACTOR (1 << ACCURACY)
171 u32 ratio = source * FACTOR / target;
172 return (FACTOR * ratio + FACTOR/2) / FACTOR;
173}
174
9084e7d2
DV
175static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
176 u32 *pfit_control)
177{
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;
183
184 /* 965+ is easy, it does everything in hw */
185 if (scaled_width > scaled_height)
186 *pfit_control |= PFIT_ENABLE |
187 PFIT_SCALING_PILLAR;
188 else if (scaled_width < scaled_height)
189 *pfit_control |= PFIT_ENABLE |
190 PFIT_SCALING_LETTER;
191 else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
192 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
193}
194
195static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
196 u32 *pfit_control, u32 *pfit_pgm_ratios,
197 u32 *border)
198{
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;
204 u32 bits;
205
206 /*
207 * For earlier chips we have to calculate the scaling
208 * ratio by hand and program it into the
209 * PFIT_PGM_RATIO register
210 */
211 if (scaled_width > scaled_height) { /* pillar */
212 centre_horizontally(adjusted_mode,
213 scaled_height /
214 pipe_config->pipe_src_h);
215
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);
220
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);
226 }
227 } else if (scaled_width < scaled_height) { /* letter */
228 centre_vertically(adjusted_mode,
229 scaled_width /
230 pipe_config->pipe_src_w);
231
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);
236
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);
242 }
243 } else {
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);
249 }
250}
251
2dd24552
JB
252void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
253 struct intel_crtc_config *pipe_config,
254 int fitting_mode)
255{
256 struct drm_device *dev = intel_crtc->base.dev;
2dd24552 257 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
37327abd 258 struct drm_display_mode *adjusted_mode;
2dd24552 259
2dd24552
JB
260 adjusted_mode = &pipe_config->adjusted_mode;
261
262 /* Native modes don't need fitting */
37327abd
VS
263 if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
264 adjusted_mode->vdisplay == pipe_config->pipe_src_h)
2dd24552
JB
265 goto out;
266
267 switch (fitting_mode) {
268 case DRM_MODE_SCALE_CENTER:
269 /*
270 * For centered modes, we have to calculate border widths &
271 * heights and modify the values programmed into the CRTC.
272 */
37327abd
VS
273 centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
274 centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
2dd24552
JB
275 border = LVDS_BORDER_ENABLE;
276 break;
277 case DRM_MODE_SCALE_ASPECT:
278 /* Scale but preserve the aspect ratio */
9084e7d2
DV
279 if (INTEL_INFO(dev)->gen >= 4)
280 i965_scale_aspect(pipe_config, &pfit_control);
281 else
282 i9xx_scale_aspect(pipe_config, &pfit_control,
283 &pfit_pgm_ratios, &border);
2dd24552 284 break;
2dd24552
JB
285 case DRM_MODE_SCALE_FULLSCREEN:
286 /*
287 * Full scaling, even if it changes the aspect ratio.
288 * Fortunately this is all done for us in hw.
289 */
37327abd
VS
290 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
291 pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
2dd24552
JB
292 pfit_control |= PFIT_ENABLE;
293 if (INTEL_INFO(dev)->gen >= 4)
294 pfit_control |= PFIT_SCALING_AUTO;
295 else
296 pfit_control |= (VERT_AUTO_SCALE |
297 VERT_INTERP_BILINEAR |
298 HORIZ_AUTO_SCALE |
299 HORIZ_INTERP_BILINEAR);
300 }
301 break;
ab3e67f4
JB
302 default:
303 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
304 return;
2dd24552
JB
305 }
306
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) |
311 PFIT_FILTER_FUZZY);
312
313out:
314 if ((pfit_control & PFIT_ENABLE) == 0) {
315 pfit_control = 0;
316 pfit_pgm_ratios = 0;
317 }
318
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;
322
2deefda5
DV
323 pipe_config->gmch_pfit.control = pfit_control;
324 pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
68fc8742 325 pipe_config->gmch_pfit.lvds_border_bits = border;
2dd24552
JB
326}
327
ba3820ad
TI
328static int is_backlight_combination_mode(struct drm_device *dev)
329{
330 struct drm_i915_private *dev_priv = dev->dev_private;
331
d9c638d5 332 if (IS_GEN4(dev))
ba3820ad
TI
333 return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
334
335 if (IS_GEN2(dev))
336 return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
337
338 return 0;
339}
340
7bd688cd 341static u32 pch_get_max_backlight(struct intel_connector *connector)
0b0b053a 342{
7bd688cd 343 struct drm_device *dev = connector->base.dev;
bfd7590d 344 struct drm_i915_private *dev_priv = dev->dev_private;
0b0b053a
CW
345 u32 val;
346
7bd688cd
JN
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);
353 }
8ba2d185 354
7bd688cd 355 val >>= 16;
0b0b053a 356
7bd688cd
JN
357 return val;
358}
07bf139b 359
7bd688cd
JN
360static u32 i9xx_get_max_backlight(struct intel_connector *connector)
361{
362 struct drm_device *dev = connector->base.dev;
363 struct drm_i915_private *dev_priv = dev->dev_private;
364 u32 val;
365
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);
0b0b053a
CW
372 }
373
7bd688cd
JN
374 val >>= 17;
375
376 if (is_backlight_combination_mode(dev))
377 val *= 0xff;
378
0b0b053a
CW
379 return val;
380}
381
7bd688cd 382static u32 i965_get_max_backlight(struct intel_connector *connector)
a9573556 383{
7bd688cd
JN
384 struct drm_device *dev = connector->base.dev;
385 struct drm_i915_private *dev_priv = dev->dev_private;
386 u32 val;
387
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);
396 }
a9573556 397
7bd688cd 398 val >>= 16;
0b0b053a 399
7bd688cd
JN
400 if (is_backlight_combination_mode(dev))
401 val *= 0xff;
402
403 return val;
404}
405
406static u32 _vlv_get_max_backlight(struct drm_device *dev, enum pipe pipe)
407{
408 struct drm_i915_private *dev_priv = dev->dev_private;
409 u32 val;
ba3820ad 410
7bd688cd
JN
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);
a9573556
CW
421 }
422
7bd688cd
JN
423 if (!val)
424 val = 0x0f42ffff;
425
426 val >>= 16;
427
428 return val;
429}
430
431static u32 vlv_get_max_backlight(struct intel_connector *connector)
432{
433 struct drm_device *dev = connector->base.dev;
434 enum pipe pipe = intel_get_pipe_from_connector(connector);
435
436 return _vlv_get_max_backlight(dev, pipe);
437}
438
439/* XXX: query mode clock or hardware clock and program max PWM appropriately
440 * when it's 0.
441 */
442static u32 intel_panel_get_max_backlight(struct intel_connector *connector)
443{
444 struct drm_device *dev = connector->base.dev;
445 struct drm_i915_private *dev_priv = dev->dev_private;
446 u32 max;
447
448 WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock));
449
450 max = dev_priv->display.get_max_backlight(connector);
451
a9573556 452 DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
d6540632 453
a9573556
CW
454 return max;
455}
456
4dca20ef
CE
457static int i915_panel_invert_brightness;
458MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
459 "(-1 force normal, 0 machine defaults, 1 force inversion), please "
7bd90909
CE
460 "report PCI device ID, subsystem vendor and subsystem device ID "
461 "to dri-devel@lists.freedesktop.org, if your machine needs it. "
462 "It will then be included in an upcoming module version.");
4dca20ef 463module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
7bd688cd
JN
464static u32 intel_panel_compute_brightness(struct intel_connector *connector,
465 u32 val)
7bd90909 466{
7bd688cd 467 struct drm_device *dev = connector->base.dev;
4dca20ef
CE
468 struct drm_i915_private *dev_priv = dev->dev_private;
469
470 if (i915_panel_invert_brightness < 0)
471 return val;
472
473 if (i915_panel_invert_brightness > 0 ||
d6540632 474 dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
7bd688cd 475 u32 max = intel_panel_get_max_backlight(connector);
d6540632
JN
476 if (max)
477 return max - val;
478 }
7bd90909
CE
479
480 return val;
481}
482
7bd688cd 483static u32 pch_get_backlight(struct intel_connector *connector)
a9573556 484{
7bd688cd 485 struct drm_device *dev = connector->base.dev;
a9573556 486 struct drm_i915_private *dev_priv = dev->dev_private;
8ba2d185 487
7bd688cd
JN
488 return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
489}
a9573556 490
7bd688cd
JN
491static u32 i9xx_get_backlight(struct intel_connector *connector)
492{
493 struct drm_device *dev = connector->base.dev;
494 struct drm_i915_private *dev_priv = dev->dev_private;
495 u32 val;
07bf139b 496
7bd688cd
JN
497 val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
498 if (INTEL_INFO(dev)->gen < 4)
499 val >>= 1;
ba3820ad 500
7bd688cd
JN
501 if (is_backlight_combination_mode(dev)) {
502 u8 lbpc;
ba3820ad 503
7bd688cd
JN
504 pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
505 val *= lbpc;
a9573556
CW
506 }
507
7bd688cd
JN
508 return val;
509}
510
511static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
512{
513 struct drm_i915_private *dev_priv = dev->dev_private;
514
515 return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
516}
517
518static u32 vlv_get_backlight(struct intel_connector *connector)
519{
520 struct drm_device *dev = connector->base.dev;
521 enum pipe pipe = intel_get_pipe_from_connector(connector);
522
523 return _vlv_get_backlight(dev, pipe);
524}
525
526static u32 intel_panel_get_backlight(struct intel_connector *connector)
527{
528 struct drm_device *dev = connector->base.dev;
529 struct drm_i915_private *dev_priv = dev->dev_private;
530 u32 val;
531 unsigned long flags;
532
533 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
534
535 val = dev_priv->display.get_backlight(connector);
536 val = intel_panel_compute_brightness(connector, val);
8ba2d185 537
58c68779 538 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
8ba2d185 539
a9573556
CW
540 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
541 return val;
542}
543
7bd688cd 544static void pch_set_backlight(struct intel_connector *connector, u32 level)
a9573556 545{
7bd688cd 546 struct drm_device *dev = connector->base.dev;
a9573556 547 struct drm_i915_private *dev_priv = dev->dev_private;
7bd688cd
JN
548 u32 tmp;
549
550 tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
551 I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
a9573556
CW
552}
553
7bd688cd 554static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
a9573556 555{
7bd688cd 556 struct drm_device *dev = connector->base.dev;
a9573556 557 struct drm_i915_private *dev_priv = dev->dev_private;
b329b328 558 u32 tmp, mask;
ba3820ad 559
0206e353 560 if (is_backlight_combination_mode(dev)) {
7bd688cd 561 u32 max = intel_panel_get_max_backlight(connector);
ba3820ad
TI
562 u8 lbpc;
563
d6540632
JN
564 /* we're screwed, but keep behaviour backwards compatible */
565 if (!max)
566 max = 1;
567
ba3820ad
TI
568 lbpc = level * 0xfe / max + 1;
569 level /= lbpc;
570 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
571 }
572
b329b328
JN
573 if (IS_GEN4(dev)) {
574 mask = BACKLIGHT_DUTY_CYCLE_MASK;
575 } else {
a9573556 576 level <<= 1;
b329b328
JN
577 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
578 }
7bd688cd 579
b329b328 580 tmp = I915_READ(BLC_PWM_CTL) & ~mask;
7bd688cd
JN
581 I915_WRITE(BLC_PWM_CTL, tmp | level);
582}
583
584static void vlv_set_backlight(struct intel_connector *connector, u32 level)
585{
586 struct drm_device *dev = connector->base.dev;
587 struct drm_i915_private *dev_priv = dev->dev_private;
588 enum pipe pipe = intel_get_pipe_from_connector(connector);
589 u32 tmp;
590
591 tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
592 I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
593}
594
595static void
596intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
597{
598 struct drm_device *dev = connector->base.dev;
599 struct drm_i915_private *dev_priv = dev->dev_private;
600
601 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
602
603 level = intel_panel_compute_brightness(connector, level);
604 dev_priv->display.set_backlight(connector, level);
a9573556 605}
47356eb6 606
d6540632 607/* set backlight brightness to level in range [0..max] */
752aa88a
JB
608void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
609 u32 max)
47356eb6 610{
752aa88a 611 struct drm_device *dev = connector->base.dev;
47356eb6 612 struct drm_i915_private *dev_priv = dev->dev_private;
58c68779 613 struct intel_panel *panel = &connector->panel;
752aa88a 614 enum pipe pipe = intel_get_pipe_from_connector(connector);
d6540632 615 u32 freq;
8ba2d185
JN
616 unsigned long flags;
617
752aa88a
JB
618 if (pipe == INVALID_PIPE)
619 return;
620
58c68779 621 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
d6540632 622
7bd688cd 623 freq = intel_panel_get_max_backlight(connector);
d6540632
JN
624 if (!freq) {
625 /* we are screwed, bail out */
8ba2d185 626 goto out;
d6540632
JN
627 }
628
22505b82
AL
629 /* scale to hardware, but be careful to not overflow */
630 if (freq < max)
631 level = level * freq / max;
632 else
633 level = freq / max * level;
47356eb6 634
58c68779
JN
635 panel->backlight.level = level;
636 if (panel->backlight.device)
637 panel->backlight.device->props.brightness = level;
b6b3ba5b 638
58c68779 639 if (panel->backlight.enabled)
7bd688cd 640 intel_panel_actually_set_backlight(connector, level);
8ba2d185 641out:
58c68779 642 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
f52c619a
TI
643}
644
7bd688cd
JN
645static void pch_disable_backlight(struct intel_connector *connector)
646{
647 struct drm_device *dev = connector->base.dev;
648 struct drm_i915_private *dev_priv = dev->dev_private;
649 u32 tmp;
650
651 tmp = I915_READ(BLC_PWM_CPU_CTL2);
652 I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
653
654 tmp = I915_READ(BLC_PWM_PCH_CTL1);
655 I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
656}
657
658static void i965_disable_backlight(struct intel_connector *connector)
659{
660 struct drm_device *dev = connector->base.dev;
661 struct drm_i915_private *dev_priv = dev->dev_private;
662 u32 tmp;
663
664 tmp = I915_READ(BLC_PWM_CTL2);
665 I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
666}
667
668static void vlv_disable_backlight(struct intel_connector *connector)
669{
670 struct drm_device *dev = connector->base.dev;
671 struct drm_i915_private *dev_priv = dev->dev_private;
672 enum pipe pipe = intel_get_pipe_from_connector(connector);
673 u32 tmp;
674
675 tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
676 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
677}
678
752aa88a 679void intel_panel_disable_backlight(struct intel_connector *connector)
f52c619a 680{
752aa88a 681 struct drm_device *dev = connector->base.dev;
f52c619a 682 struct drm_i915_private *dev_priv = dev->dev_private;
58c68779 683 struct intel_panel *panel = &connector->panel;
752aa88a 684 enum pipe pipe = intel_get_pipe_from_connector(connector);
8ba2d185
JN
685 unsigned long flags;
686
752aa88a
JB
687 if (pipe == INVALID_PIPE)
688 return;
689
3f577573
JN
690 /*
691 * Do not disable backlight on the vgaswitcheroo path. When switching
692 * away from i915, the other client may depend on i915 to handle the
693 * backlight. This will leave the backlight on unnecessarily when
694 * another client is not activated.
695 */
696 if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
697 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
698 return;
699 }
700
58c68779 701 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
47356eb6 702
58c68779 703 panel->backlight.enabled = false;
7bd688cd 704 intel_panel_actually_set_backlight(connector, 0);
24ded204 705
7bd688cd
JN
706 if (dev_priv->display.disable_backlight)
707 dev_priv->display.disable_backlight(connector);
24ded204 708
7bd688cd
JN
709 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
710}
24ded204 711
7bd688cd
JN
712static void pch_enable_backlight(struct intel_connector *connector)
713{
714 struct drm_device *dev = connector->base.dev;
715 struct drm_i915_private *dev_priv = dev->dev_private;
716 enum pipe pipe = intel_get_pipe_from_connector(connector);
717 enum transcoder cpu_transcoder =
718 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
719 u32 tmp;
a4f32fc3 720
7bd688cd
JN
721 tmp = I915_READ(BLC_PWM_CPU_CTL2);
722
723 /* Note that this can also get called through dpms changes. And
724 * we don't track the backlight dpms state, hence check whether
725 * we have to do anything first. */
726 if (tmp & BLM_PWM_ENABLE)
727 return;
728
729 if (INTEL_INFO(dev)->num_pipes == 3)
730 tmp &= ~BLM_PIPE_SELECT_IVB;
731 else
732 tmp &= ~BLM_PIPE_SELECT;
733
734 if (cpu_transcoder == TRANSCODER_EDP)
735 tmp |= BLM_TRANSCODER_EDP;
736 else
737 tmp |= BLM_PIPE(cpu_transcoder);
738 tmp &= ~BLM_PWM_ENABLE;
739
740 I915_WRITE(BLC_PWM_CPU_CTL2, tmp);
741 POSTING_READ(BLC_PWM_CPU_CTL2);
742 I915_WRITE(BLC_PWM_CPU_CTL2, tmp | BLM_PWM_ENABLE);
743
744 if (!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
745 tmp = I915_READ(BLC_PWM_PCH_CTL1);
746 tmp |= BLM_PCH_PWM_ENABLE;
747 tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
748 I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
24ded204 749 }
7bd688cd 750}
8ba2d185 751
7bd688cd
JN
752static void i965_enable_backlight(struct intel_connector *connector)
753{
754 struct drm_device *dev = connector->base.dev;
755 struct drm_i915_private *dev_priv = dev->dev_private;
756 enum pipe pipe = intel_get_pipe_from_connector(connector);
757 u32 tmp;
758
759 tmp = I915_READ(BLC_PWM_CTL2);
760
761 /* Note that this can also get called through dpms changes. And
762 * we don't track the backlight dpms state, hence check whether
763 * we have to do anything first. */
764 if (tmp & BLM_PWM_ENABLE)
765 return;
766
767 tmp &= ~BLM_PIPE_SELECT;
768 tmp |= BLM_PIPE(pipe);
769 tmp &= ~BLM_PWM_ENABLE;
770
771 I915_WRITE(BLC_PWM_CTL2, tmp);
772 POSTING_READ(BLC_PWM_CTL2);
773 I915_WRITE(BLC_PWM_CTL2, tmp | BLM_PWM_ENABLE);
774}
775
776static void vlv_enable_backlight(struct intel_connector *connector)
777{
778 struct drm_device *dev = connector->base.dev;
779 struct drm_i915_private *dev_priv = dev->dev_private;
780 enum pipe pipe = intel_get_pipe_from_connector(connector);
781 u32 tmp;
782
783 tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
784
785 /* Note that this can also get called through dpms changes. And
786 * we don't track the backlight dpms state, hence check whether
787 * we have to do anything first. */
788 if (tmp & BLM_PWM_ENABLE)
789 return;
790
7bd688cd
JN
791 tmp &= ~BLM_PWM_ENABLE;
792
793 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp);
794 POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
795 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp | BLM_PWM_ENABLE);
47356eb6
CW
796}
797
752aa88a 798void intel_panel_enable_backlight(struct intel_connector *connector)
47356eb6 799{
752aa88a 800 struct drm_device *dev = connector->base.dev;
47356eb6 801 struct drm_i915_private *dev_priv = dev->dev_private;
58c68779 802 struct intel_panel *panel = &connector->panel;
752aa88a 803 enum pipe pipe = intel_get_pipe_from_connector(connector);
8ba2d185
JN
804 unsigned long flags;
805
752aa88a
JB
806 if (pipe == INVALID_PIPE)
807 return;
808
6f2bcceb 809 DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
540b5d02 810
58c68779 811 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
47356eb6 812
58c68779 813 if (panel->backlight.level == 0) {
7bd688cd 814 panel->backlight.level = intel_panel_get_max_backlight(connector);
58c68779
JN
815 if (panel->backlight.device)
816 panel->backlight.device->props.brightness =
817 panel->backlight.level;
b6b3ba5b 818 }
47356eb6 819
7bd688cd
JN
820 if (dev_priv->display.enable_backlight)
821 dev_priv->display.enable_backlight(connector);
770c1231 822
b1289371
DV
823 /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
824 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
825 * registers are set.
770c1231 826 */
58c68779 827 panel->backlight.enabled = true;
7bd688cd 828 intel_panel_actually_set_backlight(connector, panel->backlight.level);
8ba2d185 829
58c68779 830 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
47356eb6
CW
831}
832
fe16d949
CW
833enum drm_connector_status
834intel_panel_detect(struct drm_device *dev)
835{
836 struct drm_i915_private *dev_priv = dev->dev_private;
837
838 /* Assume that the BIOS does not lie through the OpRegion... */
a726915c 839 if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
fe16d949
CW
840 return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
841 connector_status_connected :
842 connector_status_disconnected;
a726915c 843 }
fe16d949 844
a726915c
DV
845 switch (i915_panel_ignore_lid) {
846 case -2:
847 return connector_status_connected;
848 case -1:
849 return connector_status_disconnected;
850 default:
851 return connector_status_unknown;
852 }
fe16d949 853}
aaa6fd2a 854
912e8b12 855#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
db31af1d 856static int intel_backlight_device_update_status(struct backlight_device *bd)
aaa6fd2a 857{
752aa88a
JB
858 struct intel_connector *connector = bl_get_data(bd);
859 struct drm_device *dev = connector->base.dev;
860
861 mutex_lock(&dev->mode_config.mutex);
540b5d02
CW
862 DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
863 bd->props.brightness, bd->props.max_brightness);
752aa88a 864 intel_panel_set_backlight(connector, bd->props.brightness,
d6540632 865 bd->props.max_brightness);
752aa88a 866 mutex_unlock(&dev->mode_config.mutex);
aaa6fd2a
MG
867 return 0;
868}
869
db31af1d 870static int intel_backlight_device_get_brightness(struct backlight_device *bd)
aaa6fd2a 871{
752aa88a
JB
872 struct intel_connector *connector = bl_get_data(bd);
873 struct drm_device *dev = connector->base.dev;
7bd688cd 874 int ret;
752aa88a
JB
875
876 mutex_lock(&dev->mode_config.mutex);
7bd688cd 877 ret = intel_panel_get_backlight(connector);
752aa88a 878 mutex_unlock(&dev->mode_config.mutex);
752aa88a 879
7bd688cd 880 return ret;
aaa6fd2a
MG
881}
882
db31af1d
JN
883static const struct backlight_ops intel_backlight_device_ops = {
884 .update_status = intel_backlight_device_update_status,
885 .get_brightness = intel_backlight_device_get_brightness,
aaa6fd2a
MG
886};
887
db31af1d 888static int intel_backlight_device_register(struct intel_connector *connector)
aaa6fd2a 889{
58c68779 890 struct intel_panel *panel = &connector->panel;
aaa6fd2a 891 struct backlight_properties props;
aaa6fd2a 892
58c68779 893 if (WARN_ON(panel->backlight.device))
dc652f90
JN
894 return -ENODEV;
895
7bd688cd
JN
896 BUG_ON(panel->backlight.max == 0);
897
af437cfd 898 memset(&props, 0, sizeof(props));
aaa6fd2a 899 props.type = BACKLIGHT_RAW;
58c68779 900 props.brightness = panel->backlight.level;
7bd688cd 901 props.max_brightness = panel->backlight.max;
58c68779
JN
902
903 /*
904 * Note: using the same name independent of the connector prevents
905 * registration of multiple backlight devices in the driver.
906 */
907 panel->backlight.device =
aaa6fd2a 908 backlight_device_register("intel_backlight",
db31af1d
JN
909 connector->base.kdev,
910 connector,
911 &intel_backlight_device_ops, &props);
aaa6fd2a 912
58c68779 913 if (IS_ERR(panel->backlight.device)) {
aaa6fd2a 914 DRM_ERROR("Failed to register backlight: %ld\n",
58c68779
JN
915 PTR_ERR(panel->backlight.device));
916 panel->backlight.device = NULL;
aaa6fd2a
MG
917 return -ENODEV;
918 }
aaa6fd2a
MG
919 return 0;
920}
921
db31af1d 922static void intel_backlight_device_unregister(struct intel_connector *connector)
aaa6fd2a 923{
58c68779
JN
924 struct intel_panel *panel = &connector->panel;
925
926 if (panel->backlight.device) {
927 backlight_device_unregister(panel->backlight.device);
928 panel->backlight.device = NULL;
dc652f90 929 }
aaa6fd2a 930}
db31af1d
JN
931#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
932static int intel_backlight_device_register(struct intel_connector *connector)
933{
934 return 0;
935}
936static void intel_backlight_device_unregister(struct intel_connector *connector)
937{
938}
939#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
940
7bd688cd
JN
941/* Note: The setup hooks can't assume pipe is set! */
942static int pch_setup_backlight(struct intel_connector *connector)
943{
944 struct intel_panel *panel = &connector->panel;
945 u32 val;
946
947 panel->backlight.max = pch_get_max_backlight(connector);
948 if (!panel->backlight.max)
949 return -ENODEV;
950
951 val = pch_get_backlight(connector);
952 panel->backlight.level = intel_panel_compute_brightness(connector, val);
953
954 return 0;
955}
956
957static int i9xx_setup_backlight(struct intel_connector *connector)
958{
959 struct intel_panel *panel = &connector->panel;
960 u32 val;
961
962 panel->backlight.max = i9xx_get_max_backlight(connector);
963 if (!panel->backlight.max)
964 return -ENODEV;
965
966 val = i9xx_get_backlight(connector);
967 panel->backlight.level = intel_panel_compute_brightness(connector, val);
968
969 return 0;
970}
971
972static int i965_setup_backlight(struct intel_connector *connector)
973{
974 struct intel_panel *panel = &connector->panel;
975 u32 val;
976
977 panel->backlight.max = i965_get_max_backlight(connector);
978 if (!panel->backlight.max)
979 return -ENODEV;
980
981 val = i9xx_get_backlight(connector);
982 panel->backlight.level = intel_panel_compute_brightness(connector, val);
983
984 return 0;
985}
986
987static int vlv_setup_backlight(struct intel_connector *connector)
988{
989 struct drm_device *dev = connector->base.dev;
990 struct drm_i915_private *dev_priv = dev->dev_private;
991 struct intel_panel *panel = &connector->panel;
992 enum pipe pipe;
993 u32 val;
994
995 for_each_pipe(pipe) {
996 u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
997
998 /* Skip if the modulation freq is already set */
999 if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
1000 continue;
1001
1002 cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
1003 I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
1004 cur_val);
1005 }
1006
1007 panel->backlight.max = _vlv_get_max_backlight(dev, PIPE_A);
1008 if (!panel->backlight.max)
1009 return -ENODEV;
1010
1011 val = _vlv_get_backlight(dev, PIPE_A);
1012 panel->backlight.level = intel_panel_compute_brightness(connector, val);
1013
1014 return 0;
1015}
1016
0657b6b1 1017int intel_panel_setup_backlight(struct drm_connector *connector)
aaa6fd2a 1018{
db31af1d 1019 struct drm_device *dev = connector->dev;
7bd688cd 1020 struct drm_i915_private *dev_priv = dev->dev_private;
db31af1d 1021 struct intel_connector *intel_connector = to_intel_connector(connector);
58c68779 1022 struct intel_panel *panel = &intel_connector->panel;
7bd688cd
JN
1023 unsigned long flags;
1024 int ret;
db31af1d 1025
7bd688cd
JN
1026 /* set level and max in panel struct */
1027 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
1028 ret = dev_priv->display.setup_backlight(intel_connector);
1029 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
1030
1031 if (ret) {
1032 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1033 drm_get_connector_name(connector));
1034 return ret;
1035 }
db31af1d 1036
58c68779 1037 panel->backlight.enabled = panel->backlight.level != 0;
db31af1d
JN
1038
1039 intel_backlight_device_register(intel_connector);
1040
c91c9f32
JN
1041 panel->backlight.present = true;
1042
aaa6fd2a
MG
1043 return 0;
1044}
1045
db31af1d 1046void intel_panel_destroy_backlight(struct drm_connector *connector)
aaa6fd2a 1047{
db31af1d 1048 struct intel_connector *intel_connector = to_intel_connector(connector);
c91c9f32 1049 struct intel_panel *panel = &intel_connector->panel;
db31af1d 1050
c91c9f32 1051 panel->backlight.present = false;
db31af1d 1052 intel_backlight_device_unregister(intel_connector);
aaa6fd2a 1053}
1d508706 1054
7bd688cd
JN
1055/* Set up chip specific backlight functions */
1056void intel_panel_init_backlight_funcs(struct drm_device *dev)
1057{
1058 struct drm_i915_private *dev_priv = dev->dev_private;
1059
1060 if (HAS_PCH_SPLIT(dev)) {
1061 dev_priv->display.setup_backlight = pch_setup_backlight;
1062 dev_priv->display.enable_backlight = pch_enable_backlight;
1063 dev_priv->display.disable_backlight = pch_disable_backlight;
1064 dev_priv->display.set_backlight = pch_set_backlight;
1065 dev_priv->display.get_backlight = pch_get_backlight;
1066 dev_priv->display.get_max_backlight = pch_get_max_backlight;
1067 } else if (IS_VALLEYVIEW(dev)) {
1068 dev_priv->display.setup_backlight = vlv_setup_backlight;
1069 dev_priv->display.enable_backlight = vlv_enable_backlight;
1070 dev_priv->display.disable_backlight = vlv_disable_backlight;
1071 dev_priv->display.set_backlight = vlv_set_backlight;
1072 dev_priv->display.get_backlight = vlv_get_backlight;
1073 dev_priv->display.get_max_backlight = vlv_get_max_backlight;
1074 } else if (IS_GEN4(dev)) {
1075 dev_priv->display.setup_backlight = i965_setup_backlight;
1076 dev_priv->display.enable_backlight = i965_enable_backlight;
1077 dev_priv->display.disable_backlight = i965_disable_backlight;
1078 dev_priv->display.set_backlight = i9xx_set_backlight;
1079 dev_priv->display.get_backlight = i9xx_get_backlight;
1080 dev_priv->display.get_max_backlight = i965_get_max_backlight;
1081 } else {
1082 dev_priv->display.setup_backlight = i9xx_setup_backlight;
1083 dev_priv->display.set_backlight = i9xx_set_backlight;
1084 dev_priv->display.get_backlight = i9xx_get_backlight;
1085 dev_priv->display.get_max_backlight = i9xx_get_max_backlight;
1086 }
1087}
1088
dd06f90e
JN
1089int intel_panel_init(struct intel_panel *panel,
1090 struct drm_display_mode *fixed_mode)
1d508706 1091{
dd06f90e
JN
1092 panel->fixed_mode = fixed_mode;
1093
1d508706
JN
1094 return 0;
1095}
1096
1097void intel_panel_fini(struct intel_panel *panel)
1098{
dd06f90e
JN
1099 struct intel_connector *intel_connector =
1100 container_of(panel, struct intel_connector, panel);
1101
1102 if (panel->fixed_mode)
1103 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1d508706 1104}