Merge branch 'vendor/LIBEDIT'
[dragonfly.git] / sys / dev / drm / i915 / intel_panel.c
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 #include <linux/moduleparam.h>
32 #include "intel_drv.h"
33
34 void
35 intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
36                        struct drm_display_mode *adjusted_mode)
37 {
38         drm_mode_copy(adjusted_mode, fixed_mode);
39
40         drm_mode_set_crtcinfo(adjusted_mode, 0);
41 }
42
43 /**
44  * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
45  * @dev: drm device
46  * @fixed_mode : panel native mode
47  * @connector: LVDS/eDP connector
48  *
49  * Return downclock_avail
50  * Find the reduced downclock for LVDS/eDP in EDID.
51  */
52 struct drm_display_mode *
53 intel_find_panel_downclock(struct drm_device *dev,
54                         struct drm_display_mode *fixed_mode,
55                         struct drm_connector *connector)
56 {
57         struct drm_display_mode *scan, *tmp_mode;
58         int temp_downclock;
59
60         temp_downclock = fixed_mode->clock;
61         tmp_mode = NULL;
62
63         list_for_each_entry(scan, &connector->probed_modes, head) {
64                 /*
65                  * If one mode has the same resolution with the fixed_panel
66                  * mode while they have the different refresh rate, it means
67                  * that the reduced downclock is found. In such
68                  * case we can set the different FPx0/1 to dynamically select
69                  * between low and high frequency.
70                  */
71                 if (scan->hdisplay == fixed_mode->hdisplay &&
72                     scan->hsync_start == fixed_mode->hsync_start &&
73                     scan->hsync_end == fixed_mode->hsync_end &&
74                     scan->htotal == fixed_mode->htotal &&
75                     scan->vdisplay == fixed_mode->vdisplay &&
76                     scan->vsync_start == fixed_mode->vsync_start &&
77                     scan->vsync_end == fixed_mode->vsync_end &&
78                     scan->vtotal == fixed_mode->vtotal) {
79                         if (scan->clock < temp_downclock) {
80                                 /*
81                                  * The downclock is already found. But we
82                                  * expect to find the lower downclock.
83                                  */
84                                 temp_downclock = scan->clock;
85                                 tmp_mode = scan;
86                         }
87                 }
88         }
89
90         if (temp_downclock < fixed_mode->clock)
91                 return drm_mode_duplicate(dev, tmp_mode);
92         else
93                 return NULL;
94 }
95
96 /* adjusted_mode has been preset to be the panel's fixed mode */
97 void
98 intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
99                         struct intel_crtc_config *pipe_config,
100                         int fitting_mode)
101 {
102         struct drm_display_mode *adjusted_mode;
103         int x, y, width, height;
104
105         adjusted_mode = &pipe_config->adjusted_mode;
106
107         x = y = width = height = 0;
108
109         /* Native modes don't need fitting */
110         if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
111             adjusted_mode->vdisplay == pipe_config->pipe_src_h)
112                 goto done;
113
114         switch (fitting_mode) {
115         case DRM_MODE_SCALE_CENTER:
116                 width = pipe_config->pipe_src_w;
117                 height = pipe_config->pipe_src_h;
118                 x = (adjusted_mode->hdisplay - width + 1)/2;
119                 y = (adjusted_mode->vdisplay - height + 1)/2;
120                 break;
121
122         case DRM_MODE_SCALE_ASPECT:
123                 /* Scale but preserve the aspect ratio */
124                 {
125                         u32 scaled_width = adjusted_mode->hdisplay
126                                 * pipe_config->pipe_src_h;
127                         u32 scaled_height = pipe_config->pipe_src_w
128                                 * adjusted_mode->vdisplay;
129                         if (scaled_width > scaled_height) { /* pillar */
130                                 width = scaled_height / pipe_config->pipe_src_h;
131                                 if (width & 1)
132                                         width++;
133                                 x = (adjusted_mode->hdisplay - width + 1) / 2;
134                                 y = 0;
135                                 height = adjusted_mode->vdisplay;
136                         } else if (scaled_width < scaled_height) { /* letter */
137                                 height = scaled_width / pipe_config->pipe_src_w;
138                                 if (height & 1)
139                                     height++;
140                                 y = (adjusted_mode->vdisplay - height + 1) / 2;
141                                 x = 0;
142                                 width = adjusted_mode->hdisplay;
143                         } else {
144                                 x = y = 0;
145                                 width = adjusted_mode->hdisplay;
146                                 height = adjusted_mode->vdisplay;
147                         }
148                 }
149                 break;
150
151         case DRM_MODE_SCALE_FULLSCREEN:
152                 x = y = 0;
153                 width = adjusted_mode->hdisplay;
154                 height = adjusted_mode->vdisplay;
155                 break;
156
157         default:
158                 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
159                 return;
160         }
161
162 done:
163         pipe_config->pch_pfit.pos = (x << 16) | y;
164         pipe_config->pch_pfit.size = (width << 16) | height;
165         pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
166 }
167
168 static void
169 centre_horizontally(struct drm_display_mode *mode,
170                     int width)
171 {
172         u32 border, sync_pos, blank_width, sync_width;
173
174         /* keep the hsync and hblank widths constant */
175         sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
176         blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
177         sync_pos = (blank_width - sync_width + 1) / 2;
178
179         border = (mode->hdisplay - width + 1) / 2;
180         border += border & 1; /* make the border even */
181
182         mode->crtc_hdisplay = width;
183         mode->crtc_hblank_start = width + border;
184         mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
185
186         mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
187         mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
188 }
189
190 static void
191 centre_vertically(struct drm_display_mode *mode,
192                   int height)
193 {
194         u32 border, sync_pos, blank_width, sync_width;
195
196         /* keep the vsync and vblank widths constant */
197         sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
198         blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
199         sync_pos = (blank_width - sync_width + 1) / 2;
200
201         border = (mode->vdisplay - height + 1) / 2;
202
203         mode->crtc_vdisplay = height;
204         mode->crtc_vblank_start = height + border;
205         mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
206
207         mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
208         mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
209 }
210
211 static inline u32 panel_fitter_scaling(u32 source, u32 target)
212 {
213         /*
214          * Floating point operation is not supported. So the FACTOR
215          * is defined, which can avoid the floating point computation
216          * when calculating the panel ratio.
217          */
218 #define ACCURACY 12
219 #define FACTOR (1 << ACCURACY)
220         u32 ratio = source * FACTOR / target;
221         return (FACTOR * ratio + FACTOR/2) / FACTOR;
222 }
223
224 static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
225                               u32 *pfit_control)
226 {
227         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
228         u32 scaled_width = adjusted_mode->hdisplay *
229                 pipe_config->pipe_src_h;
230         u32 scaled_height = pipe_config->pipe_src_w *
231                 adjusted_mode->vdisplay;
232
233         /* 965+ is easy, it does everything in hw */
234         if (scaled_width > scaled_height)
235                 *pfit_control |= PFIT_ENABLE |
236                         PFIT_SCALING_PILLAR;
237         else if (scaled_width < scaled_height)
238                 *pfit_control |= PFIT_ENABLE |
239                         PFIT_SCALING_LETTER;
240         else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
241                 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
242 }
243
244 static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
245                               u32 *pfit_control, u32 *pfit_pgm_ratios,
246                               u32 *border)
247 {
248         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
249         u32 scaled_width = adjusted_mode->hdisplay *
250                 pipe_config->pipe_src_h;
251         u32 scaled_height = pipe_config->pipe_src_w *
252                 adjusted_mode->vdisplay;
253         u32 bits;
254
255         /*
256          * For earlier chips we have to calculate the scaling
257          * ratio by hand and program it into the
258          * PFIT_PGM_RATIO register
259          */
260         if (scaled_width > scaled_height) { /* pillar */
261                 centre_horizontally(adjusted_mode,
262                                     scaled_height /
263                                     pipe_config->pipe_src_h);
264
265                 *border = LVDS_BORDER_ENABLE;
266                 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
267                         bits = panel_fitter_scaling(pipe_config->pipe_src_h,
268                                                     adjusted_mode->vdisplay);
269
270                         *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
271                                              bits << PFIT_VERT_SCALE_SHIFT);
272                         *pfit_control |= (PFIT_ENABLE |
273                                           VERT_INTERP_BILINEAR |
274                                           HORIZ_INTERP_BILINEAR);
275                 }
276         } else if (scaled_width < scaled_height) { /* letter */
277                 centre_vertically(adjusted_mode,
278                                   scaled_width /
279                                   pipe_config->pipe_src_w);
280
281                 *border = LVDS_BORDER_ENABLE;
282                 if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
283                         bits = panel_fitter_scaling(pipe_config->pipe_src_w,
284                                                     adjusted_mode->hdisplay);
285
286                         *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
287                                              bits << PFIT_VERT_SCALE_SHIFT);
288                         *pfit_control |= (PFIT_ENABLE |
289                                           VERT_INTERP_BILINEAR |
290                                           HORIZ_INTERP_BILINEAR);
291                 }
292         } else {
293                 /* Aspects match, Let hw scale both directions */
294                 *pfit_control |= (PFIT_ENABLE |
295                                   VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
296                                   VERT_INTERP_BILINEAR |
297                                   HORIZ_INTERP_BILINEAR);
298         }
299 }
300
301 void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
302                               struct intel_crtc_config *pipe_config,
303                               int fitting_mode)
304 {
305         struct drm_device *dev = intel_crtc->base.dev;
306         u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
307         struct drm_display_mode *adjusted_mode;
308
309         adjusted_mode = &pipe_config->adjusted_mode;
310
311         /* Native modes don't need fitting */
312         if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
313             adjusted_mode->vdisplay == pipe_config->pipe_src_h)
314                 goto out;
315
316         switch (fitting_mode) {
317         case DRM_MODE_SCALE_CENTER:
318                 /*
319                  * For centered modes, we have to calculate border widths &
320                  * heights and modify the values programmed into the CRTC.
321                  */
322                 centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
323                 centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
324                 border = LVDS_BORDER_ENABLE;
325                 break;
326         case DRM_MODE_SCALE_ASPECT:
327                 /* Scale but preserve the aspect ratio */
328                 if (INTEL_INFO(dev)->gen >= 4)
329                         i965_scale_aspect(pipe_config, &pfit_control);
330                 else
331                         i9xx_scale_aspect(pipe_config, &pfit_control,
332                                           &pfit_pgm_ratios, &border);
333                 break;
334         case DRM_MODE_SCALE_FULLSCREEN:
335                 /*
336                  * Full scaling, even if it changes the aspect ratio.
337                  * Fortunately this is all done for us in hw.
338                  */
339                 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
340                     pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
341                         pfit_control |= PFIT_ENABLE;
342                         if (INTEL_INFO(dev)->gen >= 4)
343                                 pfit_control |= PFIT_SCALING_AUTO;
344                         else
345                                 pfit_control |= (VERT_AUTO_SCALE |
346                                                  VERT_INTERP_BILINEAR |
347                                                  HORIZ_AUTO_SCALE |
348                                                  HORIZ_INTERP_BILINEAR);
349                 }
350                 break;
351         default:
352                 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
353                 return;
354         }
355
356         /* 965+ wants fuzzy fitting */
357         /* FIXME: handle multiple panels by failing gracefully */
358         if (INTEL_INFO(dev)->gen >= 4)
359                 pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
360                                  PFIT_FILTER_FUZZY);
361
362 out:
363         if ((pfit_control & PFIT_ENABLE) == 0) {
364                 pfit_control = 0;
365                 pfit_pgm_ratios = 0;
366         }
367
368         /* Make sure pre-965 set dither correctly for 18bpp panels. */
369         if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
370                 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
371
372         pipe_config->gmch_pfit.control = pfit_control;
373         pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
374         pipe_config->gmch_pfit.lvds_border_bits = border;
375 }
376
377 enum drm_connector_status
378 intel_panel_detect(struct drm_device *dev)
379 {
380         struct drm_i915_private *dev_priv = dev->dev_private;
381
382         /* Assume that the BIOS does not lie through the OpRegion... */
383         if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
384                 return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
385                         connector_status_connected :
386                         connector_status_disconnected;
387         }
388
389         switch (i915.panel_ignore_lid) {
390         case -2:
391                 return connector_status_connected;
392         case -1:
393                 return connector_status_disconnected;
394         default:
395                 return connector_status_unknown;
396         }
397 }
398
399 /**
400  * scale - scale values from one range to another
401  *
402  * @source_val: value in range [@source_min..@source_max]
403  *
404  * Return @source_val in range [@source_min..@source_max] scaled to range
405  * [@target_min..@target_max].
406  */
407 static uint32_t scale(uint32_t source_val,
408                       uint32_t source_min, uint32_t source_max,
409                       uint32_t target_min, uint32_t target_max)
410 {
411         uint64_t target_val;
412
413         WARN_ON(source_min > source_max);
414         WARN_ON(target_min > target_max);
415
416         /* defensive */
417         source_val = clamp(source_val, source_min, source_max);
418
419         /* avoid overflows */
420         target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) *
421                         (target_max - target_min), source_max - source_min);
422         target_val += target_min;
423
424         return target_val;
425 }
426
427 /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
428 static inline u32 scale_user_to_hw(struct intel_connector *connector,
429                                    u32 user_level, u32 user_max)
430 {
431         struct intel_panel *panel = &connector->panel;
432
433         return scale(user_level, 0, user_max,
434                      panel->backlight.min, panel->backlight.max);
435 }
436
437 /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
438  * to [hw_min..hw_max]. */
439 static inline u32 clamp_user_to_hw(struct intel_connector *connector,
440                                    u32 user_level, u32 user_max)
441 {
442         struct intel_panel *panel = &connector->panel;
443         u32 hw_level;
444
445         hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
446         hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
447
448         return hw_level;
449 }
450
451 /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
452 static inline u32 scale_hw_to_user(struct intel_connector *connector,
453                                    u32 hw_level, u32 user_max)
454 {
455         struct intel_panel *panel = &connector->panel;
456
457         return scale(hw_level, panel->backlight.min, panel->backlight.max,
458                      0, user_max);
459 }
460
461 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
462                                           u32 val)
463 {
464         struct drm_device *dev = connector->base.dev;
465         struct drm_i915_private *dev_priv = dev->dev_private;
466         struct intel_panel *panel = &connector->panel;
467
468         WARN_ON(panel->backlight.max == 0);
469
470         if (i915.invert_brightness < 0)
471                 return val;
472
473         if (i915.invert_brightness > 0 ||
474             dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
475                 return panel->backlight.max - val;
476         }
477
478         return val;
479 }
480
481 static u32 bdw_get_backlight(struct intel_connector *connector)
482 {
483         struct drm_device *dev = connector->base.dev;
484         struct drm_i915_private *dev_priv = dev->dev_private;
485
486         return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
487 }
488
489 static u32 pch_get_backlight(struct intel_connector *connector)
490 {
491         struct drm_device *dev = connector->base.dev;
492         struct drm_i915_private *dev_priv = dev->dev_private;
493
494         return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
495 }
496
497 static u32 i9xx_get_backlight(struct intel_connector *connector)
498 {
499         struct drm_device *dev = connector->base.dev;
500         struct drm_i915_private *dev_priv = dev->dev_private;
501         struct intel_panel *panel = &connector->panel;
502         u32 val;
503
504         val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
505         if (INTEL_INFO(dev)->gen < 4)
506                 val >>= 1;
507
508         if (panel->backlight.combination_mode) {
509                 u8 lbpc;
510
511                 pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
512                 val *= lbpc;
513         }
514
515         return val;
516 }
517
518 static u32 _vlv_get_backlight(struct drm_device *dev, enum i915_pipe pipe)
519 {
520         struct drm_i915_private *dev_priv = dev->dev_private;
521
522         return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
523 }
524
525 static u32 vlv_get_backlight(struct intel_connector *connector)
526 {
527         struct drm_device *dev = connector->base.dev;
528         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
529
530         return _vlv_get_backlight(dev, pipe);
531 }
532
533 #if 0
534 static u32 intel_panel_get_backlight(struct intel_connector *connector)
535 {
536         struct drm_device *dev = connector->base.dev;
537         struct drm_i915_private *dev_priv = dev->dev_private;
538         u32 val;
539         unsigned long flags;
540
541         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
542
543         val = dev_priv->display.get_backlight(connector);
544         val = intel_panel_compute_brightness(connector, val);
545
546         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
547
548         DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
549         return val;
550 }
551 #endif
552
553 static void bdw_set_backlight(struct intel_connector *connector, u32 level)
554 {
555         struct drm_device *dev = connector->base.dev;
556         struct drm_i915_private *dev_priv = dev->dev_private;
557         u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
558         I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
559 }
560
561 static void pch_set_backlight(struct intel_connector *connector, u32 level)
562 {
563         struct drm_device *dev = connector->base.dev;
564         struct drm_i915_private *dev_priv = dev->dev_private;
565         u32 tmp;
566
567         tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
568         I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
569 }
570
571 static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
572 {
573         struct drm_device *dev = connector->base.dev;
574         struct drm_i915_private *dev_priv = dev->dev_private;
575         struct intel_panel *panel = &connector->panel;
576         u32 tmp, mask;
577
578         WARN_ON(panel->backlight.max == 0);
579
580         if (panel->backlight.combination_mode) {
581                 u8 lbpc;
582
583                 lbpc = level * 0xfe / panel->backlight.max + 1;
584                 level /= lbpc;
585                 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
586         }
587
588         if (IS_GEN4(dev)) {
589                 mask = BACKLIGHT_DUTY_CYCLE_MASK;
590         } else {
591                 level <<= 1;
592                 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
593         }
594
595         tmp = I915_READ(BLC_PWM_CTL) & ~mask;
596         I915_WRITE(BLC_PWM_CTL, tmp | level);
597 }
598
599 static void vlv_set_backlight(struct intel_connector *connector, u32 level)
600 {
601         struct drm_device *dev = connector->base.dev;
602         struct drm_i915_private *dev_priv = dev->dev_private;
603         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
604         u32 tmp;
605
606         tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
607         I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
608 }
609
610 static void
611 intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
612 {
613         struct drm_device *dev = connector->base.dev;
614         struct drm_i915_private *dev_priv = dev->dev_private;
615
616         DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
617
618         level = intel_panel_compute_brightness(connector, level);
619         dev_priv->display.set_backlight(connector, level);
620 }
621
622 /* set backlight brightness to level in range [0..max], scaling wrt hw min */
623 static void intel_panel_set_backlight(struct intel_connector *connector,
624                                       u32 user_level, u32 user_max)
625 {
626         struct drm_device *dev = connector->base.dev;
627         struct drm_i915_private *dev_priv = dev->dev_private;
628         struct intel_panel *panel = &connector->panel;
629         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
630         u32 hw_level;
631
632         if (!panel->backlight.present || pipe == INVALID_PIPE)
633                 return;
634
635         spin_lock(&dev_priv->backlight_lock);
636
637         WARN_ON(panel->backlight.max == 0);
638
639         hw_level = scale_user_to_hw(connector, user_level, user_max);
640         panel->backlight.level = hw_level;
641
642         if (panel->backlight.enabled)
643                 intel_panel_actually_set_backlight(connector, hw_level);
644
645         spin_unlock(&dev_priv->backlight_lock);
646 }
647
648 /* set backlight brightness to level in range [0..max], assuming hw min is
649  * respected.
650  */
651 void intel_panel_set_backlight_acpi(struct intel_connector *connector,
652                                     u32 user_level, u32 user_max)
653 {
654         struct drm_device *dev = connector->base.dev;
655         struct drm_i915_private *dev_priv = dev->dev_private;
656         struct intel_panel *panel = &connector->panel;
657         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
658         u32 hw_level;
659
660         if (!panel->backlight.present || pipe == INVALID_PIPE)
661                 return;
662
663         spin_lock(&dev_priv->backlight_lock);
664
665         WARN_ON(panel->backlight.max == 0);
666
667         hw_level = clamp_user_to_hw(connector, user_level, user_max);
668         panel->backlight.level = hw_level;
669
670         if (panel->backlight.device)
671                 panel->backlight.device->props.brightness =
672                         scale_hw_to_user(connector,
673                                          panel->backlight.level,
674                                          panel->backlight.device->props.max_brightness);
675
676         if (panel->backlight.enabled)
677                 intel_panel_actually_set_backlight(connector, hw_level);
678
679         spin_unlock(&dev_priv->backlight_lock);
680 }
681
682 static void pch_disable_backlight(struct intel_connector *connector)
683 {
684         struct drm_device *dev = connector->base.dev;
685         struct drm_i915_private *dev_priv = dev->dev_private;
686         u32 tmp;
687
688         intel_panel_actually_set_backlight(connector, 0);
689
690         tmp = I915_READ(BLC_PWM_CPU_CTL2);
691         I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
692
693         tmp = I915_READ(BLC_PWM_PCH_CTL1);
694         I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
695 }
696
697 static void i9xx_disable_backlight(struct intel_connector *connector)
698 {
699         intel_panel_actually_set_backlight(connector, 0);
700 }
701
702 static void i965_disable_backlight(struct intel_connector *connector)
703 {
704         struct drm_device *dev = connector->base.dev;
705         struct drm_i915_private *dev_priv = dev->dev_private;
706         u32 tmp;
707
708         intel_panel_actually_set_backlight(connector, 0);
709
710         tmp = I915_READ(BLC_PWM_CTL2);
711         I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
712 }
713
714 static void vlv_disable_backlight(struct intel_connector *connector)
715 {
716         struct drm_device *dev = connector->base.dev;
717         struct drm_i915_private *dev_priv = dev->dev_private;
718         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
719         u32 tmp;
720
721         intel_panel_actually_set_backlight(connector, 0);
722
723         tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
724         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
725 }
726
727 void intel_panel_disable_backlight(struct intel_connector *connector)
728 {
729         struct drm_device *dev = connector->base.dev;
730         struct drm_i915_private *dev_priv = dev->dev_private;
731         struct intel_panel *panel = &connector->panel;
732         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
733
734         if (!panel->backlight.present || pipe == INVALID_PIPE)
735                 return;
736
737         /*
738          * Do not disable backlight on the vgaswitcheroo path. When switching
739          * away from i915, the other client may depend on i915 to handle the
740          * backlight. This will leave the backlight on unnecessarily when
741          * another client is not activated.
742          */
743         if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
744                 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
745                 return;
746         }
747
748         spin_lock(&dev_priv->backlight_lock);
749
750         if (panel->backlight.device)
751                 panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
752         panel->backlight.enabled = false;
753         dev_priv->display.disable_backlight(connector);
754
755         spin_unlock(&dev_priv->backlight_lock);
756 }
757
758 static void bdw_enable_backlight(struct intel_connector *connector)
759 {
760         struct drm_device *dev = connector->base.dev;
761         struct drm_i915_private *dev_priv = dev->dev_private;
762         struct intel_panel *panel = &connector->panel;
763         u32 pch_ctl1, pch_ctl2;
764
765         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
766         if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
767                 DRM_DEBUG_KMS("pch backlight already enabled\n");
768                 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
769                 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
770         }
771
772         pch_ctl2 = panel->backlight.max << 16;
773         I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
774
775         pch_ctl1 = 0;
776         if (panel->backlight.active_low_pwm)
777                 pch_ctl1 |= BLM_PCH_POLARITY;
778
779         /* BDW always uses the pch pwm controls. */
780         pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
781
782         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
783         POSTING_READ(BLC_PWM_PCH_CTL1);
784         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
785
786         /* This won't stick until the above enable. */
787         intel_panel_actually_set_backlight(connector, panel->backlight.level);
788 }
789
790 static void pch_enable_backlight(struct intel_connector *connector)
791 {
792         struct drm_device *dev = connector->base.dev;
793         struct drm_i915_private *dev_priv = dev->dev_private;
794         struct intel_panel *panel = &connector->panel;
795         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
796         enum transcoder cpu_transcoder =
797                 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
798         u32 cpu_ctl2, pch_ctl1, pch_ctl2;
799
800         cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
801         if (cpu_ctl2 & BLM_PWM_ENABLE) {
802                 DRM_DEBUG_KMS("cpu backlight already enabled\n");
803                 cpu_ctl2 &= ~BLM_PWM_ENABLE;
804                 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
805         }
806
807         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
808         if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
809                 DRM_DEBUG_KMS("pch backlight already enabled\n");
810                 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
811                 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
812         }
813
814         if (cpu_transcoder == TRANSCODER_EDP)
815                 cpu_ctl2 = BLM_TRANSCODER_EDP;
816         else
817                 cpu_ctl2 = BLM_PIPE(cpu_transcoder);
818         I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
819         POSTING_READ(BLC_PWM_CPU_CTL2);
820         I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
821
822         /* This won't stick until the above enable. */
823         intel_panel_actually_set_backlight(connector, panel->backlight.level);
824
825         pch_ctl2 = panel->backlight.max << 16;
826         I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
827
828         pch_ctl1 = 0;
829         if (panel->backlight.active_low_pwm)
830                 pch_ctl1 |= BLM_PCH_POLARITY;
831
832         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
833         POSTING_READ(BLC_PWM_PCH_CTL1);
834         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
835 }
836
837 static void i9xx_enable_backlight(struct intel_connector *connector)
838 {
839         struct drm_device *dev = connector->base.dev;
840         struct drm_i915_private *dev_priv = dev->dev_private;
841         struct intel_panel *panel = &connector->panel;
842         u32 ctl, freq;
843
844         ctl = I915_READ(BLC_PWM_CTL);
845         if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
846                 DRM_DEBUG_KMS("backlight already enabled\n");
847                 I915_WRITE(BLC_PWM_CTL, 0);
848         }
849
850         freq = panel->backlight.max;
851         if (panel->backlight.combination_mode)
852                 freq /= 0xff;
853
854         ctl = freq << 17;
855         if (panel->backlight.combination_mode)
856                 ctl |= BLM_LEGACY_MODE;
857         if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
858                 ctl |= BLM_POLARITY_PNV;
859
860         I915_WRITE(BLC_PWM_CTL, ctl);
861         POSTING_READ(BLC_PWM_CTL);
862
863         /* XXX: combine this into above write? */
864         intel_panel_actually_set_backlight(connector, panel->backlight.level);
865 }
866
867 static void i965_enable_backlight(struct intel_connector *connector)
868 {
869         struct drm_device *dev = connector->base.dev;
870         struct drm_i915_private *dev_priv = dev->dev_private;
871         struct intel_panel *panel = &connector->panel;
872         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
873         u32 ctl, ctl2, freq;
874
875         ctl2 = I915_READ(BLC_PWM_CTL2);
876         if (ctl2 & BLM_PWM_ENABLE) {
877                 DRM_DEBUG_KMS("backlight already enabled\n");
878                 ctl2 &= ~BLM_PWM_ENABLE;
879                 I915_WRITE(BLC_PWM_CTL2, ctl2);
880         }
881
882         freq = panel->backlight.max;
883         if (panel->backlight.combination_mode)
884                 freq /= 0xff;
885
886         ctl = freq << 16;
887         I915_WRITE(BLC_PWM_CTL, ctl);
888
889         ctl2 = BLM_PIPE(pipe);
890         if (panel->backlight.combination_mode)
891                 ctl2 |= BLM_COMBINATION_MODE;
892         if (panel->backlight.active_low_pwm)
893                 ctl2 |= BLM_POLARITY_I965;
894         I915_WRITE(BLC_PWM_CTL2, ctl2);
895         POSTING_READ(BLC_PWM_CTL2);
896         I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
897
898         intel_panel_actually_set_backlight(connector, panel->backlight.level);
899 }
900
901 static void vlv_enable_backlight(struct intel_connector *connector)
902 {
903         struct drm_device *dev = connector->base.dev;
904         struct drm_i915_private *dev_priv = dev->dev_private;
905         struct intel_panel *panel = &connector->panel;
906         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
907         u32 ctl, ctl2;
908
909         ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
910         if (ctl2 & BLM_PWM_ENABLE) {
911                 DRM_DEBUG_KMS("backlight already enabled\n");
912                 ctl2 &= ~BLM_PWM_ENABLE;
913                 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
914         }
915
916         ctl = panel->backlight.max << 16;
917         I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
918
919         /* XXX: combine this into above write? */
920         intel_panel_actually_set_backlight(connector, panel->backlight.level);
921
922         ctl2 = 0;
923         if (panel->backlight.active_low_pwm)
924                 ctl2 |= BLM_POLARITY_I965;
925         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
926         POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
927         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
928 }
929
930 void intel_panel_enable_backlight(struct intel_connector *connector)
931 {
932         struct drm_device *dev = connector->base.dev;
933         struct drm_i915_private *dev_priv = dev->dev_private;
934         struct intel_panel *panel = &connector->panel;
935         enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
936
937         if (!panel->backlight.present || pipe == INVALID_PIPE)
938                 return;
939
940         DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
941
942         spin_lock(&dev_priv->backlight_lock);
943
944         WARN_ON(panel->backlight.max == 0);
945
946         if (panel->backlight.level == 0) {
947                 panel->backlight.level = panel->backlight.max;
948                 if (panel->backlight.device)
949                         panel->backlight.device->props.brightness =
950                                 scale_hw_to_user(connector,
951                                                  panel->backlight.level,
952                                                  panel->backlight.device->props.max_brightness);
953         }
954
955         dev_priv->display.enable_backlight(connector);
956         panel->backlight.enabled = true;
957         if (panel->backlight.device)
958                 panel->backlight.device->props.power = FB_BLANK_UNBLANK;
959
960         spin_unlock(&dev_priv->backlight_lock);
961 }
962
963 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
964 static int intel_backlight_device_update_status(struct backlight_device *bd)
965 {
966         struct intel_connector *connector = bl_get_data(bd);
967         struct intel_panel *panel = &connector->panel;
968         struct drm_device *dev = connector->base.dev;
969
970         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
971         DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
972                       bd->props.brightness, bd->props.max_brightness);
973         intel_panel_set_backlight(connector, bd->props.brightness,
974                                   bd->props.max_brightness);
975
976         /*
977          * Allow flipping bl_power as a sub-state of enabled. Sadly the
978          * backlight class device does not make it easy to to differentiate
979          * between callbacks for brightness and bl_power, so our backlight_power
980          * callback needs to take this into account.
981          */
982         if (panel->backlight.enabled) {
983                 if (panel->backlight_power) {
984                         bool enable = bd->props.power == FB_BLANK_UNBLANK &&
985                                 bd->props.brightness != 0;
986                         panel->backlight_power(connector, enable);
987                 }
988         } else {
989                 bd->props.power = FB_BLANK_POWERDOWN;
990         }
991
992         drm_modeset_unlock(&dev->mode_config.connection_mutex);
993         return 0;
994 }
995
996 static int intel_backlight_device_get_brightness(struct backlight_device *bd)
997 {
998         struct intel_connector *connector = bl_get_data(bd);
999         struct drm_device *dev = connector->base.dev;
1000         struct drm_i915_private *dev_priv = dev->dev_private;
1001         u32 hw_level;
1002         int ret;
1003
1004         intel_runtime_pm_get(dev_priv);
1005         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1006
1007         hw_level = intel_panel_get_backlight(connector);
1008         ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
1009
1010         drm_modeset_unlock(&dev->mode_config.connection_mutex);
1011         intel_runtime_pm_put(dev_priv);
1012
1013         return ret;
1014 }
1015
1016 static const struct backlight_ops intel_backlight_device_ops = {
1017         .update_status = intel_backlight_device_update_status,
1018         .get_brightness = intel_backlight_device_get_brightness,
1019 };
1020
1021 static int intel_backlight_device_register(struct intel_connector *connector)
1022 {
1023         struct intel_panel *panel = &connector->panel;
1024         struct backlight_properties props;
1025
1026         if (WARN_ON(panel->backlight.device))
1027                 return -ENODEV;
1028
1029         WARN_ON(panel->backlight.max == 0);
1030
1031         memset(&props, 0, sizeof(props));
1032         props.type = BACKLIGHT_RAW;
1033
1034         /*
1035          * Note: Everything should work even if the backlight device max
1036          * presented to the userspace is arbitrarily chosen.
1037          */
1038         props.max_brightness = panel->backlight.max;
1039         props.brightness = scale_hw_to_user(connector,
1040                                             panel->backlight.level,
1041                                             props.max_brightness);
1042
1043         if (panel->backlight.enabled)
1044                 props.power = FB_BLANK_UNBLANK;
1045         else
1046                 props.power = FB_BLANK_POWERDOWN;
1047
1048         /*
1049          * Note: using the same name independent of the connector prevents
1050          * registration of multiple backlight devices in the driver.
1051          */
1052         panel->backlight.device =
1053                 backlight_device_register("intel_backlight",
1054                                           connector->base.kdev,
1055                                           connector,
1056                                           &intel_backlight_device_ops, &props);
1057
1058         if (IS_ERR(panel->backlight.device)) {
1059                 DRM_ERROR("Failed to register backlight: %ld\n",
1060                           PTR_ERR(panel->backlight.device));
1061                 panel->backlight.device = NULL;
1062                 return -ENODEV;
1063         }
1064         return 0;
1065 }
1066
1067 static void intel_backlight_device_unregister(struct intel_connector *connector)
1068 {
1069         struct intel_panel *panel = &connector->panel;
1070
1071         if (panel->backlight.device) {
1072                 backlight_device_unregister(panel->backlight.device);
1073                 panel->backlight.device = NULL;
1074         }
1075 }
1076 #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1077 static int intel_backlight_device_register(struct intel_connector *connector)
1078 {
1079         return 0;
1080 }
1081 static void intel_backlight_device_unregister(struct intel_connector *connector)
1082 {
1083 }
1084 #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1085
1086 /*
1087  * Note: The setup hooks can't assume pipe is set!
1088  *
1089  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
1090  * appropriately when it's 0. Use VBT and/or sane defaults.
1091  */
1092 static u32 get_backlight_min_vbt(struct intel_connector *connector)
1093 {
1094         struct drm_device *dev = connector->base.dev;
1095         struct drm_i915_private *dev_priv = dev->dev_private;
1096         struct intel_panel *panel = &connector->panel;
1097         int min;
1098
1099         WARN_ON(panel->backlight.max == 0);
1100
1101         /*
1102          * XXX: If the vbt value is 255, it makes min equal to max, which leads
1103          * to problems. There are such machines out there. Either our
1104          * interpretation is wrong or the vbt has bogus data. Or both. Safeguard
1105          * against this by letting the minimum be at most (arbitrarily chosen)
1106          * 25% of the max.
1107          */
1108         min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64);
1109         if (min != dev_priv->vbt.backlight.min_brightness) {
1110                 DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n",
1111                               dev_priv->vbt.backlight.min_brightness, min);
1112         }
1113
1114         /* vbt value is a coefficient in range [0..255] */
1115         return scale(min, 0, 255, 0, panel->backlight.max);
1116 }
1117
1118 static int bdw_setup_backlight(struct intel_connector *connector)
1119 {
1120         struct drm_device *dev = connector->base.dev;
1121         struct drm_i915_private *dev_priv = dev->dev_private;
1122         struct intel_panel *panel = &connector->panel;
1123         u32 pch_ctl1, pch_ctl2, val;
1124
1125         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1126         panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1127
1128         pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1129         panel->backlight.max = pch_ctl2 >> 16;
1130         if (!panel->backlight.max)
1131                 return -ENODEV;
1132
1133         panel->backlight.min = get_backlight_min_vbt(connector);
1134
1135         val = bdw_get_backlight(connector);
1136         panel->backlight.level = intel_panel_compute_brightness(connector, val);
1137
1138         panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
1139                 panel->backlight.level != 0;
1140
1141         return 0;
1142 }
1143
1144 static int pch_setup_backlight(struct intel_connector *connector)
1145 {
1146         struct drm_device *dev = connector->base.dev;
1147         struct drm_i915_private *dev_priv = dev->dev_private;
1148         struct intel_panel *panel = &connector->panel;
1149         u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
1150
1151         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1152         panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1153
1154         pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1155         panel->backlight.max = pch_ctl2 >> 16;
1156         if (!panel->backlight.max)
1157                 return -ENODEV;
1158
1159         panel->backlight.min = get_backlight_min_vbt(connector);
1160
1161         val = pch_get_backlight(connector);
1162         panel->backlight.level = intel_panel_compute_brightness(connector, val);
1163
1164         cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
1165         panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
1166                 (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
1167
1168         return 0;
1169 }
1170
1171 static int i9xx_setup_backlight(struct intel_connector *connector)
1172 {
1173         struct drm_device *dev = connector->base.dev;
1174         struct drm_i915_private *dev_priv = dev->dev_private;
1175         struct intel_panel *panel = &connector->panel;
1176         u32 ctl, val;
1177
1178         ctl = I915_READ(BLC_PWM_CTL);
1179
1180         if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
1181                 panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
1182
1183         if (IS_PINEVIEW(dev))
1184                 panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
1185
1186         panel->backlight.max = ctl >> 17;
1187         if (panel->backlight.combination_mode)
1188                 panel->backlight.max *= 0xff;
1189
1190         if (!panel->backlight.max)
1191                 return -ENODEV;
1192
1193         panel->backlight.min = get_backlight_min_vbt(connector);
1194
1195         val = i9xx_get_backlight(connector);
1196         panel->backlight.level = intel_panel_compute_brightness(connector, val);
1197
1198         panel->backlight.enabled = panel->backlight.level != 0;
1199
1200         return 0;
1201 }
1202
1203 static int i965_setup_backlight(struct intel_connector *connector)
1204 {
1205         struct drm_device *dev = connector->base.dev;
1206         struct drm_i915_private *dev_priv = dev->dev_private;
1207         struct intel_panel *panel = &connector->panel;
1208         u32 ctl, ctl2, val;
1209
1210         ctl2 = I915_READ(BLC_PWM_CTL2);
1211         panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1212         panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1213
1214         ctl = I915_READ(BLC_PWM_CTL);
1215         panel->backlight.max = ctl >> 16;
1216         if (panel->backlight.combination_mode)
1217                 panel->backlight.max *= 0xff;
1218
1219         if (!panel->backlight.max)
1220                 return -ENODEV;
1221
1222         panel->backlight.min = get_backlight_min_vbt(connector);
1223
1224         val = i9xx_get_backlight(connector);
1225         panel->backlight.level = intel_panel_compute_brightness(connector, val);
1226
1227         panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1228                 panel->backlight.level != 0;
1229
1230         return 0;
1231 }
1232
1233 static int vlv_setup_backlight(struct intel_connector *connector)
1234 {
1235         struct drm_device *dev = connector->base.dev;
1236         struct drm_i915_private *dev_priv = dev->dev_private;
1237         struct intel_panel *panel = &connector->panel;
1238         enum i915_pipe pipe;
1239         u32 ctl, ctl2, val;
1240
1241         for_each_pipe(dev_priv, pipe) {
1242                 u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
1243
1244                 /* Skip if the modulation freq is already set */
1245                 if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
1246                         continue;
1247
1248                 cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
1249                 I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
1250                            cur_val);
1251         }
1252
1253         ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
1254         panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1255
1256         ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
1257         panel->backlight.max = ctl >> 16;
1258         if (!panel->backlight.max)
1259                 return -ENODEV;
1260
1261         panel->backlight.min = get_backlight_min_vbt(connector);
1262
1263         val = _vlv_get_backlight(dev, PIPE_A);
1264         panel->backlight.level = intel_panel_compute_brightness(connector, val);
1265
1266         panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1267                 panel->backlight.level != 0;
1268
1269         return 0;
1270 }
1271
1272 #ifdef __DragonFly__
1273 /*
1274  * Read max backlight level
1275  */
1276 static int
1277 sysctl_backlight_max(SYSCTL_HANDLER_ARGS)
1278 {
1279         int err, val;
1280         struct intel_connector *connector = arg1;
1281         struct drm_device *dev = connector->base.dev;
1282         struct drm_i915_private *dev_priv = dev->dev_private;
1283         struct intel_panel *panel = &connector->panel;
1284
1285         spin_lock(&dev_priv->backlight_lock);
1286         val = panel->backlight.max;
1287         spin_unlock(&dev_priv->backlight_lock);
1288
1289         err = sysctl_handle_int(oidp, &val, 0, req);
1290         return(err);
1291 }
1292
1293 /*
1294  * Read/write backlight level
1295  */
1296 static int
1297 sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)
1298 {
1299         struct intel_connector *connector = arg1;
1300         struct drm_device *dev = connector->base.dev;
1301         struct drm_i915_private *dev_priv = dev->dev_private;
1302         struct intel_panel *panel = &connector->panel;
1303         int err, val;
1304         u32 max_brightness;
1305
1306         val = panel->backlight.level;
1307
1308         spin_lock(&dev_priv->backlight_lock);
1309         max_brightness = panel->backlight.max;
1310         spin_unlock(&dev_priv->backlight_lock);
1311
1312         err = sysctl_handle_int(oidp, &val, 0, req);
1313         if (err != 0 || req->newptr == NULL) {
1314                 return(err);
1315         }
1316
1317         if (val != panel->backlight.level && val >=0 &&
1318                         val <= max_brightness) {
1319                 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1320                 intel_panel_set_backlight(arg1, val, max_brightness);
1321                 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1322         }
1323
1324         return(err);
1325 }
1326 #endif /* __DragonFly__ */
1327
1328 int intel_panel_setup_backlight(struct drm_connector *connector)
1329 {
1330         struct drm_device *dev = connector->dev;
1331         struct drm_i915_private *dev_priv = dev->dev_private;
1332         struct intel_connector *intel_connector = to_intel_connector(connector);
1333         struct intel_panel *panel = &intel_connector->panel;
1334         int ret;
1335
1336         if (!dev_priv->vbt.backlight.present) {
1337                 if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
1338                         DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
1339                 } else {
1340                         DRM_DEBUG_KMS("no backlight present per VBT\n");
1341                         return 0;
1342                 }
1343         }
1344
1345         /* set level and max in panel struct */
1346         spin_lock(&dev_priv->backlight_lock);
1347         ret = dev_priv->display.setup_backlight(intel_connector);
1348         spin_unlock(&dev_priv->backlight_lock);
1349
1350         if (ret) {
1351                 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1352                               connector->name);
1353                 return ret;
1354         }
1355
1356         intel_backlight_device_register(intel_connector);
1357
1358         panel->backlight.present = true;
1359
1360 #ifdef __DragonFly__
1361         SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1362                         OID_AUTO, "backlight_max",
1363                         CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
1364                         connector, sizeof(int),
1365                         sysctl_backlight_max,
1366                         "I", "Max backlight level");
1367         SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1368                         OID_AUTO, "backlight_level",
1369                         CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
1370                         connector, sizeof(int),
1371                         sysctl_backlight_handler,
1372                         "I", "Backlight level");
1373 #endif
1374
1375         DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
1376                       "sysfs interface %sregistered\n",
1377                       panel->backlight.enabled ? "enabled" : "disabled",
1378                       panel->backlight.level, panel->backlight.max,
1379                       panel->backlight.device ? "" : "not ");
1380
1381         return 0;
1382 }
1383
1384 void intel_panel_destroy_backlight(struct drm_connector *connector)
1385 {
1386         struct intel_connector *intel_connector = to_intel_connector(connector);
1387         struct intel_panel *panel = &intel_connector->panel;
1388
1389         panel->backlight.present = false;
1390         intel_backlight_device_unregister(intel_connector);
1391 }
1392
1393 /* Set up chip specific backlight functions */
1394 void intel_panel_init_backlight_funcs(struct drm_device *dev)
1395 {
1396         struct drm_i915_private *dev_priv = dev->dev_private;
1397
1398         if (IS_BROADWELL(dev)) {
1399                 dev_priv->display.setup_backlight = bdw_setup_backlight;
1400                 dev_priv->display.enable_backlight = bdw_enable_backlight;
1401                 dev_priv->display.disable_backlight = pch_disable_backlight;
1402                 dev_priv->display.set_backlight = bdw_set_backlight;
1403                 dev_priv->display.get_backlight = bdw_get_backlight;
1404         } else if (HAS_PCH_SPLIT(dev)) {
1405                 dev_priv->display.setup_backlight = pch_setup_backlight;
1406                 dev_priv->display.enable_backlight = pch_enable_backlight;
1407                 dev_priv->display.disable_backlight = pch_disable_backlight;
1408                 dev_priv->display.set_backlight = pch_set_backlight;
1409                 dev_priv->display.get_backlight = pch_get_backlight;
1410         } else if (IS_VALLEYVIEW(dev)) {
1411                 dev_priv->display.setup_backlight = vlv_setup_backlight;
1412                 dev_priv->display.enable_backlight = vlv_enable_backlight;
1413                 dev_priv->display.disable_backlight = vlv_disable_backlight;
1414                 dev_priv->display.set_backlight = vlv_set_backlight;
1415                 dev_priv->display.get_backlight = vlv_get_backlight;
1416         } else if (IS_GEN4(dev)) {
1417                 dev_priv->display.setup_backlight = i965_setup_backlight;
1418                 dev_priv->display.enable_backlight = i965_enable_backlight;
1419                 dev_priv->display.disable_backlight = i965_disable_backlight;
1420                 dev_priv->display.set_backlight = i9xx_set_backlight;
1421                 dev_priv->display.get_backlight = i9xx_get_backlight;
1422         } else {
1423                 dev_priv->display.setup_backlight = i9xx_setup_backlight;
1424                 dev_priv->display.enable_backlight = i9xx_enable_backlight;
1425                 dev_priv->display.disable_backlight = i9xx_disable_backlight;
1426                 dev_priv->display.set_backlight = i9xx_set_backlight;
1427                 dev_priv->display.get_backlight = i9xx_get_backlight;
1428         }
1429 }
1430
1431 int intel_panel_init(struct intel_panel *panel,
1432                      struct drm_display_mode *fixed_mode,
1433                      struct drm_display_mode *downclock_mode)
1434 {
1435         panel->fixed_mode = fixed_mode;
1436         panel->downclock_mode = downclock_mode;
1437
1438         return 0;
1439 }
1440
1441 void intel_panel_fini(struct intel_panel *panel)
1442 {
1443         struct intel_connector *intel_connector =
1444                 container_of(panel, struct intel_connector, panel);
1445
1446         if (panel->fixed_mode)
1447                 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1448
1449         if (panel->downclock_mode)
1450                 drm_mode_destroy(intel_connector->base.dev,
1451                                 panel->downclock_mode);
1452 }