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/kernel.h> 32 #include <linux/pwm.h> 33 34 #include "intel_backlight.h" 35 #include "intel_connector.h" 36 #include "intel_de.h" 37 #include "intel_display_types.h" 38 #include "intel_panel.h" 39 40 bool intel_panel_use_ssc(struct drm_i915_private *i915) 41 { 42 if (i915->params.panel_use_ssc >= 0) 43 return i915->params.panel_use_ssc != 0; 44 return i915->vbt.lvds_use_ssc 45 && !(i915->quirks & QUIRK_LVDS_SSC_DISABLE); 46 } 47 48 int intel_panel_compute_config(struct intel_connector *connector, 49 struct drm_display_mode *adjusted_mode) 50 { 51 const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; 52 53 if (!fixed_mode) 54 return 0; 55 56 /* 57 * We don't want to lie too much to the user about the refresh 58 * rate they're going to get. But we have to allow a bit of latitude 59 * for Xorg since it likes to automagically cook up modes with slightly 60 * off refresh rates. 61 */ 62 if (abs(drm_mode_vrefresh(adjusted_mode) - drm_mode_vrefresh(fixed_mode)) > 1) { 63 drm_dbg_kms(connector->base.dev, 64 "[CONNECTOR:%d:%s] Requested mode vrefresh (%d Hz) does not match fixed mode vrefresh (%d Hz)\n", 65 connector->base.base.id, connector->base.name, 66 drm_mode_vrefresh(adjusted_mode), drm_mode_vrefresh(fixed_mode)); 67 68 return -EINVAL; 69 } 70 71 drm_mode_copy(adjusted_mode, fixed_mode); 72 73 drm_mode_set_crtcinfo(adjusted_mode, 0); 74 75 return 0; 76 } 77 78 static bool is_downclock_mode(const struct drm_display_mode *downclock_mode, 79 const struct drm_display_mode *fixed_mode) 80 { 81 return drm_mode_match(downclock_mode, fixed_mode, 82 DRM_MODE_MATCH_TIMINGS | 83 DRM_MODE_MATCH_FLAGS | 84 DRM_MODE_MATCH_3D_FLAGS) && 85 downclock_mode->clock < fixed_mode->clock; 86 } 87 88 struct drm_display_mode * 89 intel_panel_edid_downclock_mode(struct intel_connector *connector, 90 const struct drm_display_mode *fixed_mode) 91 { 92 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 93 const struct drm_display_mode *scan, *best_mode = NULL; 94 struct drm_display_mode *downclock_mode; 95 int best_clock = fixed_mode->clock; 96 97 list_for_each_entry(scan, &connector->base.probed_modes, head) { 98 /* 99 * If one mode has the same resolution with the fixed_panel 100 * mode while they have the different refresh rate, it means 101 * that the reduced downclock is found. In such 102 * case we can set the different FPx0/1 to dynamically select 103 * between low and high frequency. 104 */ 105 if (is_downclock_mode(scan, fixed_mode) && 106 scan->clock < best_clock) { 107 /* 108 * The downclock is already found. But we 109 * expect to find the lower downclock. 110 */ 111 best_clock = scan->clock; 112 best_mode = scan; 113 } 114 } 115 116 if (!best_mode) 117 return NULL; 118 119 downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode); 120 if (!downclock_mode) 121 return NULL; 122 123 drm_dbg_kms(&dev_priv->drm, 124 "[CONNECTOR:%d:%s] using downclock mode from EDID: ", 125 connector->base.base.id, connector->base.name); 126 drm_mode_debug_printmodeline(downclock_mode); 127 128 return downclock_mode; 129 } 130 131 struct drm_display_mode * 132 intel_panel_edid_fixed_mode(struct intel_connector *connector) 133 { 134 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 135 const struct drm_display_mode *scan; 136 struct drm_display_mode *fixed_mode; 137 138 if (list_empty(&connector->base.probed_modes)) 139 return NULL; 140 141 /* prefer fixed mode from EDID if available */ 142 list_for_each_entry(scan, &connector->base.probed_modes, head) { 143 if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0) 144 continue; 145 146 fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); 147 if (!fixed_mode) 148 return NULL; 149 150 drm_dbg_kms(&dev_priv->drm, 151 "[CONNECTOR:%d:%s] using preferred mode from EDID: ", 152 connector->base.base.id, connector->base.name); 153 drm_mode_debug_printmodeline(fixed_mode); 154 155 return fixed_mode; 156 } 157 158 scan = list_first_entry(&connector->base.probed_modes, 159 typeof(*scan), head); 160 161 fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); 162 if (!fixed_mode) 163 return NULL; 164 165 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; 166 167 drm_dbg_kms(&dev_priv->drm, 168 "[CONNECTOR:%d:%s] using first mode from EDID: ", 169 connector->base.base.id, connector->base.name); 170 drm_mode_debug_printmodeline(fixed_mode); 171 172 return fixed_mode; 173 } 174 175 struct drm_display_mode * 176 intel_panel_vbt_fixed_mode(struct intel_connector *connector) 177 { 178 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 179 struct drm_display_info *info = &connector->base.display_info; 180 struct drm_display_mode *fixed_mode; 181 182 if (!dev_priv->vbt.lfp_lvds_vbt_mode) 183 return NULL; 184 185 fixed_mode = drm_mode_duplicate(&dev_priv->drm, 186 dev_priv->vbt.lfp_lvds_vbt_mode); 187 if (!fixed_mode) 188 return NULL; 189 190 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; 191 192 drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: ", 193 connector->base.base.id, connector->base.name); 194 drm_mode_debug_printmodeline(fixed_mode); 195 196 info->width_mm = fixed_mode->width_mm; 197 info->height_mm = fixed_mode->height_mm; 198 199 return fixed_mode; 200 } 201 202 /* adjusted_mode has been preset to be the panel's fixed mode */ 203 static int pch_panel_fitting(struct intel_crtc_state *crtc_state, 204 const struct drm_connector_state *conn_state) 205 { 206 const struct drm_display_mode *adjusted_mode = 207 &crtc_state->hw.adjusted_mode; 208 int x, y, width, height; 209 210 /* Native modes don't need fitting */ 211 if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && 212 adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h && 213 crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) 214 return 0; 215 216 switch (conn_state->scaling_mode) { 217 case DRM_MODE_SCALE_CENTER: 218 width = crtc_state->pipe_src_w; 219 height = crtc_state->pipe_src_h; 220 x = (adjusted_mode->crtc_hdisplay - width + 1)/2; 221 y = (adjusted_mode->crtc_vdisplay - height + 1)/2; 222 break; 223 224 case DRM_MODE_SCALE_ASPECT: 225 /* Scale but preserve the aspect ratio */ 226 { 227 u32 scaled_width = adjusted_mode->crtc_hdisplay 228 * crtc_state->pipe_src_h; 229 u32 scaled_height = crtc_state->pipe_src_w 230 * adjusted_mode->crtc_vdisplay; 231 if (scaled_width > scaled_height) { /* pillar */ 232 width = scaled_height / crtc_state->pipe_src_h; 233 if (width & 1) 234 width++; 235 x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; 236 y = 0; 237 height = adjusted_mode->crtc_vdisplay; 238 } else if (scaled_width < scaled_height) { /* letter */ 239 height = scaled_width / crtc_state->pipe_src_w; 240 if (height & 1) 241 height++; 242 y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; 243 x = 0; 244 width = adjusted_mode->crtc_hdisplay; 245 } else { 246 x = y = 0; 247 width = adjusted_mode->crtc_hdisplay; 248 height = adjusted_mode->crtc_vdisplay; 249 } 250 } 251 break; 252 253 case DRM_MODE_SCALE_NONE: 254 WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w); 255 WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h); 256 fallthrough; 257 case DRM_MODE_SCALE_FULLSCREEN: 258 x = y = 0; 259 width = adjusted_mode->crtc_hdisplay; 260 height = adjusted_mode->crtc_vdisplay; 261 break; 262 263 default: 264 MISSING_CASE(conn_state->scaling_mode); 265 return -EINVAL; 266 } 267 268 drm_rect_init(&crtc_state->pch_pfit.dst, 269 x, y, width, height); 270 crtc_state->pch_pfit.enabled = true; 271 272 return 0; 273 } 274 275 static void 276 centre_horizontally(struct drm_display_mode *adjusted_mode, 277 int width) 278 { 279 u32 border, sync_pos, blank_width, sync_width; 280 281 /* keep the hsync and hblank widths constant */ 282 sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; 283 blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; 284 sync_pos = (blank_width - sync_width + 1) / 2; 285 286 border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; 287 border += border & 1; /* make the border even */ 288 289 adjusted_mode->crtc_hdisplay = width; 290 adjusted_mode->crtc_hblank_start = width + border; 291 adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; 292 293 adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; 294 adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; 295 } 296 297 static void 298 centre_vertically(struct drm_display_mode *adjusted_mode, 299 int height) 300 { 301 u32 border, sync_pos, blank_width, sync_width; 302 303 /* keep the vsync and vblank widths constant */ 304 sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; 305 blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; 306 sync_pos = (blank_width - sync_width + 1) / 2; 307 308 border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; 309 310 adjusted_mode->crtc_vdisplay = height; 311 adjusted_mode->crtc_vblank_start = height + border; 312 adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; 313 314 adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; 315 adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; 316 } 317 318 static u32 panel_fitter_scaling(u32 source, u32 target) 319 { 320 /* 321 * Floating point operation is not supported. So the FACTOR 322 * is defined, which can avoid the floating point computation 323 * when calculating the panel ratio. 324 */ 325 #define ACCURACY 12 326 #define FACTOR (1 << ACCURACY) 327 u32 ratio = source * FACTOR / target; 328 return (FACTOR * ratio + FACTOR/2) / FACTOR; 329 } 330 331 static void i965_scale_aspect(struct intel_crtc_state *crtc_state, 332 u32 *pfit_control) 333 { 334 const struct drm_display_mode *adjusted_mode = 335 &crtc_state->hw.adjusted_mode; 336 u32 scaled_width = adjusted_mode->crtc_hdisplay * 337 crtc_state->pipe_src_h; 338 u32 scaled_height = crtc_state->pipe_src_w * 339 adjusted_mode->crtc_vdisplay; 340 341 /* 965+ is easy, it does everything in hw */ 342 if (scaled_width > scaled_height) 343 *pfit_control |= PFIT_ENABLE | 344 PFIT_SCALING_PILLAR; 345 else if (scaled_width < scaled_height) 346 *pfit_control |= PFIT_ENABLE | 347 PFIT_SCALING_LETTER; 348 else if (adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w) 349 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; 350 } 351 352 static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, 353 u32 *pfit_control, u32 *pfit_pgm_ratios, 354 u32 *border) 355 { 356 struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 357 u32 scaled_width = adjusted_mode->crtc_hdisplay * 358 crtc_state->pipe_src_h; 359 u32 scaled_height = crtc_state->pipe_src_w * 360 adjusted_mode->crtc_vdisplay; 361 u32 bits; 362 363 /* 364 * For earlier chips we have to calculate the scaling 365 * ratio by hand and program it into the 366 * PFIT_PGM_RATIO register 367 */ 368 if (scaled_width > scaled_height) { /* pillar */ 369 centre_horizontally(adjusted_mode, 370 scaled_height / 371 crtc_state->pipe_src_h); 372 373 *border = LVDS_BORDER_ENABLE; 374 if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay) { 375 bits = panel_fitter_scaling(crtc_state->pipe_src_h, 376 adjusted_mode->crtc_vdisplay); 377 378 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | 379 bits << PFIT_VERT_SCALE_SHIFT); 380 *pfit_control |= (PFIT_ENABLE | 381 VERT_INTERP_BILINEAR | 382 HORIZ_INTERP_BILINEAR); 383 } 384 } else if (scaled_width < scaled_height) { /* letter */ 385 centre_vertically(adjusted_mode, 386 scaled_width / 387 crtc_state->pipe_src_w); 388 389 *border = LVDS_BORDER_ENABLE; 390 if (crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { 391 bits = panel_fitter_scaling(crtc_state->pipe_src_w, 392 adjusted_mode->crtc_hdisplay); 393 394 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | 395 bits << PFIT_VERT_SCALE_SHIFT); 396 *pfit_control |= (PFIT_ENABLE | 397 VERT_INTERP_BILINEAR | 398 HORIZ_INTERP_BILINEAR); 399 } 400 } else { 401 /* Aspects match, Let hw scale both directions */ 402 *pfit_control |= (PFIT_ENABLE | 403 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | 404 VERT_INTERP_BILINEAR | 405 HORIZ_INTERP_BILINEAR); 406 } 407 } 408 409 static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, 410 const struct drm_connector_state *conn_state) 411 { 412 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 413 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 414 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; 415 struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 416 417 /* Native modes don't need fitting */ 418 if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && 419 adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h) 420 goto out; 421 422 switch (conn_state->scaling_mode) { 423 case DRM_MODE_SCALE_CENTER: 424 /* 425 * For centered modes, we have to calculate border widths & 426 * heights and modify the values programmed into the CRTC. 427 */ 428 centre_horizontally(adjusted_mode, crtc_state->pipe_src_w); 429 centre_vertically(adjusted_mode, crtc_state->pipe_src_h); 430 border = LVDS_BORDER_ENABLE; 431 break; 432 case DRM_MODE_SCALE_ASPECT: 433 /* Scale but preserve the aspect ratio */ 434 if (DISPLAY_VER(dev_priv) >= 4) 435 i965_scale_aspect(crtc_state, &pfit_control); 436 else 437 i9xx_scale_aspect(crtc_state, &pfit_control, 438 &pfit_pgm_ratios, &border); 439 break; 440 case DRM_MODE_SCALE_FULLSCREEN: 441 /* 442 * Full scaling, even if it changes the aspect ratio. 443 * Fortunately this is all done for us in hw. 444 */ 445 if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay || 446 crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { 447 pfit_control |= PFIT_ENABLE; 448 if (DISPLAY_VER(dev_priv) >= 4) 449 pfit_control |= PFIT_SCALING_AUTO; 450 else 451 pfit_control |= (VERT_AUTO_SCALE | 452 VERT_INTERP_BILINEAR | 453 HORIZ_AUTO_SCALE | 454 HORIZ_INTERP_BILINEAR); 455 } 456 break; 457 default: 458 MISSING_CASE(conn_state->scaling_mode); 459 return -EINVAL; 460 } 461 462 /* 965+ wants fuzzy fitting */ 463 /* FIXME: handle multiple panels by failing gracefully */ 464 if (DISPLAY_VER(dev_priv) >= 4) 465 pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY; 466 467 out: 468 if ((pfit_control & PFIT_ENABLE) == 0) { 469 pfit_control = 0; 470 pfit_pgm_ratios = 0; 471 } 472 473 /* Make sure pre-965 set dither correctly for 18bpp panels. */ 474 if (DISPLAY_VER(dev_priv) < 4 && crtc_state->pipe_bpp == 18) 475 pfit_control |= PANEL_8TO6_DITHER_ENABLE; 476 477 crtc_state->gmch_pfit.control = pfit_control; 478 crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios; 479 crtc_state->gmch_pfit.lvds_border_bits = border; 480 481 return 0; 482 } 483 484 int intel_panel_fitting(struct intel_crtc_state *crtc_state, 485 const struct drm_connector_state *conn_state) 486 { 487 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 488 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 489 490 if (HAS_GMCH(i915)) 491 return gmch_panel_fitting(crtc_state, conn_state); 492 else 493 return pch_panel_fitting(crtc_state, conn_state); 494 } 495 496 enum drm_connector_status 497 intel_panel_detect(struct drm_connector *connector, bool force) 498 { 499 struct drm_i915_private *i915 = to_i915(connector->dev); 500 501 if (!INTEL_DISPLAY_ENABLED(i915)) 502 return connector_status_disconnected; 503 504 return connector_status_connected; 505 } 506 507 enum drm_mode_status 508 intel_panel_mode_valid(struct intel_connector *connector, 509 const struct drm_display_mode *mode) 510 { 511 const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; 512 513 if (!fixed_mode) 514 return MODE_OK; 515 516 if (mode->hdisplay != fixed_mode->hdisplay) 517 return MODE_PANEL; 518 519 if (mode->vdisplay != fixed_mode->vdisplay) 520 return MODE_PANEL; 521 522 if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(fixed_mode)) 523 return MODE_PANEL; 524 525 return MODE_OK; 526 } 527 528 int intel_panel_init(struct intel_panel *panel, 529 struct drm_display_mode *fixed_mode, 530 struct drm_display_mode *downclock_mode) 531 { 532 intel_backlight_init_funcs(panel); 533 534 panel->fixed_mode = fixed_mode; 535 panel->downclock_mode = downclock_mode; 536 537 return 0; 538 } 539 540 void intel_panel_fini(struct intel_panel *panel) 541 { 542 struct intel_connector *intel_connector = 543 container_of(panel, struct intel_connector, panel); 544 545 intel_backlight_destroy(panel); 546 547 if (panel->fixed_mode) 548 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); 549 550 if (panel->downclock_mode) 551 drm_mode_destroy(intel_connector->base.dev, 552 panel->downclock_mode); 553 } 554