2 * Copyright © 2006-2010 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
28 * Chris Wilson <chris@chris-wilson.co.uk>
31 #include <linux/moduleparam.h>
32 #include "intel_drv.h"
35 intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
36 struct drm_display_mode *adjusted_mode)
38 drm_mode_copy(adjusted_mode, fixed_mode);
40 drm_mode_set_crtcinfo(adjusted_mode, 0);
44 * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
46 * @fixed_mode : panel native mode
47 * @connector: LVDS/eDP connector
49 * Return downclock_avail
50 * Find the reduced downclock for LVDS/eDP in EDID.
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)
57 struct drm_display_mode *scan, *tmp_mode;
60 temp_downclock = fixed_mode->clock;
63 list_for_each_entry(scan, &connector->probed_modes, head) {
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.
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) {
81 * The downclock is already found. But we
82 * expect to find the lower downclock.
84 temp_downclock = scan->clock;
90 if (temp_downclock < fixed_mode->clock)
91 return drm_mode_duplicate(dev, tmp_mode);
96 /* adjusted_mode has been preset to be the panel's fixed mode */
98 intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
99 struct intel_crtc_config *pipe_config,
102 struct drm_display_mode *adjusted_mode;
103 int x, y, width, height;
105 adjusted_mode = &pipe_config->adjusted_mode;
107 x = y = width = height = 0;
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)
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;
122 case DRM_MODE_SCALE_ASPECT:
123 /* Scale but preserve the aspect ratio */
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;
133 x = (adjusted_mode->hdisplay - width + 1) / 2;
135 height = adjusted_mode->vdisplay;
136 } else if (scaled_width < scaled_height) { /* letter */
137 height = scaled_width / pipe_config->pipe_src_w;
140 y = (adjusted_mode->vdisplay - height + 1) / 2;
142 width = adjusted_mode->hdisplay;
145 width = adjusted_mode->hdisplay;
146 height = adjusted_mode->vdisplay;
151 case DRM_MODE_SCALE_FULLSCREEN:
153 width = adjusted_mode->hdisplay;
154 height = adjusted_mode->vdisplay;
158 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
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;
169 centre_horizontally(struct drm_display_mode *mode,
172 u32 border, sync_pos, blank_width, sync_width;
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;
179 border = (mode->hdisplay - width + 1) / 2;
180 border += border & 1; /* make the border even */
182 mode->crtc_hdisplay = width;
183 mode->crtc_hblank_start = width + border;
184 mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
186 mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
187 mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
191 centre_vertically(struct drm_display_mode *mode,
194 u32 border, sync_pos, blank_width, sync_width;
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;
201 border = (mode->vdisplay - height + 1) / 2;
203 mode->crtc_vdisplay = height;
204 mode->crtc_vblank_start = height + border;
205 mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
207 mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
208 mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
211 static inline u32 panel_fitter_scaling(u32 source, u32 target)
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.
219 #define FACTOR (1 << ACCURACY)
220 u32 ratio = source * FACTOR / target;
221 return (FACTOR * ratio + FACTOR/2) / FACTOR;
224 static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
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;
233 /* 965+ is easy, it does everything in hw */
234 if (scaled_width > scaled_height)
235 *pfit_control |= PFIT_ENABLE |
237 else if (scaled_width < scaled_height)
238 *pfit_control |= PFIT_ENABLE |
240 else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
241 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
244 static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
245 u32 *pfit_control, u32 *pfit_pgm_ratios,
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;
256 * For earlier chips we have to calculate the scaling
257 * ratio by hand and program it into the
258 * PFIT_PGM_RATIO register
260 if (scaled_width > scaled_height) { /* pillar */
261 centre_horizontally(adjusted_mode,
263 pipe_config->pipe_src_h);
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);
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);
276 } else if (scaled_width < scaled_height) { /* letter */
277 centre_vertically(adjusted_mode,
279 pipe_config->pipe_src_w);
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);
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);
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);
301 void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
302 struct intel_crtc_config *pipe_config,
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;
309 adjusted_mode = &pipe_config->adjusted_mode;
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)
316 switch (fitting_mode) {
317 case DRM_MODE_SCALE_CENTER:
319 * For centered modes, we have to calculate border widths &
320 * heights and modify the values programmed into the CRTC.
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;
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);
331 i9xx_scale_aspect(pipe_config, &pfit_control,
332 &pfit_pgm_ratios, &border);
334 case DRM_MODE_SCALE_FULLSCREEN:
336 * Full scaling, even if it changes the aspect ratio.
337 * Fortunately this is all done for us in hw.
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;
345 pfit_control |= (VERT_AUTO_SCALE |
346 VERT_INTERP_BILINEAR |
348 HORIZ_INTERP_BILINEAR);
352 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
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) |
363 if ((pfit_control & PFIT_ENABLE) == 0) {
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;
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;
377 enum drm_connector_status
378 intel_panel_detect(struct drm_device *dev)
380 struct drm_i915_private *dev_priv = dev->dev_private;
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;
389 switch (i915.panel_ignore_lid) {
391 return connector_status_connected;
393 return connector_status_disconnected;
395 return connector_status_unknown;
399 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
402 struct drm_device *dev = connector->base.dev;
403 struct drm_i915_private *dev_priv = dev->dev_private;
404 struct intel_panel *panel = &connector->panel;
406 WARN_ON(panel->backlight.max == 0);
408 if (i915.invert_brightness < 0)
411 if (i915.invert_brightness > 0 ||
412 dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
413 return panel->backlight.max - val;
419 static u32 bdw_get_backlight(struct intel_connector *connector)
421 struct drm_device *dev = connector->base.dev;
422 struct drm_i915_private *dev_priv = dev->dev_private;
424 return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
427 static u32 pch_get_backlight(struct intel_connector *connector)
429 struct drm_device *dev = connector->base.dev;
430 struct drm_i915_private *dev_priv = dev->dev_private;
432 return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
435 static u32 i9xx_get_backlight(struct intel_connector *connector)
437 struct drm_device *dev = connector->base.dev;
438 struct drm_i915_private *dev_priv = dev->dev_private;
439 struct intel_panel *panel = &connector->panel;
442 val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
443 if (INTEL_INFO(dev)->gen < 4)
446 if (panel->backlight.combination_mode) {
449 pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
456 static u32 _vlv_get_backlight(struct drm_device *dev, enum i915_pipe pipe)
458 struct drm_i915_private *dev_priv = dev->dev_private;
460 return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
463 static u32 vlv_get_backlight(struct intel_connector *connector)
465 struct drm_device *dev = connector->base.dev;
466 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
468 return _vlv_get_backlight(dev, pipe);
472 static u32 intel_panel_get_backlight(struct intel_connector *connector)
474 struct drm_device *dev = connector->base.dev;
475 struct drm_i915_private *dev_priv = dev->dev_private;
479 spin_lock_irqsave(&dev_priv->backlight_lock, flags);
481 val = dev_priv->display.get_backlight(connector);
482 val = intel_panel_compute_brightness(connector, val);
484 spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
486 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
491 static void bdw_set_backlight(struct intel_connector *connector, u32 level)
493 struct drm_device *dev = connector->base.dev;
494 struct drm_i915_private *dev_priv = dev->dev_private;
495 u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
496 I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
499 static void pch_set_backlight(struct intel_connector *connector, u32 level)
501 struct drm_device *dev = connector->base.dev;
502 struct drm_i915_private *dev_priv = dev->dev_private;
505 tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
506 I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
509 static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
511 struct drm_device *dev = connector->base.dev;
512 struct drm_i915_private *dev_priv = dev->dev_private;
513 struct intel_panel *panel = &connector->panel;
516 WARN_ON(panel->backlight.max == 0);
518 if (panel->backlight.combination_mode) {
521 lbpc = level * 0xfe / panel->backlight.max + 1;
523 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
527 mask = BACKLIGHT_DUTY_CYCLE_MASK;
530 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
533 tmp = I915_READ(BLC_PWM_CTL) & ~mask;
534 I915_WRITE(BLC_PWM_CTL, tmp | level);
537 static void vlv_set_backlight(struct intel_connector *connector, u32 level)
539 struct drm_device *dev = connector->base.dev;
540 struct drm_i915_private *dev_priv = dev->dev_private;
541 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
544 tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
545 I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
549 intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
551 struct drm_device *dev = connector->base.dev;
552 struct drm_i915_private *dev_priv = dev->dev_private;
554 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
556 level = intel_panel_compute_brightness(connector, level);
557 dev_priv->display.set_backlight(connector, level);
560 /* set backlight brightness to level in range [0..max] */
561 void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
564 struct drm_device *dev = connector->base.dev;
565 struct drm_i915_private *dev_priv = dev->dev_private;
566 struct intel_panel *panel = &connector->panel;
567 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
570 if (!panel->backlight.present || pipe == INVALID_PIPE)
573 spin_lock(&dev_priv->backlight_lock);
575 WARN_ON(panel->backlight.max == 0);
577 /* scale to hardware max, but be careful to not overflow */
578 freq = panel->backlight.max;
580 level = level * freq / max;
582 level = freq / max * level;
584 panel->backlight.level = level;
585 if (panel->backlight.device)
586 panel->backlight.device->props.brightness = level;
588 if (panel->backlight.enabled)
589 intel_panel_actually_set_backlight(connector, level);
591 spin_unlock(&dev_priv->backlight_lock);
594 static void pch_disable_backlight(struct intel_connector *connector)
596 struct drm_device *dev = connector->base.dev;
597 struct drm_i915_private *dev_priv = dev->dev_private;
600 intel_panel_actually_set_backlight(connector, 0);
602 tmp = I915_READ(BLC_PWM_CPU_CTL2);
603 I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
605 tmp = I915_READ(BLC_PWM_PCH_CTL1);
606 I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
609 static void i9xx_disable_backlight(struct intel_connector *connector)
611 intel_panel_actually_set_backlight(connector, 0);
614 static void i965_disable_backlight(struct intel_connector *connector)
616 struct drm_device *dev = connector->base.dev;
617 struct drm_i915_private *dev_priv = dev->dev_private;
620 intel_panel_actually_set_backlight(connector, 0);
622 tmp = I915_READ(BLC_PWM_CTL2);
623 I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
626 static void vlv_disable_backlight(struct intel_connector *connector)
628 struct drm_device *dev = connector->base.dev;
629 struct drm_i915_private *dev_priv = dev->dev_private;
630 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
633 intel_panel_actually_set_backlight(connector, 0);
635 tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
636 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
639 void intel_panel_disable_backlight(struct intel_connector *connector)
641 struct drm_device *dev = connector->base.dev;
642 struct drm_i915_private *dev_priv = dev->dev_private;
643 struct intel_panel *panel = &connector->panel;
644 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
646 if (!panel->backlight.present || pipe == INVALID_PIPE)
650 * Do not disable backlight on the vgaswitcheroo path. When switching
651 * away from i915, the other client may depend on i915 to handle the
652 * backlight. This will leave the backlight on unnecessarily when
653 * another client is not activated.
655 if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
656 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
660 spin_lock(&dev_priv->backlight_lock);
662 panel->backlight.enabled = false;
663 dev_priv->display.disable_backlight(connector);
665 spin_unlock(&dev_priv->backlight_lock);
668 static void bdw_enable_backlight(struct intel_connector *connector)
670 struct drm_device *dev = connector->base.dev;
671 struct drm_i915_private *dev_priv = dev->dev_private;
672 struct intel_panel *panel = &connector->panel;
673 u32 pch_ctl1, pch_ctl2;
675 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
676 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
677 DRM_DEBUG_KMS("pch backlight already enabled\n");
678 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
679 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
682 pch_ctl2 = panel->backlight.max << 16;
683 I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
686 if (panel->backlight.active_low_pwm)
687 pch_ctl1 |= BLM_PCH_POLARITY;
689 /* BDW always uses the pch pwm controls. */
690 pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
692 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
693 POSTING_READ(BLC_PWM_PCH_CTL1);
694 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
696 /* This won't stick until the above enable. */
697 intel_panel_actually_set_backlight(connector, panel->backlight.level);
700 static void pch_enable_backlight(struct intel_connector *connector)
702 struct drm_device *dev = connector->base.dev;
703 struct drm_i915_private *dev_priv = dev->dev_private;
704 struct intel_panel *panel = &connector->panel;
705 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
706 enum transcoder cpu_transcoder =
707 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
708 u32 cpu_ctl2, pch_ctl1, pch_ctl2;
710 cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
711 if (cpu_ctl2 & BLM_PWM_ENABLE) {
712 WARN(1, "cpu backlight already enabled\n");
713 cpu_ctl2 &= ~BLM_PWM_ENABLE;
714 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
717 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
718 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
719 DRM_DEBUG_KMS("pch backlight already enabled\n");
720 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
721 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
724 if (cpu_transcoder == TRANSCODER_EDP)
725 cpu_ctl2 = BLM_TRANSCODER_EDP;
727 cpu_ctl2 = BLM_PIPE(cpu_transcoder);
728 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
729 POSTING_READ(BLC_PWM_CPU_CTL2);
730 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
732 /* This won't stick until the above enable. */
733 intel_panel_actually_set_backlight(connector, panel->backlight.level);
735 pch_ctl2 = panel->backlight.max << 16;
736 I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
739 if (panel->backlight.active_low_pwm)
740 pch_ctl1 |= BLM_PCH_POLARITY;
742 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
743 POSTING_READ(BLC_PWM_PCH_CTL1);
744 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
747 static void i9xx_enable_backlight(struct intel_connector *connector)
749 struct drm_device *dev = connector->base.dev;
750 struct drm_i915_private *dev_priv = dev->dev_private;
751 struct intel_panel *panel = &connector->panel;
754 ctl = I915_READ(BLC_PWM_CTL);
755 if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
756 WARN(1, "backlight already enabled\n");
757 I915_WRITE(BLC_PWM_CTL, 0);
760 freq = panel->backlight.max;
761 if (panel->backlight.combination_mode)
765 if (panel->backlight.combination_mode)
766 ctl |= BLM_LEGACY_MODE;
767 if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
768 ctl |= BLM_POLARITY_PNV;
770 I915_WRITE(BLC_PWM_CTL, ctl);
771 POSTING_READ(BLC_PWM_CTL);
773 /* XXX: combine this into above write? */
774 intel_panel_actually_set_backlight(connector, panel->backlight.level);
777 static void i965_enable_backlight(struct intel_connector *connector)
779 struct drm_device *dev = connector->base.dev;
780 struct drm_i915_private *dev_priv = dev->dev_private;
781 struct intel_panel *panel = &connector->panel;
782 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
785 ctl2 = I915_READ(BLC_PWM_CTL2);
786 if (ctl2 & BLM_PWM_ENABLE) {
787 WARN(1, "backlight already enabled\n");
788 ctl2 &= ~BLM_PWM_ENABLE;
789 I915_WRITE(BLC_PWM_CTL2, ctl2);
792 freq = panel->backlight.max;
793 if (panel->backlight.combination_mode)
797 I915_WRITE(BLC_PWM_CTL, ctl);
799 ctl2 = BLM_PIPE(pipe);
800 if (panel->backlight.combination_mode)
801 ctl2 |= BLM_COMBINATION_MODE;
802 if (panel->backlight.active_low_pwm)
803 ctl2 |= BLM_POLARITY_I965;
804 I915_WRITE(BLC_PWM_CTL2, ctl2);
805 POSTING_READ(BLC_PWM_CTL2);
806 I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
808 intel_panel_actually_set_backlight(connector, panel->backlight.level);
811 static void vlv_enable_backlight(struct intel_connector *connector)
813 struct drm_device *dev = connector->base.dev;
814 struct drm_i915_private *dev_priv = dev->dev_private;
815 struct intel_panel *panel = &connector->panel;
816 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
819 ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
820 if (ctl2 & BLM_PWM_ENABLE) {
821 WARN(1, "backlight already enabled\n");
822 ctl2 &= ~BLM_PWM_ENABLE;
823 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
826 ctl = panel->backlight.max << 16;
827 I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
829 /* XXX: combine this into above write? */
830 intel_panel_actually_set_backlight(connector, panel->backlight.level);
833 if (panel->backlight.active_low_pwm)
834 ctl2 |= BLM_POLARITY_I965;
835 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
836 POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
837 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
840 void intel_panel_enable_backlight(struct intel_connector *connector)
842 struct drm_device *dev = connector->base.dev;
843 struct drm_i915_private *dev_priv = dev->dev_private;
844 struct intel_panel *panel = &connector->panel;
845 enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
847 if (!panel->backlight.present || pipe == INVALID_PIPE)
850 DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
852 spin_lock(&dev_priv->backlight_lock);
854 WARN_ON(panel->backlight.max == 0);
856 if (panel->backlight.level == 0) {
857 panel->backlight.level = panel->backlight.max;
858 if (panel->backlight.device)
859 panel->backlight.device->props.brightness =
860 panel->backlight.level;
863 dev_priv->display.enable_backlight(connector);
864 panel->backlight.enabled = true;
866 spin_unlock(&dev_priv->backlight_lock);
869 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
870 static int intel_backlight_device_update_status(struct backlight_device *bd)
872 struct intel_connector *connector = bl_get_data(bd);
873 struct drm_device *dev = connector->base.dev;
875 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
876 DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
877 bd->props.brightness, bd->props.max_brightness);
878 intel_panel_set_backlight(connector, bd->props.brightness,
879 bd->props.max_brightness);
880 drm_modeset_unlock(&dev->mode_config.connection_mutex);
884 static int intel_backlight_device_get_brightness(struct backlight_device *bd)
886 struct intel_connector *connector = bl_get_data(bd);
887 struct drm_device *dev = connector->base.dev;
888 struct drm_i915_private *dev_priv = dev->dev_private;
891 intel_runtime_pm_get(dev_priv);
892 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
893 ret = intel_panel_get_backlight(connector);
894 drm_modeset_unlock(&dev->mode_config.connection_mutex);
895 intel_runtime_pm_put(dev_priv);
900 static const struct backlight_ops intel_backlight_device_ops = {
901 .update_status = intel_backlight_device_update_status,
902 .get_brightness = intel_backlight_device_get_brightness,
905 static int intel_backlight_device_register(struct intel_connector *connector)
907 struct intel_panel *panel = &connector->panel;
908 struct backlight_properties props;
910 if (WARN_ON(panel->backlight.device))
913 BUG_ON(panel->backlight.max == 0);
915 memset(&props, 0, sizeof(props));
916 props.type = BACKLIGHT_RAW;
917 props.brightness = panel->backlight.level;
918 props.max_brightness = panel->backlight.max;
921 * Note: using the same name independent of the connector prevents
922 * registration of multiple backlight devices in the driver.
924 panel->backlight.device =
925 backlight_device_register("intel_backlight",
926 connector->base.kdev,
928 &intel_backlight_device_ops, &props);
930 if (IS_ERR(panel->backlight.device)) {
931 DRM_ERROR("Failed to register backlight: %ld\n",
932 PTR_ERR(panel->backlight.device));
933 panel->backlight.device = NULL;
939 static void intel_backlight_device_unregister(struct intel_connector *connector)
941 struct intel_panel *panel = &connector->panel;
943 if (panel->backlight.device) {
944 backlight_device_unregister(panel->backlight.device);
945 panel->backlight.device = NULL;
948 #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
949 static int intel_backlight_device_register(struct intel_connector *connector)
953 static void intel_backlight_device_unregister(struct intel_connector *connector)
956 #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
959 * Note: The setup hooks can't assume pipe is set!
961 * XXX: Query mode clock or hardware clock and program PWM modulation frequency
962 * appropriately when it's 0. Use VBT and/or sane defaults.
964 static int bdw_setup_backlight(struct intel_connector *connector)
966 struct drm_device *dev = connector->base.dev;
967 struct drm_i915_private *dev_priv = dev->dev_private;
968 struct intel_panel *panel = &connector->panel;
969 u32 pch_ctl1, pch_ctl2, val;
971 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
972 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
974 pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
975 panel->backlight.max = pch_ctl2 >> 16;
976 if (!panel->backlight.max)
979 val = bdw_get_backlight(connector);
980 panel->backlight.level = intel_panel_compute_brightness(connector, val);
982 panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
983 panel->backlight.level != 0;
988 static int pch_setup_backlight(struct intel_connector *connector)
990 struct drm_device *dev = connector->base.dev;
991 struct drm_i915_private *dev_priv = dev->dev_private;
992 struct intel_panel *panel = &connector->panel;
993 u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
995 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
996 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
998 pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
999 panel->backlight.max = pch_ctl2 >> 16;
1000 if (!panel->backlight.max)
1003 val = pch_get_backlight(connector);
1004 panel->backlight.level = intel_panel_compute_brightness(connector, val);
1006 cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
1007 panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
1008 (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
1013 static int i9xx_setup_backlight(struct intel_connector *connector)
1015 struct drm_device *dev = connector->base.dev;
1016 struct drm_i915_private *dev_priv = dev->dev_private;
1017 struct intel_panel *panel = &connector->panel;
1020 ctl = I915_READ(BLC_PWM_CTL);
1022 if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
1023 panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
1025 if (IS_PINEVIEW(dev))
1026 panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
1028 panel->backlight.max = ctl >> 17;
1029 if (panel->backlight.combination_mode)
1030 panel->backlight.max *= 0xff;
1032 if (!panel->backlight.max)
1035 val = i9xx_get_backlight(connector);
1036 panel->backlight.level = intel_panel_compute_brightness(connector, val);
1038 panel->backlight.enabled = panel->backlight.level != 0;
1043 static int i965_setup_backlight(struct intel_connector *connector)
1045 struct drm_device *dev = connector->base.dev;
1046 struct drm_i915_private *dev_priv = dev->dev_private;
1047 struct intel_panel *panel = &connector->panel;
1050 ctl2 = I915_READ(BLC_PWM_CTL2);
1051 panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1052 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1054 ctl = I915_READ(BLC_PWM_CTL);
1055 panel->backlight.max = ctl >> 16;
1056 if (panel->backlight.combination_mode)
1057 panel->backlight.max *= 0xff;
1059 if (!panel->backlight.max)
1062 val = i9xx_get_backlight(connector);
1063 panel->backlight.level = intel_panel_compute_brightness(connector, val);
1065 panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1066 panel->backlight.level != 0;
1071 static int vlv_setup_backlight(struct intel_connector *connector)
1073 struct drm_device *dev = connector->base.dev;
1074 struct drm_i915_private *dev_priv = dev->dev_private;
1075 struct intel_panel *panel = &connector->panel;
1076 enum i915_pipe pipe;
1079 for_each_pipe(pipe) {
1080 u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
1082 /* Skip if the modulation freq is already set */
1083 if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
1086 cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
1087 I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
1091 ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
1092 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1094 ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
1095 panel->backlight.max = ctl >> 16;
1096 if (!panel->backlight.max)
1099 val = _vlv_get_backlight(dev, PIPE_A);
1100 panel->backlight.level = intel_panel_compute_brightness(connector, val);
1102 panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1103 panel->backlight.level != 0;
1108 /* XXX: DragonFly-specific begin */
1110 * Read max backlight level
1113 sysctl_backlight_max(SYSCTL_HANDLER_ARGS)
1116 struct intel_connector *connector = arg1;
1117 struct drm_device *dev = connector->base.dev;
1118 struct drm_i915_private *dev_priv = dev->dev_private;
1119 struct intel_panel *panel = &connector->panel;
1121 spin_lock(&dev_priv->backlight_lock);
1122 val = panel->backlight.max;
1123 spin_unlock(&dev_priv->backlight_lock);
1125 err = sysctl_handle_int(oidp, &val, 0, req);
1130 * Read/write backlight level
1133 sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)
1135 struct intel_connector *connector = arg1;
1136 struct drm_device *dev = connector->base.dev;
1137 struct drm_i915_private *dev_priv = dev->dev_private;
1138 struct intel_panel *panel = &connector->panel;
1142 val = panel->backlight.level;
1144 spin_lock(&dev_priv->backlight_lock);
1145 max_brightness = panel->backlight.max;
1146 spin_unlock(&dev_priv->backlight_lock);
1148 err = sysctl_handle_int(oidp, &val, 0, req);
1149 if (err != 0 || req->newptr == NULL) {
1153 if (val != panel->backlight.level && val >=0 &&
1154 val <= max_brightness) {
1155 intel_panel_set_backlight(arg1, val, max_brightness);
1160 /* XXX: DragonFly-specific end */
1162 int intel_panel_setup_backlight(struct drm_connector *connector)
1164 struct drm_device *dev = connector->dev;
1165 struct drm_i915_private *dev_priv = dev->dev_private;
1166 struct intel_connector *intel_connector = to_intel_connector(connector);
1167 struct intel_panel *panel = &intel_connector->panel;
1170 if (!dev_priv->vbt.backlight.present) {
1171 if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
1172 DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
1174 DRM_DEBUG_KMS("no backlight present per VBT\n");
1179 /* set level and max in panel struct */
1180 spin_lock(&dev_priv->backlight_lock);
1181 ret = dev_priv->display.setup_backlight(intel_connector);
1182 spin_unlock(&dev_priv->backlight_lock);
1185 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1190 intel_backlight_device_register(intel_connector);
1192 panel->backlight.present = true;
1194 /* XXX: DragonFly-specific begin */
1195 SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1196 OID_AUTO, "backlight_max",
1197 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
1198 connector, sizeof(int),
1199 sysctl_backlight_max,
1200 "I", "Max backlight level");
1201 SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1202 OID_AUTO, "backlight_level",
1203 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
1204 connector, sizeof(int),
1205 sysctl_backlight_handler,
1206 "I", "Backlight level");
1207 /* XXX: DragonFly-specific end */
1209 DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
1210 "sysfs interface %sregistered\n",
1211 panel->backlight.enabled ? "enabled" : "disabled",
1212 panel->backlight.level, panel->backlight.max,
1213 panel->backlight.device ? "" : "not ");
1218 void intel_panel_destroy_backlight(struct drm_connector *connector)
1220 struct intel_connector *intel_connector = to_intel_connector(connector);
1221 struct intel_panel *panel = &intel_connector->panel;
1223 panel->backlight.present = false;
1224 intel_backlight_device_unregister(intel_connector);
1227 /* Set up chip specific backlight functions */
1228 void intel_panel_init_backlight_funcs(struct drm_device *dev)
1230 struct drm_i915_private *dev_priv = dev->dev_private;
1232 if (IS_BROADWELL(dev)) {
1233 dev_priv->display.setup_backlight = bdw_setup_backlight;
1234 dev_priv->display.enable_backlight = bdw_enable_backlight;
1235 dev_priv->display.disable_backlight = pch_disable_backlight;
1236 dev_priv->display.set_backlight = bdw_set_backlight;
1237 dev_priv->display.get_backlight = bdw_get_backlight;
1238 } else if (HAS_PCH_SPLIT(dev)) {
1239 dev_priv->display.setup_backlight = pch_setup_backlight;
1240 dev_priv->display.enable_backlight = pch_enable_backlight;
1241 dev_priv->display.disable_backlight = pch_disable_backlight;
1242 dev_priv->display.set_backlight = pch_set_backlight;
1243 dev_priv->display.get_backlight = pch_get_backlight;
1244 } else if (IS_VALLEYVIEW(dev)) {
1245 dev_priv->display.setup_backlight = vlv_setup_backlight;
1246 dev_priv->display.enable_backlight = vlv_enable_backlight;
1247 dev_priv->display.disable_backlight = vlv_disable_backlight;
1248 dev_priv->display.set_backlight = vlv_set_backlight;
1249 dev_priv->display.get_backlight = vlv_get_backlight;
1250 } else if (IS_GEN4(dev)) {
1251 dev_priv->display.setup_backlight = i965_setup_backlight;
1252 dev_priv->display.enable_backlight = i965_enable_backlight;
1253 dev_priv->display.disable_backlight = i965_disable_backlight;
1254 dev_priv->display.set_backlight = i9xx_set_backlight;
1255 dev_priv->display.get_backlight = i9xx_get_backlight;
1257 dev_priv->display.setup_backlight = i9xx_setup_backlight;
1258 dev_priv->display.enable_backlight = i9xx_enable_backlight;
1259 dev_priv->display.disable_backlight = i9xx_disable_backlight;
1260 dev_priv->display.set_backlight = i9xx_set_backlight;
1261 dev_priv->display.get_backlight = i9xx_get_backlight;
1265 int intel_panel_init(struct intel_panel *panel,
1266 struct drm_display_mode *fixed_mode,
1267 struct drm_display_mode *downclock_mode)
1269 panel->fixed_mode = fixed_mode;
1270 panel->downclock_mode = downclock_mode;
1275 void intel_panel_fini(struct intel_panel *panel)
1277 struct intel_connector *intel_connector =
1278 container_of(panel, struct intel_connector, panel);
1280 if (panel->fixed_mode)
1281 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1283 if (panel->downclock_mode)
1284 drm_mode_destroy(intel_connector->base.dev,
1285 panel->downclock_mode);