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