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