Line data Source code
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 :
31 : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 :
33 : #ifdef __linux__
34 : #include <linux/kernel.h>
35 : #include <linux/moduleparam.h>
36 : #include <linux/pwm.h>
37 : #endif
38 : #include "intel_drv.h"
39 :
40 : #define CRC_PMIC_PWM_PERIOD_NS 21333
41 :
42 : void
43 0 : intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
44 : struct drm_display_mode *adjusted_mode)
45 : {
46 0 : drm_mode_copy(adjusted_mode, fixed_mode);
47 :
48 0 : drm_mode_set_crtcinfo(adjusted_mode, 0);
49 0 : }
50 :
51 : /**
52 : * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
53 : * @dev: drm device
54 : * @fixed_mode : panel native mode
55 : * @connector: LVDS/eDP connector
56 : *
57 : * Return downclock_avail
58 : * Find the reduced downclock for LVDS/eDP in EDID.
59 : */
60 : struct drm_display_mode *
61 0 : intel_find_panel_downclock(struct drm_device *dev,
62 : struct drm_display_mode *fixed_mode,
63 : struct drm_connector *connector)
64 : {
65 : struct drm_display_mode *scan, *tmp_mode;
66 : int temp_downclock;
67 :
68 0 : temp_downclock = fixed_mode->clock;
69 : tmp_mode = NULL;
70 :
71 0 : list_for_each_entry(scan, &connector->probed_modes, head) {
72 : /*
73 : * If one mode has the same resolution with the fixed_panel
74 : * mode while they have the different refresh rate, it means
75 : * that the reduced downclock is found. In such
76 : * case we can set the different FPx0/1 to dynamically select
77 : * between low and high frequency.
78 : */
79 0 : if (scan->hdisplay == fixed_mode->hdisplay &&
80 0 : scan->hsync_start == fixed_mode->hsync_start &&
81 0 : scan->hsync_end == fixed_mode->hsync_end &&
82 0 : scan->htotal == fixed_mode->htotal &&
83 0 : scan->vdisplay == fixed_mode->vdisplay &&
84 0 : scan->vsync_start == fixed_mode->vsync_start &&
85 0 : scan->vsync_end == fixed_mode->vsync_end &&
86 0 : scan->vtotal == fixed_mode->vtotal) {
87 0 : if (scan->clock < temp_downclock) {
88 : /*
89 : * The downclock is already found. But we
90 : * expect to find the lower downclock.
91 : */
92 : temp_downclock = scan->clock;
93 : tmp_mode = scan;
94 0 : }
95 : }
96 : }
97 :
98 0 : if (temp_downclock < fixed_mode->clock)
99 0 : return drm_mode_duplicate(dev, tmp_mode);
100 : else
101 0 : return NULL;
102 0 : }
103 :
104 : /* adjusted_mode has been preset to be the panel's fixed mode */
105 : void
106 0 : intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
107 : struct intel_crtc_state *pipe_config,
108 : int fitting_mode)
109 : {
110 0 : const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
111 : int x = 0, y = 0, width = 0, height = 0;
112 :
113 : /* Native modes don't need fitting */
114 0 : if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
115 0 : adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
116 : goto done;
117 :
118 0 : switch (fitting_mode) {
119 : case DRM_MODE_SCALE_CENTER:
120 0 : width = pipe_config->pipe_src_w;
121 0 : height = pipe_config->pipe_src_h;
122 0 : x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
123 0 : y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
124 0 : break;
125 :
126 : case DRM_MODE_SCALE_ASPECT:
127 : /* Scale but preserve the aspect ratio */
128 : {
129 0 : u32 scaled_width = adjusted_mode->crtc_hdisplay
130 0 : * pipe_config->pipe_src_h;
131 0 : u32 scaled_height = pipe_config->pipe_src_w
132 0 : * adjusted_mode->crtc_vdisplay;
133 0 : if (scaled_width > scaled_height) { /* pillar */
134 0 : width = scaled_height / pipe_config->pipe_src_h;
135 0 : if (width & 1)
136 0 : width++;
137 0 : x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
138 : y = 0;
139 0 : height = adjusted_mode->crtc_vdisplay;
140 0 : } else if (scaled_width < scaled_height) { /* letter */
141 0 : height = scaled_width / pipe_config->pipe_src_w;
142 0 : if (height & 1)
143 0 : height++;
144 0 : y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
145 : x = 0;
146 0 : width = adjusted_mode->crtc_hdisplay;
147 0 : } else {
148 : x = y = 0;
149 : width = adjusted_mode->crtc_hdisplay;
150 : height = adjusted_mode->crtc_vdisplay;
151 : }
152 : }
153 0 : break;
154 :
155 : case DRM_MODE_SCALE_FULLSCREEN:
156 : x = y = 0;
157 0 : width = adjusted_mode->crtc_hdisplay;
158 0 : height = adjusted_mode->crtc_vdisplay;
159 0 : break;
160 :
161 : default:
162 0 : WARN(1, "bad panel fit mode: %d\n", fitting_mode);
163 0 : return;
164 : }
165 :
166 : done:
167 0 : pipe_config->pch_pfit.pos = (x << 16) | y;
168 0 : pipe_config->pch_pfit.size = (width << 16) | height;
169 0 : pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
170 0 : }
171 :
172 : static void
173 0 : centre_horizontally(struct drm_display_mode *adjusted_mode,
174 : int width)
175 : {
176 : u32 border, sync_pos, blank_width, sync_width;
177 :
178 : /* keep the hsync and hblank widths constant */
179 0 : sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
180 0 : blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
181 0 : sync_pos = (blank_width - sync_width + 1) / 2;
182 :
183 0 : border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
184 0 : border += border & 1; /* make the border even */
185 :
186 0 : adjusted_mode->crtc_hdisplay = width;
187 0 : adjusted_mode->crtc_hblank_start = width + border;
188 0 : adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
189 :
190 0 : adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
191 0 : adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
192 0 : }
193 :
194 : static void
195 0 : centre_vertically(struct drm_display_mode *adjusted_mode,
196 : int height)
197 : {
198 : u32 border, sync_pos, blank_width, sync_width;
199 :
200 : /* keep the vsync and vblank widths constant */
201 0 : sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
202 0 : blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
203 0 : sync_pos = (blank_width - sync_width + 1) / 2;
204 :
205 0 : border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
206 :
207 0 : adjusted_mode->crtc_vdisplay = height;
208 0 : adjusted_mode->crtc_vblank_start = height + border;
209 0 : adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
210 :
211 0 : adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
212 0 : adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
213 0 : }
214 :
215 0 : static inline u32 panel_fitter_scaling(u32 source, u32 target)
216 : {
217 : /*
218 : * Floating point operation is not supported. So the FACTOR
219 : * is defined, which can avoid the floating point computation
220 : * when calculating the panel ratio.
221 : */
222 : #define ACCURACY 12
223 : #define FACTOR (1 << ACCURACY)
224 0 : u32 ratio = source * FACTOR / target;
225 0 : return (FACTOR * ratio + FACTOR/2) / FACTOR;
226 : }
227 :
228 0 : static void i965_scale_aspect(struct intel_crtc_state *pipe_config,
229 : u32 *pfit_control)
230 : {
231 0 : const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
232 0 : u32 scaled_width = adjusted_mode->crtc_hdisplay *
233 0 : pipe_config->pipe_src_h;
234 0 : u32 scaled_height = pipe_config->pipe_src_w *
235 0 : adjusted_mode->crtc_vdisplay;
236 :
237 : /* 965+ is easy, it does everything in hw */
238 0 : if (scaled_width > scaled_height)
239 0 : *pfit_control |= PFIT_ENABLE |
240 : PFIT_SCALING_PILLAR;
241 0 : else if (scaled_width < scaled_height)
242 0 : *pfit_control |= PFIT_ENABLE |
243 : PFIT_SCALING_LETTER;
244 0 : else if (adjusted_mode->crtc_hdisplay != pipe_config->pipe_src_w)
245 0 : *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
246 0 : }
247 :
248 0 : static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config,
249 : u32 *pfit_control, u32 *pfit_pgm_ratios,
250 : u32 *border)
251 : {
252 0 : struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
253 0 : u32 scaled_width = adjusted_mode->crtc_hdisplay *
254 0 : pipe_config->pipe_src_h;
255 0 : u32 scaled_height = pipe_config->pipe_src_w *
256 0 : adjusted_mode->crtc_vdisplay;
257 : u32 bits;
258 :
259 : /*
260 : * For earlier chips we have to calculate the scaling
261 : * ratio by hand and program it into the
262 : * PFIT_PGM_RATIO register
263 : */
264 0 : if (scaled_width > scaled_height) { /* pillar */
265 0 : centre_horizontally(adjusted_mode,
266 0 : scaled_height /
267 : pipe_config->pipe_src_h);
268 :
269 0 : *border = LVDS_BORDER_ENABLE;
270 0 : if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay) {
271 0 : bits = panel_fitter_scaling(pipe_config->pipe_src_h,
272 : adjusted_mode->crtc_vdisplay);
273 :
274 0 : *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
275 0 : bits << PFIT_VERT_SCALE_SHIFT);
276 0 : *pfit_control |= (PFIT_ENABLE |
277 : VERT_INTERP_BILINEAR |
278 : HORIZ_INTERP_BILINEAR);
279 0 : }
280 0 : } else if (scaled_width < scaled_height) { /* letter */
281 0 : centre_vertically(adjusted_mode,
282 0 : scaled_width /
283 : pipe_config->pipe_src_w);
284 :
285 0 : *border = LVDS_BORDER_ENABLE;
286 0 : if (pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
287 0 : bits = panel_fitter_scaling(pipe_config->pipe_src_w,
288 : adjusted_mode->crtc_hdisplay);
289 :
290 0 : *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
291 0 : bits << PFIT_VERT_SCALE_SHIFT);
292 0 : *pfit_control |= (PFIT_ENABLE |
293 : VERT_INTERP_BILINEAR |
294 : HORIZ_INTERP_BILINEAR);
295 0 : }
296 : } else {
297 : /* Aspects match, Let hw scale both directions */
298 0 : *pfit_control |= (PFIT_ENABLE |
299 : VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
300 : VERT_INTERP_BILINEAR |
301 : HORIZ_INTERP_BILINEAR);
302 : }
303 0 : }
304 :
305 0 : void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
306 : struct intel_crtc_state *pipe_config,
307 : int fitting_mode)
308 : {
309 0 : struct drm_device *dev = intel_crtc->base.dev;
310 0 : u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
311 0 : struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
312 :
313 : /* Native modes don't need fitting */
314 0 : if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
315 0 : adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
316 : goto out;
317 :
318 0 : switch (fitting_mode) {
319 : case DRM_MODE_SCALE_CENTER:
320 : /*
321 : * For centered modes, we have to calculate border widths &
322 : * heights and modify the values programmed into the CRTC.
323 : */
324 0 : centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
325 0 : centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
326 0 : border = LVDS_BORDER_ENABLE;
327 0 : break;
328 : case DRM_MODE_SCALE_ASPECT:
329 : /* Scale but preserve the aspect ratio */
330 0 : if (INTEL_INFO(dev)->gen >= 4)
331 0 : i965_scale_aspect(pipe_config, &pfit_control);
332 : else
333 0 : i9xx_scale_aspect(pipe_config, &pfit_control,
334 : &pfit_pgm_ratios, &border);
335 : break;
336 : case DRM_MODE_SCALE_FULLSCREEN:
337 : /*
338 : * Full scaling, even if it changes the aspect ratio.
339 : * Fortunately this is all done for us in hw.
340 : */
341 0 : if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay ||
342 0 : pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
343 0 : pfit_control |= PFIT_ENABLE;
344 0 : if (INTEL_INFO(dev)->gen >= 4)
345 0 : pfit_control |= PFIT_SCALING_AUTO;
346 : else
347 0 : pfit_control |= (VERT_AUTO_SCALE |
348 : VERT_INTERP_BILINEAR |
349 : HORIZ_AUTO_SCALE |
350 : HORIZ_INTERP_BILINEAR);
351 : }
352 : break;
353 : default:
354 0 : WARN(1, "bad panel fit mode: %d\n", fitting_mode);
355 0 : return;
356 : }
357 :
358 : /* 965+ wants fuzzy fitting */
359 : /* FIXME: handle multiple panels by failing gracefully */
360 0 : if (INTEL_INFO(dev)->gen >= 4)
361 0 : pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
362 : PFIT_FILTER_FUZZY);
363 :
364 : out:
365 0 : if ((pfit_control & PFIT_ENABLE) == 0) {
366 0 : pfit_control = 0;
367 0 : pfit_pgm_ratios = 0;
368 0 : }
369 :
370 : /* Make sure pre-965 set dither correctly for 18bpp panels. */
371 0 : if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
372 0 : pfit_control |= PANEL_8TO6_DITHER_ENABLE;
373 :
374 0 : pipe_config->gmch_pfit.control = pfit_control;
375 0 : pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
376 0 : pipe_config->gmch_pfit.lvds_border_bits = border;
377 0 : }
378 :
379 : enum drm_connector_status
380 0 : intel_panel_detect(struct drm_device *dev)
381 : {
382 0 : struct drm_i915_private *dev_priv = dev->dev_private;
383 :
384 : /* Assume that the BIOS does not lie through the OpRegion... */
385 0 : if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
386 0 : return *dev_priv->opregion.lid_state & 0x1 ?
387 : connector_status_connected :
388 : connector_status_disconnected;
389 : }
390 :
391 0 : switch (i915.panel_ignore_lid) {
392 : case -2:
393 0 : return connector_status_connected;
394 : case -1:
395 0 : return connector_status_disconnected;
396 : default:
397 0 : return connector_status_unknown;
398 : }
399 0 : }
400 :
401 : /**
402 : * scale - scale values from one range to another
403 : *
404 : * @source_val: value in range [@source_min..@source_max]
405 : *
406 : * Return @source_val in range [@source_min..@source_max] scaled to range
407 : * [@target_min..@target_max].
408 : */
409 0 : static uint32_t scale(uint32_t source_val,
410 : uint32_t source_min, uint32_t source_max,
411 : uint32_t target_min, uint32_t target_max)
412 : {
413 : uint64_t target_val;
414 :
415 0 : WARN_ON(source_min > source_max);
416 0 : WARN_ON(target_min > target_max);
417 :
418 : /* defensive */
419 0 : source_val = clamp(source_val, source_min, source_max);
420 :
421 : /* avoid overflows */
422 0 : target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) *
423 : (target_max - target_min), source_max - source_min);
424 0 : target_val += target_min;
425 :
426 0 : return target_val;
427 : }
428 :
429 : /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
430 0 : static inline u32 scale_user_to_hw(struct intel_connector *connector,
431 : u32 user_level, u32 user_max)
432 : {
433 0 : struct intel_panel *panel = &connector->panel;
434 :
435 0 : return scale(user_level, 0, user_max,
436 0 : panel->backlight.min, panel->backlight.max);
437 : }
438 :
439 : /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
440 : * to [hw_min..hw_max]. */
441 0 : static inline u32 clamp_user_to_hw(struct intel_connector *connector,
442 : u32 user_level, u32 user_max)
443 : {
444 0 : struct intel_panel *panel = &connector->panel;
445 : u32 hw_level;
446 :
447 0 : hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
448 0 : hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
449 :
450 0 : return hw_level;
451 : }
452 :
453 : /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
454 0 : static inline u32 scale_hw_to_user(struct intel_connector *connector,
455 : u32 hw_level, u32 user_max)
456 : {
457 0 : struct intel_panel *panel = &connector->panel;
458 :
459 0 : return scale(hw_level, panel->backlight.min, panel->backlight.max,
460 : 0, user_max);
461 : }
462 :
463 0 : static u32 intel_panel_compute_brightness(struct intel_connector *connector,
464 : u32 val)
465 : {
466 0 : struct drm_device *dev = connector->base.dev;
467 0 : struct drm_i915_private *dev_priv = dev->dev_private;
468 0 : struct intel_panel *panel = &connector->panel;
469 :
470 0 : WARN_ON(panel->backlight.max == 0);
471 :
472 0 : if (i915.invert_brightness < 0)
473 0 : return val;
474 :
475 0 : if (i915.invert_brightness > 0 ||
476 0 : dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
477 0 : return panel->backlight.max - val;
478 : }
479 :
480 0 : return val;
481 0 : }
482 :
483 0 : static u32 lpt_get_backlight(struct intel_connector *connector)
484 : {
485 0 : struct drm_device *dev = connector->base.dev;
486 0 : struct drm_i915_private *dev_priv = dev->dev_private;
487 :
488 0 : return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
489 : }
490 :
491 0 : static u32 pch_get_backlight(struct intel_connector *connector)
492 : {
493 0 : struct drm_device *dev = connector->base.dev;
494 0 : struct drm_i915_private *dev_priv = dev->dev_private;
495 :
496 0 : return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
497 : }
498 :
499 0 : static u32 i9xx_get_backlight(struct intel_connector *connector)
500 : {
501 0 : struct drm_device *dev = connector->base.dev;
502 0 : struct drm_i915_private *dev_priv = dev->dev_private;
503 0 : struct intel_panel *panel = &connector->panel;
504 : u32 val;
505 :
506 0 : val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
507 0 : if (INTEL_INFO(dev)->gen < 4)
508 0 : val >>= 1;
509 :
510 0 : if (panel->backlight.combination_mode) {
511 0 : u8 lbpc;
512 :
513 0 : pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
514 0 : val *= lbpc;
515 0 : }
516 :
517 0 : return val;
518 : }
519 :
520 0 : static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
521 : {
522 0 : struct drm_i915_private *dev_priv = dev->dev_private;
523 :
524 0 : if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
525 0 : return 0;
526 :
527 0 : return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
528 0 : }
529 :
530 0 : static u32 vlv_get_backlight(struct intel_connector *connector)
531 : {
532 0 : struct drm_device *dev = connector->base.dev;
533 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
534 :
535 0 : return _vlv_get_backlight(dev, pipe);
536 : }
537 :
538 0 : static u32 bxt_get_backlight(struct intel_connector *connector)
539 : {
540 0 : struct drm_device *dev = connector->base.dev;
541 0 : struct intel_panel *panel = &connector->panel;
542 0 : struct drm_i915_private *dev_priv = dev->dev_private;
543 :
544 0 : return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller));
545 : }
546 :
547 0 : static u32 pwm_get_backlight(struct intel_connector *connector)
548 : {
549 0 : struct intel_panel *panel = &connector->panel;
550 : int duty_ns;
551 :
552 0 : duty_ns = pwm_get_duty_cycle(panel->backlight.pwm);
553 0 : return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
554 : }
555 :
556 0 : static u32 intel_panel_get_backlight(struct intel_connector *connector)
557 : {
558 0 : struct drm_device *dev = connector->base.dev;
559 0 : struct drm_i915_private *dev_priv = dev->dev_private;
560 0 : struct intel_panel *panel = &connector->panel;
561 : u32 val = 0;
562 :
563 0 : mutex_lock(&dev_priv->backlight_lock);
564 :
565 0 : if (panel->backlight.enabled) {
566 0 : val = panel->backlight.get(connector);
567 0 : val = intel_panel_compute_brightness(connector, val);
568 0 : }
569 :
570 0 : mutex_unlock(&dev_priv->backlight_lock);
571 :
572 : DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
573 0 : return val;
574 : }
575 :
576 0 : static void lpt_set_backlight(struct intel_connector *connector, u32 level)
577 : {
578 0 : struct drm_device *dev = connector->base.dev;
579 0 : struct drm_i915_private *dev_priv = dev->dev_private;
580 0 : u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
581 0 : I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
582 0 : }
583 :
584 0 : static void pch_set_backlight(struct intel_connector *connector, u32 level)
585 : {
586 0 : struct drm_device *dev = connector->base.dev;
587 0 : struct drm_i915_private *dev_priv = dev->dev_private;
588 : u32 tmp;
589 :
590 0 : tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
591 0 : I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
592 0 : }
593 :
594 0 : static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
595 : {
596 0 : struct drm_device *dev = connector->base.dev;
597 0 : struct drm_i915_private *dev_priv = dev->dev_private;
598 0 : struct intel_panel *panel = &connector->panel;
599 : u32 tmp, mask;
600 :
601 0 : WARN_ON(panel->backlight.max == 0);
602 :
603 0 : if (panel->backlight.combination_mode) {
604 : u8 lbpc;
605 :
606 0 : lbpc = level * 0xfe / panel->backlight.max + 1;
607 0 : level /= lbpc;
608 0 : pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
609 0 : }
610 :
611 0 : if (IS_GEN4(dev)) {
612 : mask = BACKLIGHT_DUTY_CYCLE_MASK;
613 0 : } else {
614 0 : level <<= 1;
615 : mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
616 : }
617 :
618 0 : tmp = I915_READ(BLC_PWM_CTL) & ~mask;
619 0 : I915_WRITE(BLC_PWM_CTL, tmp | level);
620 0 : }
621 :
622 0 : static void vlv_set_backlight(struct intel_connector *connector, u32 level)
623 : {
624 0 : struct drm_device *dev = connector->base.dev;
625 0 : struct drm_i915_private *dev_priv = dev->dev_private;
626 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
627 : u32 tmp;
628 :
629 0 : if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
630 0 : return;
631 :
632 0 : tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
633 0 : I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
634 0 : }
635 :
636 0 : static void bxt_set_backlight(struct intel_connector *connector, u32 level)
637 : {
638 0 : struct drm_device *dev = connector->base.dev;
639 0 : struct drm_i915_private *dev_priv = dev->dev_private;
640 0 : struct intel_panel *panel = &connector->panel;
641 :
642 0 : I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
643 0 : }
644 :
645 0 : static void pwm_set_backlight(struct intel_connector *connector, u32 level)
646 : {
647 0 : struct intel_panel *panel = &connector->panel;
648 0 : int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
649 :
650 0 : pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
651 0 : }
652 :
653 : static void
654 0 : intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
655 : {
656 0 : struct intel_panel *panel = &connector->panel;
657 :
658 : DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
659 :
660 0 : level = intel_panel_compute_brightness(connector, level);
661 0 : panel->backlight.set(connector, level);
662 0 : }
663 :
664 : /* set backlight brightness to level in range [0..max], scaling wrt hw min */
665 0 : static void intel_panel_set_backlight(struct intel_connector *connector,
666 : u32 user_level, u32 user_max)
667 : {
668 0 : struct drm_device *dev = connector->base.dev;
669 0 : struct drm_i915_private *dev_priv = dev->dev_private;
670 0 : struct intel_panel *panel = &connector->panel;
671 : u32 hw_level;
672 :
673 0 : if (!panel->backlight.present)
674 0 : return;
675 :
676 0 : mutex_lock(&dev_priv->backlight_lock);
677 :
678 0 : WARN_ON(panel->backlight.max == 0);
679 :
680 0 : hw_level = scale_user_to_hw(connector, user_level, user_max);
681 0 : panel->backlight.level = hw_level;
682 :
683 0 : if (panel->backlight.enabled)
684 0 : intel_panel_actually_set_backlight(connector, hw_level);
685 :
686 0 : mutex_unlock(&dev_priv->backlight_lock);
687 0 : }
688 :
689 : /* set backlight brightness to level in range [0..max], assuming hw min is
690 : * respected.
691 : */
692 0 : void intel_panel_set_backlight_acpi(struct intel_connector *connector,
693 : u32 user_level, u32 user_max)
694 : {
695 0 : struct drm_device *dev = connector->base.dev;
696 0 : struct drm_i915_private *dev_priv = dev->dev_private;
697 0 : struct intel_panel *panel = &connector->panel;
698 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
699 : u32 hw_level;
700 :
701 : /*
702 : * INVALID_PIPE may occur during driver init because
703 : * connection_mutex isn't held across the entire backlight
704 : * setup + modeset readout, and the BIOS can issue the
705 : * requests at any time.
706 : */
707 0 : if (!panel->backlight.present || pipe == INVALID_PIPE)
708 0 : return;
709 :
710 0 : mutex_lock(&dev_priv->backlight_lock);
711 :
712 0 : WARN_ON(panel->backlight.max == 0);
713 :
714 0 : hw_level = clamp_user_to_hw(connector, user_level, user_max);
715 0 : panel->backlight.level = hw_level;
716 :
717 0 : if (panel->backlight.device)
718 0 : panel->backlight.device->props.brightness =
719 0 : scale_hw_to_user(connector,
720 : panel->backlight.level,
721 0 : panel->backlight.device->props.max_brightness);
722 :
723 0 : if (panel->backlight.enabled)
724 0 : intel_panel_actually_set_backlight(connector, hw_level);
725 :
726 0 : mutex_unlock(&dev_priv->backlight_lock);
727 0 : }
728 :
729 0 : static void lpt_disable_backlight(struct intel_connector *connector)
730 : {
731 0 : struct drm_device *dev = connector->base.dev;
732 0 : struct drm_i915_private *dev_priv = dev->dev_private;
733 : u32 tmp;
734 :
735 0 : intel_panel_actually_set_backlight(connector, 0);
736 :
737 : /*
738 : * Although we don't support or enable CPU PWM with LPT/SPT based
739 : * systems, it may have been enabled prior to loading the
740 : * driver. Disable to avoid warnings on LCPLL disable.
741 : *
742 : * This needs rework if we need to add support for CPU PWM on PCH split
743 : * platforms.
744 : */
745 0 : tmp = I915_READ(BLC_PWM_CPU_CTL2);
746 0 : if (tmp & BLM_PWM_ENABLE) {
747 : DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n");
748 0 : I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
749 0 : }
750 :
751 0 : tmp = I915_READ(BLC_PWM_PCH_CTL1);
752 0 : I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
753 0 : }
754 :
755 0 : static void pch_disable_backlight(struct intel_connector *connector)
756 : {
757 0 : struct drm_device *dev = connector->base.dev;
758 0 : struct drm_i915_private *dev_priv = dev->dev_private;
759 : u32 tmp;
760 :
761 0 : intel_panel_actually_set_backlight(connector, 0);
762 :
763 0 : tmp = I915_READ(BLC_PWM_CPU_CTL2);
764 0 : I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
765 :
766 0 : tmp = I915_READ(BLC_PWM_PCH_CTL1);
767 0 : I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
768 0 : }
769 :
770 0 : static void i9xx_disable_backlight(struct intel_connector *connector)
771 : {
772 0 : intel_panel_actually_set_backlight(connector, 0);
773 0 : }
774 :
775 0 : static void i965_disable_backlight(struct intel_connector *connector)
776 : {
777 0 : struct drm_device *dev = connector->base.dev;
778 0 : struct drm_i915_private *dev_priv = dev->dev_private;
779 : u32 tmp;
780 :
781 0 : intel_panel_actually_set_backlight(connector, 0);
782 :
783 0 : tmp = I915_READ(BLC_PWM_CTL2);
784 0 : I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
785 0 : }
786 :
787 0 : static void vlv_disable_backlight(struct intel_connector *connector)
788 : {
789 0 : struct drm_device *dev = connector->base.dev;
790 0 : struct drm_i915_private *dev_priv = dev->dev_private;
791 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
792 : u32 tmp;
793 :
794 0 : if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
795 0 : return;
796 :
797 0 : intel_panel_actually_set_backlight(connector, 0);
798 :
799 0 : tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
800 0 : I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
801 0 : }
802 :
803 0 : static void bxt_disable_backlight(struct intel_connector *connector)
804 : {
805 0 : struct drm_device *dev = connector->base.dev;
806 0 : struct drm_i915_private *dev_priv = dev->dev_private;
807 0 : struct intel_panel *panel = &connector->panel;
808 : u32 tmp, val;
809 :
810 0 : intel_panel_actually_set_backlight(connector, 0);
811 :
812 0 : tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
813 0 : I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
814 : tmp & ~BXT_BLC_PWM_ENABLE);
815 :
816 0 : if (panel->backlight.controller == 1) {
817 0 : val = I915_READ(UTIL_PIN_CTL);
818 0 : val &= ~UTIL_PIN_ENABLE;
819 0 : I915_WRITE(UTIL_PIN_CTL, val);
820 0 : }
821 0 : }
822 :
823 0 : static void pwm_disable_backlight(struct intel_connector *connector)
824 : {
825 0 : struct intel_panel *panel = &connector->panel;
826 :
827 : /* Disable the backlight */
828 0 : pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS);
829 0 : usleep_range(2000, 3000);
830 0 : pwm_disable(panel->backlight.pwm);
831 0 : }
832 :
833 0 : void intel_panel_disable_backlight(struct intel_connector *connector)
834 : {
835 0 : struct drm_device *dev = connector->base.dev;
836 0 : struct drm_i915_private *dev_priv = dev->dev_private;
837 0 : struct intel_panel *panel = &connector->panel;
838 :
839 0 : if (!panel->backlight.present)
840 0 : return;
841 :
842 : #ifdef __linux__
843 : /*
844 : * Do not disable backlight on the vga_switcheroo path. When switching
845 : * away from i915, the other client may depend on i915 to handle the
846 : * backlight. This will leave the backlight on unnecessarily when
847 : * another client is not activated.
848 : */
849 : if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
850 : DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
851 : return;
852 : }
853 : #endif
854 :
855 0 : mutex_lock(&dev_priv->backlight_lock);
856 :
857 0 : if (panel->backlight.device)
858 0 : panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
859 0 : panel->backlight.enabled = false;
860 0 : panel->backlight.disable(connector);
861 :
862 0 : mutex_unlock(&dev_priv->backlight_lock);
863 0 : }
864 :
865 0 : static void lpt_enable_backlight(struct intel_connector *connector)
866 : {
867 0 : struct drm_device *dev = connector->base.dev;
868 0 : struct drm_i915_private *dev_priv = dev->dev_private;
869 0 : struct intel_panel *panel = &connector->panel;
870 : u32 pch_ctl1, pch_ctl2, schicken;
871 :
872 0 : pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
873 0 : if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
874 : DRM_DEBUG_KMS("pch backlight already enabled\n");
875 0 : pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
876 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
877 0 : }
878 :
879 0 : if (HAS_PCH_LPT(dev)) {
880 0 : schicken = I915_READ(SOUTH_CHICKEN2);
881 0 : if (panel->backlight.alternate_pwm_increment)
882 0 : schicken |= LPT_PWM_GRANULARITY;
883 : else
884 0 : schicken &= ~LPT_PWM_GRANULARITY;
885 0 : I915_WRITE(SOUTH_CHICKEN2, schicken);
886 0 : } else {
887 0 : schicken = I915_READ(SOUTH_CHICKEN1);
888 0 : if (panel->backlight.alternate_pwm_increment)
889 0 : schicken |= SPT_PWM_GRANULARITY;
890 : else
891 0 : schicken &= ~SPT_PWM_GRANULARITY;
892 0 : I915_WRITE(SOUTH_CHICKEN1, schicken);
893 : }
894 :
895 0 : pch_ctl2 = panel->backlight.max << 16;
896 0 : I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
897 :
898 : pch_ctl1 = 0;
899 0 : if (panel->backlight.active_low_pwm)
900 0 : pch_ctl1 |= BLM_PCH_POLARITY;
901 :
902 : /* After LPT, override is the default. */
903 0 : if (HAS_PCH_LPT(dev_priv))
904 0 : pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
905 :
906 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
907 0 : POSTING_READ(BLC_PWM_PCH_CTL1);
908 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
909 :
910 : /* This won't stick until the above enable. */
911 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
912 0 : }
913 :
914 0 : static void pch_enable_backlight(struct intel_connector *connector)
915 : {
916 0 : struct drm_device *dev = connector->base.dev;
917 0 : struct drm_i915_private *dev_priv = dev->dev_private;
918 0 : struct intel_panel *panel = &connector->panel;
919 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
920 : enum transcoder cpu_transcoder =
921 0 : intel_pipe_to_cpu_transcoder(dev_priv, pipe);
922 : u32 cpu_ctl2, pch_ctl1, pch_ctl2;
923 :
924 0 : cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
925 0 : if (cpu_ctl2 & BLM_PWM_ENABLE) {
926 : DRM_DEBUG_KMS("cpu backlight already enabled\n");
927 0 : cpu_ctl2 &= ~BLM_PWM_ENABLE;
928 0 : I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
929 0 : }
930 :
931 0 : pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
932 0 : if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
933 : DRM_DEBUG_KMS("pch backlight already enabled\n");
934 0 : pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
935 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
936 0 : }
937 :
938 0 : if (cpu_transcoder == TRANSCODER_EDP)
939 0 : cpu_ctl2 = BLM_TRANSCODER_EDP;
940 : else
941 0 : cpu_ctl2 = BLM_PIPE(cpu_transcoder);
942 0 : I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
943 0 : POSTING_READ(BLC_PWM_CPU_CTL2);
944 0 : I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
945 :
946 : /* This won't stick until the above enable. */
947 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
948 :
949 0 : pch_ctl2 = panel->backlight.max << 16;
950 0 : I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
951 :
952 : pch_ctl1 = 0;
953 0 : if (panel->backlight.active_low_pwm)
954 0 : pch_ctl1 |= BLM_PCH_POLARITY;
955 :
956 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
957 0 : POSTING_READ(BLC_PWM_PCH_CTL1);
958 0 : I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
959 0 : }
960 :
961 0 : static void i9xx_enable_backlight(struct intel_connector *connector)
962 : {
963 0 : struct drm_device *dev = connector->base.dev;
964 0 : struct drm_i915_private *dev_priv = dev->dev_private;
965 0 : struct intel_panel *panel = &connector->panel;
966 : u32 ctl, freq;
967 :
968 0 : ctl = I915_READ(BLC_PWM_CTL);
969 0 : if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
970 : DRM_DEBUG_KMS("backlight already enabled\n");
971 0 : I915_WRITE(BLC_PWM_CTL, 0);
972 0 : }
973 :
974 0 : freq = panel->backlight.max;
975 0 : if (panel->backlight.combination_mode)
976 0 : freq /= 0xff;
977 :
978 0 : ctl = freq << 17;
979 0 : if (panel->backlight.combination_mode)
980 0 : ctl |= BLM_LEGACY_MODE;
981 0 : if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
982 0 : ctl |= BLM_POLARITY_PNV;
983 :
984 0 : I915_WRITE(BLC_PWM_CTL, ctl);
985 0 : POSTING_READ(BLC_PWM_CTL);
986 :
987 : /* XXX: combine this into above write? */
988 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
989 :
990 : /*
991 : * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is
992 : * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
993 : * that has backlight.
994 : */
995 0 : if (IS_GEN2(dev))
996 0 : I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
997 0 : }
998 :
999 0 : static void i965_enable_backlight(struct intel_connector *connector)
1000 : {
1001 0 : struct drm_device *dev = connector->base.dev;
1002 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1003 0 : struct intel_panel *panel = &connector->panel;
1004 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
1005 : u32 ctl, ctl2, freq;
1006 :
1007 0 : ctl2 = I915_READ(BLC_PWM_CTL2);
1008 0 : if (ctl2 & BLM_PWM_ENABLE) {
1009 : DRM_DEBUG_KMS("backlight already enabled\n");
1010 0 : ctl2 &= ~BLM_PWM_ENABLE;
1011 0 : I915_WRITE(BLC_PWM_CTL2, ctl2);
1012 0 : }
1013 :
1014 0 : freq = panel->backlight.max;
1015 0 : if (panel->backlight.combination_mode)
1016 0 : freq /= 0xff;
1017 :
1018 0 : ctl = freq << 16;
1019 0 : I915_WRITE(BLC_PWM_CTL, ctl);
1020 :
1021 0 : ctl2 = BLM_PIPE(pipe);
1022 0 : if (panel->backlight.combination_mode)
1023 0 : ctl2 |= BLM_COMBINATION_MODE;
1024 0 : if (panel->backlight.active_low_pwm)
1025 0 : ctl2 |= BLM_POLARITY_I965;
1026 0 : I915_WRITE(BLC_PWM_CTL2, ctl2);
1027 0 : POSTING_READ(BLC_PWM_CTL2);
1028 0 : I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
1029 :
1030 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
1031 0 : }
1032 :
1033 0 : static void vlv_enable_backlight(struct intel_connector *connector)
1034 : {
1035 0 : struct drm_device *dev = connector->base.dev;
1036 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1037 0 : struct intel_panel *panel = &connector->panel;
1038 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
1039 : u32 ctl, ctl2;
1040 :
1041 0 : if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
1042 0 : return;
1043 :
1044 0 : ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
1045 0 : if (ctl2 & BLM_PWM_ENABLE) {
1046 : DRM_DEBUG_KMS("backlight already enabled\n");
1047 0 : ctl2 &= ~BLM_PWM_ENABLE;
1048 0 : I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
1049 0 : }
1050 :
1051 0 : ctl = panel->backlight.max << 16;
1052 0 : I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
1053 :
1054 : /* XXX: combine this into above write? */
1055 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
1056 :
1057 : ctl2 = 0;
1058 0 : if (panel->backlight.active_low_pwm)
1059 0 : ctl2 |= BLM_POLARITY_I965;
1060 0 : I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
1061 0 : POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
1062 0 : I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
1063 0 : }
1064 :
1065 0 : static void bxt_enable_backlight(struct intel_connector *connector)
1066 : {
1067 0 : struct drm_device *dev = connector->base.dev;
1068 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1069 0 : struct intel_panel *panel = &connector->panel;
1070 0 : enum pipe pipe = intel_get_pipe_from_connector(connector);
1071 : u32 pwm_ctl, val;
1072 :
1073 : /* To use 2nd set of backlight registers, utility pin has to be
1074 : * enabled with PWM mode.
1075 : * The field should only be changed when the utility pin is disabled
1076 : */
1077 0 : if (panel->backlight.controller == 1) {
1078 0 : val = I915_READ(UTIL_PIN_CTL);
1079 0 : if (val & UTIL_PIN_ENABLE) {
1080 : DRM_DEBUG_KMS("util pin already enabled\n");
1081 0 : val &= ~UTIL_PIN_ENABLE;
1082 0 : I915_WRITE(UTIL_PIN_CTL, val);
1083 0 : }
1084 :
1085 : val = 0;
1086 0 : if (panel->backlight.util_pin_active_low)
1087 0 : val |= UTIL_PIN_POLARITY;
1088 0 : I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) |
1089 : UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE);
1090 0 : }
1091 :
1092 0 : pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1093 0 : if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
1094 : DRM_DEBUG_KMS("backlight already enabled\n");
1095 0 : pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
1096 0 : I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1097 : pwm_ctl);
1098 0 : }
1099 :
1100 0 : I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller),
1101 : panel->backlight.max);
1102 :
1103 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
1104 :
1105 : pwm_ctl = 0;
1106 0 : if (panel->backlight.active_low_pwm)
1107 0 : pwm_ctl |= BXT_BLC_PWM_POLARITY;
1108 :
1109 0 : I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl);
1110 0 : POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1111 0 : I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1112 : pwm_ctl | BXT_BLC_PWM_ENABLE);
1113 0 : }
1114 :
1115 0 : static void pwm_enable_backlight(struct intel_connector *connector)
1116 : {
1117 0 : struct intel_panel *panel = &connector->panel;
1118 :
1119 0 : pwm_enable(panel->backlight.pwm);
1120 0 : intel_panel_actually_set_backlight(connector, panel->backlight.level);
1121 0 : }
1122 :
1123 0 : void intel_panel_enable_backlight(struct intel_connector *connector)
1124 : {
1125 0 : struct drm_device *dev = connector->base.dev;
1126 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1127 0 : struct intel_panel *panel = &connector->panel;
1128 : #ifdef DRMDEBUG
1129 : enum pipe pipe = intel_get_pipe_from_connector(connector);
1130 : #endif
1131 :
1132 0 : if (!panel->backlight.present)
1133 0 : return;
1134 :
1135 : DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
1136 :
1137 0 : mutex_lock(&dev_priv->backlight_lock);
1138 :
1139 0 : WARN_ON(panel->backlight.max == 0);
1140 :
1141 0 : if (panel->backlight.level <= panel->backlight.min) {
1142 0 : panel->backlight.level = panel->backlight.max;
1143 0 : if (panel->backlight.device)
1144 0 : panel->backlight.device->props.brightness =
1145 0 : scale_hw_to_user(connector,
1146 : panel->backlight.level,
1147 0 : panel->backlight.device->props.max_brightness);
1148 : }
1149 :
1150 0 : panel->backlight.enable(connector);
1151 0 : panel->backlight.enabled = true;
1152 0 : if (panel->backlight.device)
1153 0 : panel->backlight.device->props.power = FB_BLANK_UNBLANK;
1154 :
1155 0 : mutex_unlock(&dev_priv->backlight_lock);
1156 0 : }
1157 :
1158 : #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
1159 0 : static int intel_backlight_device_update_status(struct backlight_device *bd)
1160 : {
1161 0 : struct intel_connector *connector = bl_get_data(bd);
1162 0 : struct intel_panel *panel = &connector->panel;
1163 0 : struct drm_device *dev = connector->base.dev;
1164 :
1165 0 : drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1166 : DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
1167 : bd->props.brightness, bd->props.max_brightness);
1168 0 : intel_panel_set_backlight(connector, bd->props.brightness,
1169 0 : bd->props.max_brightness);
1170 :
1171 : /*
1172 : * Allow flipping bl_power as a sub-state of enabled. Sadly the
1173 : * backlight class device does not make it easy to to differentiate
1174 : * between callbacks for brightness and bl_power, so our backlight_power
1175 : * callback needs to take this into account.
1176 : */
1177 0 : if (panel->backlight.enabled) {
1178 0 : if (panel->backlight.power) {
1179 0 : bool enable = bd->props.power == FB_BLANK_UNBLANK &&
1180 0 : bd->props.brightness != 0;
1181 0 : panel->backlight.power(connector, enable);
1182 0 : }
1183 : } else {
1184 0 : bd->props.power = FB_BLANK_POWERDOWN;
1185 : }
1186 :
1187 0 : drm_modeset_unlock(&dev->mode_config.connection_mutex);
1188 0 : return 0;
1189 : }
1190 :
1191 0 : static int intel_backlight_device_get_brightness(struct backlight_device *bd)
1192 : {
1193 0 : struct intel_connector *connector = bl_get_data(bd);
1194 0 : struct drm_device *dev = connector->base.dev;
1195 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1196 : u32 hw_level;
1197 : int ret;
1198 :
1199 0 : intel_runtime_pm_get(dev_priv);
1200 0 : drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1201 :
1202 0 : hw_level = intel_panel_get_backlight(connector);
1203 0 : ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
1204 :
1205 0 : drm_modeset_unlock(&dev->mode_config.connection_mutex);
1206 0 : intel_runtime_pm_put(dev_priv);
1207 :
1208 0 : return ret;
1209 : }
1210 :
1211 : static const struct backlight_ops intel_backlight_device_ops = {
1212 : .update_status = intel_backlight_device_update_status,
1213 : .get_brightness = intel_backlight_device_get_brightness,
1214 : };
1215 :
1216 0 : static int intel_backlight_device_register(struct intel_connector *connector)
1217 : {
1218 0 : struct intel_panel *panel = &connector->panel;
1219 0 : struct backlight_properties props;
1220 :
1221 0 : if (WARN_ON(panel->backlight.device))
1222 0 : return -ENODEV;
1223 :
1224 0 : if (!panel->backlight.present)
1225 0 : return 0;
1226 :
1227 0 : WARN_ON(panel->backlight.max == 0);
1228 :
1229 0 : memset(&props, 0, sizeof(props));
1230 0 : props.type = BACKLIGHT_RAW;
1231 :
1232 : /*
1233 : * Note: Everything should work even if the backlight device max
1234 : * presented to the userspace is arbitrarily chosen.
1235 : */
1236 0 : props.max_brightness = panel->backlight.max;
1237 0 : props.brightness = scale_hw_to_user(connector,
1238 0 : panel->backlight.level,
1239 : props.max_brightness);
1240 :
1241 0 : if (panel->backlight.enabled)
1242 0 : props.power = FB_BLANK_UNBLANK;
1243 : else
1244 0 : props.power = FB_BLANK_POWERDOWN;
1245 :
1246 : /*
1247 : * Note: using the same name independent of the connector prevents
1248 : * registration of multiple backlight devices in the driver.
1249 : */
1250 0 : panel->backlight.device =
1251 0 : backlight_device_register("intel_backlight",
1252 0 : connector->base.kdev,
1253 0 : connector,
1254 : &intel_backlight_device_ops, &props);
1255 :
1256 0 : if (IS_ERR(panel->backlight.device)) {
1257 0 : DRM_ERROR("Failed to register backlight: %ld\n",
1258 : PTR_ERR(panel->backlight.device));
1259 0 : panel->backlight.device = NULL;
1260 0 : return -ENODEV;
1261 : }
1262 :
1263 : DRM_DEBUG_KMS("Connector %s backlight sysfs interface registered\n",
1264 : connector->base.name);
1265 :
1266 0 : return 0;
1267 0 : }
1268 :
1269 0 : static void intel_backlight_device_unregister(struct intel_connector *connector)
1270 : {
1271 0 : struct intel_panel *panel = &connector->panel;
1272 :
1273 0 : if (panel->backlight.device) {
1274 0 : backlight_device_unregister(panel->backlight.device);
1275 0 : panel->backlight.device = NULL;
1276 0 : }
1277 0 : }
1278 : #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1279 : static int intel_backlight_device_register(struct intel_connector *connector)
1280 : {
1281 : return 0;
1282 : }
1283 : static void intel_backlight_device_unregister(struct intel_connector *connector)
1284 : {
1285 : }
1286 : #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1287 :
1288 : /*
1289 : * SPT: This value represents the period of the PWM stream in clock periods
1290 : * multiplied by 16 (default increment) or 128 (alternate increment selected in
1291 : * SCHICKEN_1 bit 0). PWM clock is 24 MHz.
1292 : */
1293 0 : static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1294 : {
1295 0 : struct drm_device *dev = connector->base.dev;
1296 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1297 : u32 mul, clock;
1298 :
1299 0 : if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
1300 0 : mul = 128;
1301 : else
1302 : mul = 16;
1303 :
1304 : clock = MHz(24);
1305 :
1306 0 : return clock / (pwm_freq_hz * mul);
1307 : }
1308 :
1309 : /*
1310 : * LPT: This value represents the period of the PWM stream in clock periods
1311 : * multiplied by 128 (default increment) or 16 (alternate increment, selected in
1312 : * LPT SOUTH_CHICKEN2 register bit 5).
1313 : */
1314 0 : static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1315 : {
1316 0 : struct drm_device *dev = connector->base.dev;
1317 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1318 : u32 mul, clock;
1319 :
1320 0 : if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY)
1321 0 : mul = 16;
1322 : else
1323 : mul = 128;
1324 :
1325 0 : if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
1326 0 : clock = MHz(135); /* LPT:H */
1327 : else
1328 : clock = MHz(24); /* LPT:LP */
1329 :
1330 0 : return clock / (pwm_freq_hz * mul);
1331 : }
1332 :
1333 : /*
1334 : * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH
1335 : * display raw clocks multiplied by 128.
1336 : */
1337 0 : static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1338 : {
1339 0 : struct drm_device *dev = connector->base.dev;
1340 0 : int clock = MHz(intel_pch_rawclk(dev));
1341 :
1342 0 : return clock / (pwm_freq_hz * 128);
1343 : }
1344 :
1345 : /*
1346 : * Gen2: This field determines the number of time base events (display core
1347 : * clock frequency/32) in total for a complete cycle of modulated backlight
1348 : * control.
1349 : *
1350 : * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock)
1351 : * divided by 32.
1352 : */
1353 0 : static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1354 : {
1355 0 : struct drm_device *dev = connector->base.dev;
1356 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1357 : int clock;
1358 :
1359 0 : if (IS_PINEVIEW(dev))
1360 0 : clock = intel_hrawclk(dev);
1361 : else
1362 0 : clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
1363 :
1364 0 : return clock / (pwm_freq_hz * 32);
1365 : }
1366 :
1367 : /*
1368 : * Gen4: This value represents the period of the PWM stream in display core
1369 : * clocks multiplied by 128.
1370 : */
1371 0 : static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1372 : {
1373 0 : struct drm_device *dev = connector->base.dev;
1374 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1375 0 : int clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
1376 :
1377 0 : return clock / (pwm_freq_hz * 128);
1378 : }
1379 :
1380 : /*
1381 : * VLV: This value represents the period of the PWM stream in display core
1382 : * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
1383 : * multiplied by 16. CHV uses a 19.2MHz S0IX clock.
1384 : */
1385 0 : static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1386 : {
1387 0 : struct drm_device *dev = connector->base.dev;
1388 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1389 : int clock;
1390 :
1391 0 : if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
1392 0 : if (IS_CHERRYVIEW(dev))
1393 0 : return KHz(19200) / (pwm_freq_hz * 16);
1394 : else
1395 0 : return MHz(25) / (pwm_freq_hz * 16);
1396 : } else {
1397 0 : clock = intel_hrawclk(dev);
1398 0 : return MHz(clock) / (pwm_freq_hz * 128);
1399 : }
1400 0 : }
1401 :
1402 0 : static u32 get_backlight_max_vbt(struct intel_connector *connector)
1403 : {
1404 0 : struct drm_device *dev = connector->base.dev;
1405 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1406 0 : struct intel_panel *panel = &connector->panel;
1407 0 : u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
1408 : u32 pwm;
1409 :
1410 0 : if (!pwm_freq_hz) {
1411 : DRM_DEBUG_KMS("backlight frequency not specified in VBT\n");
1412 0 : return 0;
1413 : }
1414 :
1415 0 : if (!panel->backlight.hz_to_pwm) {
1416 : DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n");
1417 0 : return 0;
1418 : }
1419 :
1420 0 : pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz);
1421 0 : if (!pwm) {
1422 : DRM_DEBUG_KMS("backlight frequency conversion failed\n");
1423 0 : return 0;
1424 : }
1425 :
1426 : DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz);
1427 :
1428 0 : return pwm;
1429 0 : }
1430 :
1431 : /*
1432 : * Note: The setup hooks can't assume pipe is set!
1433 : */
1434 0 : static u32 get_backlight_min_vbt(struct intel_connector *connector)
1435 : {
1436 0 : struct drm_device *dev = connector->base.dev;
1437 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1438 0 : struct intel_panel *panel = &connector->panel;
1439 : int min;
1440 :
1441 0 : WARN_ON(panel->backlight.max == 0);
1442 :
1443 : /*
1444 : * XXX: If the vbt value is 255, it makes min equal to max, which leads
1445 : * to problems. There are such machines out there. Either our
1446 : * interpretation is wrong or the vbt has bogus data. Or both. Safeguard
1447 : * against this by letting the minimum be at most (arbitrarily chosen)
1448 : * 25% of the max.
1449 : */
1450 0 : min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64);
1451 : if (min != dev_priv->vbt.backlight.min_brightness) {
1452 : DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n",
1453 : dev_priv->vbt.backlight.min_brightness, min);
1454 : }
1455 :
1456 : /* vbt value is a coefficient in range [0..255] */
1457 0 : return scale(min, 0, 255, 0, panel->backlight.max);
1458 : }
1459 :
1460 0 : static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
1461 : {
1462 0 : struct drm_device *dev = connector->base.dev;
1463 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1464 0 : struct intel_panel *panel = &connector->panel;
1465 : u32 pch_ctl1, pch_ctl2, val;
1466 : bool alt;
1467 :
1468 0 : if (HAS_PCH_LPT(dev))
1469 0 : alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY;
1470 : else
1471 0 : alt = I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY;
1472 0 : panel->backlight.alternate_pwm_increment = alt;
1473 :
1474 0 : pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1475 0 : panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1476 :
1477 0 : pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1478 0 : panel->backlight.max = pch_ctl2 >> 16;
1479 :
1480 0 : if (!panel->backlight.max)
1481 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1482 :
1483 0 : if (!panel->backlight.max)
1484 0 : return -ENODEV;
1485 :
1486 0 : panel->backlight.min = get_backlight_min_vbt(connector);
1487 :
1488 0 : val = lpt_get_backlight(connector);
1489 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1490 :
1491 0 : panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
1492 0 : panel->backlight.level != 0;
1493 :
1494 0 : return 0;
1495 0 : }
1496 :
1497 0 : static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused)
1498 : {
1499 0 : struct drm_device *dev = connector->base.dev;
1500 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1501 0 : struct intel_panel *panel = &connector->panel;
1502 : u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
1503 :
1504 0 : pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1505 0 : panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1506 :
1507 0 : pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1508 0 : panel->backlight.max = pch_ctl2 >> 16;
1509 :
1510 0 : if (!panel->backlight.max)
1511 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1512 :
1513 0 : if (!panel->backlight.max)
1514 0 : return -ENODEV;
1515 :
1516 0 : panel->backlight.min = get_backlight_min_vbt(connector);
1517 :
1518 0 : val = pch_get_backlight(connector);
1519 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1520 :
1521 0 : cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
1522 0 : panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
1523 0 : (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
1524 :
1525 0 : return 0;
1526 0 : }
1527 :
1528 0 : static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused)
1529 : {
1530 0 : struct drm_device *dev = connector->base.dev;
1531 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1532 0 : struct intel_panel *panel = &connector->panel;
1533 : u32 ctl, val;
1534 :
1535 0 : ctl = I915_READ(BLC_PWM_CTL);
1536 :
1537 0 : if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
1538 0 : panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
1539 :
1540 0 : if (IS_PINEVIEW(dev))
1541 0 : panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
1542 :
1543 0 : panel->backlight.max = ctl >> 17;
1544 :
1545 0 : if (!panel->backlight.max) {
1546 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1547 0 : panel->backlight.max >>= 1;
1548 0 : }
1549 :
1550 0 : if (!panel->backlight.max)
1551 0 : return -ENODEV;
1552 :
1553 0 : if (panel->backlight.combination_mode)
1554 0 : panel->backlight.max *= 0xff;
1555 :
1556 0 : panel->backlight.min = get_backlight_min_vbt(connector);
1557 :
1558 0 : val = i9xx_get_backlight(connector);
1559 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1560 :
1561 0 : panel->backlight.enabled = panel->backlight.level != 0;
1562 :
1563 0 : return 0;
1564 0 : }
1565 :
1566 0 : static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused)
1567 : {
1568 0 : struct drm_device *dev = connector->base.dev;
1569 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1570 0 : struct intel_panel *panel = &connector->panel;
1571 : u32 ctl, ctl2, val;
1572 :
1573 0 : ctl2 = I915_READ(BLC_PWM_CTL2);
1574 0 : panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1575 0 : panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1576 :
1577 0 : ctl = I915_READ(BLC_PWM_CTL);
1578 0 : panel->backlight.max = ctl >> 16;
1579 :
1580 0 : if (!panel->backlight.max)
1581 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1582 :
1583 0 : if (!panel->backlight.max)
1584 0 : return -ENODEV;
1585 :
1586 0 : if (panel->backlight.combination_mode)
1587 0 : panel->backlight.max *= 0xff;
1588 :
1589 0 : panel->backlight.min = get_backlight_min_vbt(connector);
1590 :
1591 0 : val = i9xx_get_backlight(connector);
1592 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1593 :
1594 0 : panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1595 0 : panel->backlight.level != 0;
1596 :
1597 0 : return 0;
1598 0 : }
1599 :
1600 0 : static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe)
1601 : {
1602 0 : struct drm_device *dev = connector->base.dev;
1603 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1604 0 : struct intel_panel *panel = &connector->panel;
1605 : u32 ctl, ctl2, val;
1606 :
1607 0 : if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
1608 0 : return -ENODEV;
1609 :
1610 0 : ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
1611 0 : panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1612 :
1613 0 : ctl = I915_READ(VLV_BLC_PWM_CTL(pipe));
1614 0 : panel->backlight.max = ctl >> 16;
1615 :
1616 0 : if (!panel->backlight.max)
1617 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1618 :
1619 0 : if (!panel->backlight.max)
1620 0 : return -ENODEV;
1621 :
1622 0 : panel->backlight.min = get_backlight_min_vbt(connector);
1623 :
1624 0 : val = _vlv_get_backlight(dev, pipe);
1625 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1626 :
1627 0 : panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1628 0 : panel->backlight.level != 0;
1629 :
1630 0 : return 0;
1631 0 : }
1632 :
1633 : static int
1634 0 : bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
1635 : {
1636 0 : struct drm_device *dev = connector->base.dev;
1637 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1638 0 : struct intel_panel *panel = &connector->panel;
1639 : u32 pwm_ctl, val;
1640 :
1641 : /*
1642 : * For BXT hard coding the Backlight controller to 0.
1643 : * TODO : Read the controller value from VBT and generalize
1644 : */
1645 0 : panel->backlight.controller = 0;
1646 :
1647 0 : pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1648 :
1649 : /* Keeping the check if controller 1 is to be programmed.
1650 : * This will come into affect once the VBT parsing
1651 : * is fixed for controller selection, and controller 1 is used
1652 : * for a prticular display configuration.
1653 : */
1654 0 : if (panel->backlight.controller == 1) {
1655 0 : val = I915_READ(UTIL_PIN_CTL);
1656 0 : panel->backlight.util_pin_active_low =
1657 0 : val & UTIL_PIN_POLARITY;
1658 0 : }
1659 :
1660 0 : panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
1661 0 : panel->backlight.max =
1662 0 : I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller));
1663 :
1664 0 : if (!panel->backlight.max)
1665 0 : panel->backlight.max = get_backlight_max_vbt(connector);
1666 :
1667 0 : if (!panel->backlight.max)
1668 0 : return -ENODEV;
1669 :
1670 0 : val = bxt_get_backlight(connector);
1671 0 : panel->backlight.level = intel_panel_compute_brightness(connector, val);
1672 :
1673 0 : panel->backlight.enabled = (pwm_ctl & BXT_BLC_PWM_ENABLE) &&
1674 0 : panel->backlight.level != 0;
1675 :
1676 0 : return 0;
1677 0 : }
1678 :
1679 0 : static int pwm_setup_backlight(struct intel_connector *connector,
1680 : enum pipe pipe)
1681 : {
1682 0 : struct drm_device *dev = connector->base.dev;
1683 0 : struct intel_panel *panel = &connector->panel;
1684 : int retval;
1685 :
1686 : /* Get the PWM chip for backlight control */
1687 0 : panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight");
1688 0 : if (IS_ERR(panel->backlight.pwm)) {
1689 0 : DRM_ERROR("Failed to own the pwm chip\n");
1690 0 : panel->backlight.pwm = NULL;
1691 0 : return -ENODEV;
1692 : }
1693 :
1694 0 : retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS,
1695 : CRC_PMIC_PWM_PERIOD_NS);
1696 0 : if (retval < 0) {
1697 0 : DRM_ERROR("Failed to configure the pwm chip\n");
1698 0 : pwm_put(panel->backlight.pwm);
1699 0 : panel->backlight.pwm = NULL;
1700 0 : return retval;
1701 : }
1702 :
1703 0 : panel->backlight.min = 0; /* 0% */
1704 0 : panel->backlight.max = 100; /* 100% */
1705 0 : panel->backlight.level = DIV_ROUND_UP(
1706 : pwm_get_duty_cycle(panel->backlight.pwm) * 100,
1707 : CRC_PMIC_PWM_PERIOD_NS);
1708 0 : panel->backlight.enabled = panel->backlight.level != 0;
1709 :
1710 0 : return 0;
1711 0 : }
1712 :
1713 0 : int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
1714 : {
1715 0 : struct drm_device *dev = connector->dev;
1716 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1717 0 : struct intel_connector *intel_connector = to_intel_connector(connector);
1718 0 : struct intel_panel *panel = &intel_connector->panel;
1719 : int ret;
1720 :
1721 0 : if (!dev_priv->vbt.backlight.present) {
1722 0 : if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
1723 : DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
1724 : } else {
1725 : DRM_DEBUG_KMS("no backlight present per VBT\n");
1726 0 : return 0;
1727 : }
1728 : }
1729 :
1730 : /* ensure intel_panel has been initialized first */
1731 0 : if (WARN_ON(!panel->backlight.setup))
1732 0 : return -ENODEV;
1733 :
1734 : /* set level and max in panel struct */
1735 0 : mutex_lock(&dev_priv->backlight_lock);
1736 0 : ret = panel->backlight.setup(intel_connector, pipe);
1737 0 : mutex_unlock(&dev_priv->backlight_lock);
1738 :
1739 0 : if (ret) {
1740 : DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1741 : connector->name);
1742 0 : return ret;
1743 : }
1744 :
1745 0 : panel->backlight.present = true;
1746 :
1747 : DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n",
1748 : connector->name,
1749 : panel->backlight.enabled ? "enabled" : "disabled",
1750 : panel->backlight.level, panel->backlight.max);
1751 :
1752 0 : return 0;
1753 0 : }
1754 :
1755 0 : void intel_panel_destroy_backlight(struct drm_connector *connector)
1756 : {
1757 0 : struct intel_connector *intel_connector = to_intel_connector(connector);
1758 0 : struct intel_panel *panel = &intel_connector->panel;
1759 :
1760 : /* dispose of the pwm */
1761 0 : if (panel->backlight.pwm)
1762 0 : pwm_put(panel->backlight.pwm);
1763 :
1764 0 : panel->backlight.present = false;
1765 0 : }
1766 :
1767 : /* Set up chip specific backlight functions */
1768 : static void
1769 0 : intel_panel_init_backlight_funcs(struct intel_panel *panel)
1770 : {
1771 : struct intel_connector *intel_connector =
1772 0 : container_of(panel, struct intel_connector, panel);
1773 0 : struct drm_device *dev = intel_connector->base.dev;
1774 0 : struct drm_i915_private *dev_priv = dev->dev_private;
1775 :
1776 0 : if (IS_BROXTON(dev)) {
1777 0 : panel->backlight.setup = bxt_setup_backlight;
1778 0 : panel->backlight.enable = bxt_enable_backlight;
1779 0 : panel->backlight.disable = bxt_disable_backlight;
1780 0 : panel->backlight.set = bxt_set_backlight;
1781 0 : panel->backlight.get = bxt_get_backlight;
1782 0 : } else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv) ||
1783 0 : HAS_PCH_KBP(dev_priv)) {
1784 0 : panel->backlight.setup = lpt_setup_backlight;
1785 0 : panel->backlight.enable = lpt_enable_backlight;
1786 0 : panel->backlight.disable = lpt_disable_backlight;
1787 0 : panel->backlight.set = lpt_set_backlight;
1788 0 : panel->backlight.get = lpt_get_backlight;
1789 0 : if (HAS_PCH_LPT(dev))
1790 0 : panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
1791 : else
1792 0 : panel->backlight.hz_to_pwm = spt_hz_to_pwm;
1793 0 : } else if (HAS_PCH_SPLIT(dev)) {
1794 0 : panel->backlight.setup = pch_setup_backlight;
1795 0 : panel->backlight.enable = pch_enable_backlight;
1796 0 : panel->backlight.disable = pch_disable_backlight;
1797 0 : panel->backlight.set = pch_set_backlight;
1798 0 : panel->backlight.get = pch_get_backlight;
1799 0 : panel->backlight.hz_to_pwm = pch_hz_to_pwm;
1800 0 : } else if (IS_VALLEYVIEW(dev)) {
1801 0 : if (dev_priv->vbt.has_mipi) {
1802 0 : panel->backlight.setup = pwm_setup_backlight;
1803 0 : panel->backlight.enable = pwm_enable_backlight;
1804 0 : panel->backlight.disable = pwm_disable_backlight;
1805 0 : panel->backlight.set = pwm_set_backlight;
1806 0 : panel->backlight.get = pwm_get_backlight;
1807 0 : } else {
1808 0 : panel->backlight.setup = vlv_setup_backlight;
1809 0 : panel->backlight.enable = vlv_enable_backlight;
1810 0 : panel->backlight.disable = vlv_disable_backlight;
1811 0 : panel->backlight.set = vlv_set_backlight;
1812 0 : panel->backlight.get = vlv_get_backlight;
1813 0 : panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
1814 : }
1815 0 : } else if (IS_GEN4(dev)) {
1816 0 : panel->backlight.setup = i965_setup_backlight;
1817 0 : panel->backlight.enable = i965_enable_backlight;
1818 0 : panel->backlight.disable = i965_disable_backlight;
1819 0 : panel->backlight.set = i9xx_set_backlight;
1820 0 : panel->backlight.get = i9xx_get_backlight;
1821 0 : panel->backlight.hz_to_pwm = i965_hz_to_pwm;
1822 0 : } else {
1823 0 : panel->backlight.setup = i9xx_setup_backlight;
1824 0 : panel->backlight.enable = i9xx_enable_backlight;
1825 0 : panel->backlight.disable = i9xx_disable_backlight;
1826 0 : panel->backlight.set = i9xx_set_backlight;
1827 0 : panel->backlight.get = i9xx_get_backlight;
1828 0 : panel->backlight.hz_to_pwm = i9xx_hz_to_pwm;
1829 : }
1830 0 : }
1831 :
1832 0 : int intel_panel_init(struct intel_panel *panel,
1833 : struct drm_display_mode *fixed_mode,
1834 : struct drm_display_mode *downclock_mode)
1835 : {
1836 0 : intel_panel_init_backlight_funcs(panel);
1837 :
1838 0 : panel->fixed_mode = fixed_mode;
1839 0 : panel->downclock_mode = downclock_mode;
1840 :
1841 0 : return 0;
1842 : }
1843 :
1844 0 : void intel_panel_fini(struct intel_panel *panel)
1845 : {
1846 : struct intel_connector *intel_connector =
1847 0 : container_of(panel, struct intel_connector, panel);
1848 :
1849 0 : if (panel->fixed_mode)
1850 0 : drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1851 :
1852 0 : if (panel->downclock_mode)
1853 0 : drm_mode_destroy(intel_connector->base.dev,
1854 : panel->downclock_mode);
1855 0 : }
1856 :
1857 0 : void intel_backlight_register(struct drm_device *dev)
1858 : {
1859 : struct intel_connector *connector;
1860 :
1861 0 : list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
1862 0 : intel_backlight_device_register(connector);
1863 0 : }
1864 :
1865 0 : void intel_backlight_unregister(struct drm_device *dev)
1866 : {
1867 : struct intel_connector *connector;
1868 :
1869 0 : list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
1870 0 : intel_backlight_device_unregister(connector);
1871 0 : }
|