2 * Copyright © 2006-2010 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
28 * Chris Wilson <chris@chris-wilson.co.uk>
31 #include <linux/kernel.h>
32 #include <linux/pwm.h>
34 #include "intel_backlight.h"
35 #include "intel_connector.h"
37 #include "intel_display_types.h"
38 #include "intel_drrs.h"
39 #include "intel_panel.h"
41 bool intel_panel_use_ssc(struct drm_i915_private *i915)
43 if (i915->params.panel_use_ssc >= 0)
44 return i915->params.panel_use_ssc != 0;
45 return i915->vbt.lvds_use_ssc
46 && !(i915->quirks & QUIRK_LVDS_SSC_DISABLE);
49 const struct drm_display_mode *
50 intel_panel_preferred_fixed_mode(struct intel_connector *connector)
52 return list_first_entry_or_null(&connector->panel.fixed_modes,
53 struct drm_display_mode, head);
56 const struct drm_display_mode *
57 intel_panel_fixed_mode(struct intel_connector *connector,
58 const struct drm_display_mode *mode)
60 const struct drm_display_mode *fixed_mode, *best_mode = NULL;
61 int vrefresh = drm_mode_vrefresh(mode);
63 /* pick the fixed_mode that is closest in terms of vrefresh */
64 list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
66 abs(drm_mode_vrefresh(fixed_mode) - vrefresh) <
67 abs(drm_mode_vrefresh(best_mode) - vrefresh))
68 best_mode = fixed_mode;
74 static bool is_alt_drrs_mode(const struct drm_display_mode *mode,
75 const struct drm_display_mode *preferred_mode)
77 return drm_mode_match(mode, preferred_mode,
78 DRM_MODE_MATCH_TIMINGS |
79 DRM_MODE_MATCH_FLAGS |
80 DRM_MODE_MATCH_3D_FLAGS) &&
81 mode->clock != preferred_mode->clock;
84 static bool is_alt_vrr_mode(const struct drm_display_mode *mode,
85 const struct drm_display_mode *preferred_mode)
87 return drm_mode_match(mode, preferred_mode,
88 DRM_MODE_MATCH_FLAGS |
89 DRM_MODE_MATCH_3D_FLAGS) &&
90 mode->hdisplay == preferred_mode->hdisplay &&
91 mode->vdisplay == preferred_mode->vdisplay &&
92 mode->clock != preferred_mode->clock;
95 const struct drm_display_mode *
96 intel_panel_downclock_mode(struct intel_connector *connector,
97 const struct drm_display_mode *adjusted_mode)
99 const struct drm_display_mode *fixed_mode, *best_mode = NULL;
100 int min_vrefresh = connector->panel.vbt.seamless_drrs_min_refresh_rate;
101 int max_vrefresh = drm_mode_vrefresh(adjusted_mode);
103 /* pick the fixed_mode with the lowest refresh rate */
104 list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
105 int vrefresh = drm_mode_vrefresh(fixed_mode);
107 if (is_alt_drrs_mode(fixed_mode, adjusted_mode) &&
108 vrefresh >= min_vrefresh && vrefresh < max_vrefresh) {
109 max_vrefresh = vrefresh;
110 best_mode = fixed_mode;
117 int intel_panel_get_modes(struct intel_connector *connector)
119 const struct drm_display_mode *fixed_mode;
122 list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
123 struct drm_display_mode *mode;
125 mode = drm_mode_duplicate(connector->base.dev, fixed_mode);
127 drm_mode_probed_add(&connector->base, mode);
135 enum drrs_type intel_panel_drrs_type(struct intel_connector *connector)
137 if (list_empty(&connector->panel.fixed_modes) ||
138 list_is_singular(&connector->panel.fixed_modes))
139 return DRRS_TYPE_NONE;
141 return connector->panel.vbt.drrs_type;
144 int intel_panel_compute_config(struct intel_connector *connector,
145 struct drm_display_mode *adjusted_mode)
147 const struct drm_display_mode *fixed_mode =
148 intel_panel_fixed_mode(connector, adjusted_mode);
154 * We don't want to lie too much to the user about the refresh
155 * rate they're going to get. But we have to allow a bit of latitude
156 * for Xorg since it likes to automagically cook up modes with slightly
159 if (abs(drm_mode_vrefresh(adjusted_mode) - drm_mode_vrefresh(fixed_mode)) > 1) {
160 drm_dbg_kms(connector->base.dev,
161 "[CONNECTOR:%d:%s] Requested mode vrefresh (%d Hz) does not match fixed mode vrefresh (%d Hz)\n",
162 connector->base.base.id, connector->base.name,
163 drm_mode_vrefresh(adjusted_mode), drm_mode_vrefresh(fixed_mode));
168 drm_mode_copy(adjusted_mode, fixed_mode);
170 drm_mode_set_crtcinfo(adjusted_mode, 0);
175 static bool is_alt_fixed_mode(const struct drm_display_mode *mode,
176 const struct drm_display_mode *preferred_mode,
179 /* is_alt_drrs_mode() is a subset of is_alt_vrr_mode() */
181 return is_alt_vrr_mode(mode, preferred_mode);
183 return is_alt_drrs_mode(mode, preferred_mode);
186 static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector,
189 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
190 const struct drm_display_mode *preferred_mode =
191 intel_panel_preferred_fixed_mode(connector);
192 struct drm_display_mode *mode, *next;
194 list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
195 if (!is_alt_fixed_mode(mode, preferred_mode, has_vrr))
198 drm_dbg_kms(&dev_priv->drm,
199 "[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n",
200 connector->base.base.id, connector->base.name,
203 list_move_tail(&mode->head, &connector->panel.fixed_modes);
207 static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector)
209 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
210 struct drm_display_mode *scan, *fixed_mode = NULL;
212 if (list_empty(&connector->base.probed_modes))
215 /* make sure the preferred mode is first */
216 list_for_each_entry(scan, &connector->base.probed_modes, head) {
217 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
224 fixed_mode = list_first_entry(&connector->base.probed_modes,
225 typeof(*fixed_mode), head);
227 drm_dbg_kms(&dev_priv->drm,
228 "[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n",
229 connector->base.base.id, connector->base.name,
230 fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first",
231 DRM_MODE_ARG(fixed_mode));
233 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
235 list_move_tail(&fixed_mode->head, &connector->panel.fixed_modes);
238 static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
240 struct drm_i915_private *i915 = to_i915(connector->base.dev);
241 struct drm_display_mode *mode, *next;
243 list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
244 drm_dbg_kms(&i915->drm,
245 "[CONNECTOR:%d:%s] not using EDID mode: " DRM_MODE_FMT "\n",
246 connector->base.base.id, connector->base.name,
248 list_del(&mode->head);
249 drm_mode_destroy(&i915->drm, mode);
253 void intel_panel_add_edid_fixed_modes(struct intel_connector *connector,
254 bool has_drrs, bool has_vrr)
256 intel_panel_add_edid_preferred_mode(connector);
257 if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr))
258 intel_panel_add_edid_alt_fixed_modes(connector, has_vrr);
259 intel_panel_destroy_probed_modes(connector);
262 static void intel_panel_add_fixed_mode(struct intel_connector *connector,
263 struct drm_display_mode *fixed_mode,
266 struct drm_i915_private *i915 = to_i915(connector->base.dev);
267 struct drm_display_info *info = &connector->base.display_info;
272 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
274 info->width_mm = fixed_mode->width_mm;
275 info->height_mm = fixed_mode->height_mm;
277 drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n",
278 connector->base.base.id, connector->base.name, type,
279 DRM_MODE_ARG(fixed_mode));
281 list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes);
284 void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector)
286 struct drm_i915_private *i915 = to_i915(connector->base.dev);
287 const struct drm_display_mode *mode;
289 mode = connector->panel.vbt.lfp_lvds_vbt_mode;
293 intel_panel_add_fixed_mode(connector,
294 drm_mode_duplicate(&i915->drm, mode),
298 void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector)
300 struct drm_i915_private *i915 = to_i915(connector->base.dev);
301 const struct drm_display_mode *mode;
303 mode = connector->panel.vbt.sdvo_lvds_vbt_mode;
307 intel_panel_add_fixed_mode(connector,
308 drm_mode_duplicate(&i915->drm, mode),
312 void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
313 struct intel_encoder *encoder)
315 intel_panel_add_fixed_mode(connector,
316 intel_encoder_current_mode(encoder),
320 /* adjusted_mode has been preset to be the panel's fixed mode */
321 static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
322 const struct drm_connector_state *conn_state)
324 const struct drm_display_mode *adjusted_mode =
325 &crtc_state->hw.adjusted_mode;
326 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
327 int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
328 int x, y, width, height;
330 /* Native modes don't need fitting */
331 if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
332 adjusted_mode->crtc_vdisplay == pipe_src_h &&
333 crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
336 switch (conn_state->scaling_mode) {
337 case DRM_MODE_SCALE_CENTER:
340 x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
341 y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
344 case DRM_MODE_SCALE_ASPECT:
345 /* Scale but preserve the aspect ratio */
347 u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
348 u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
349 if (scaled_width > scaled_height) { /* pillar */
350 width = scaled_height / pipe_src_h;
353 x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
355 height = adjusted_mode->crtc_vdisplay;
356 } else if (scaled_width < scaled_height) { /* letter */
357 height = scaled_width / pipe_src_w;
360 y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
362 width = adjusted_mode->crtc_hdisplay;
365 width = adjusted_mode->crtc_hdisplay;
366 height = adjusted_mode->crtc_vdisplay;
371 case DRM_MODE_SCALE_NONE:
372 WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w);
373 WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h);
375 case DRM_MODE_SCALE_FULLSCREEN:
377 width = adjusted_mode->crtc_hdisplay;
378 height = adjusted_mode->crtc_vdisplay;
382 MISSING_CASE(conn_state->scaling_mode);
386 drm_rect_init(&crtc_state->pch_pfit.dst,
387 x, y, width, height);
388 crtc_state->pch_pfit.enabled = true;
394 centre_horizontally(struct drm_display_mode *adjusted_mode,
397 u32 border, sync_pos, blank_width, sync_width;
399 /* keep the hsync and hblank widths constant */
400 sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
401 blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
402 sync_pos = (blank_width - sync_width + 1) / 2;
404 border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
405 border += border & 1; /* make the border even */
407 adjusted_mode->crtc_hdisplay = width;
408 adjusted_mode->crtc_hblank_start = width + border;
409 adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
411 adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
412 adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
416 centre_vertically(struct drm_display_mode *adjusted_mode,
419 u32 border, sync_pos, blank_width, sync_width;
421 /* keep the vsync and vblank widths constant */
422 sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
423 blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
424 sync_pos = (blank_width - sync_width + 1) / 2;
426 border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
428 adjusted_mode->crtc_vdisplay = height;
429 adjusted_mode->crtc_vblank_start = height + border;
430 adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
432 adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
433 adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
436 static u32 panel_fitter_scaling(u32 source, u32 target)
439 * Floating point operation is not supported. So the FACTOR
440 * is defined, which can avoid the floating point computation
441 * when calculating the panel ratio.
444 #define FACTOR (1 << ACCURACY)
445 u32 ratio = source * FACTOR / target;
446 return (FACTOR * ratio + FACTOR/2) / FACTOR;
449 static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
452 const struct drm_display_mode *adjusted_mode =
453 &crtc_state->hw.adjusted_mode;
454 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
455 int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
456 u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
457 u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
459 /* 965+ is easy, it does everything in hw */
460 if (scaled_width > scaled_height)
461 *pfit_control |= PFIT_ENABLE |
463 else if (scaled_width < scaled_height)
464 *pfit_control |= PFIT_ENABLE |
466 else if (adjusted_mode->crtc_hdisplay != pipe_src_w)
467 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
470 static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
471 u32 *pfit_control, u32 *pfit_pgm_ratios,
474 struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
475 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
476 int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
477 u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
478 u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
482 * For earlier chips we have to calculate the scaling
483 * ratio by hand and program it into the
484 * PFIT_PGM_RATIO register
486 if (scaled_width > scaled_height) { /* pillar */
487 centre_horizontally(adjusted_mode,
488 scaled_height / pipe_src_h);
490 *border = LVDS_BORDER_ENABLE;
491 if (pipe_src_h != adjusted_mode->crtc_vdisplay) {
492 bits = panel_fitter_scaling(pipe_src_h,
493 adjusted_mode->crtc_vdisplay);
495 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
496 bits << PFIT_VERT_SCALE_SHIFT);
497 *pfit_control |= (PFIT_ENABLE |
498 VERT_INTERP_BILINEAR |
499 HORIZ_INTERP_BILINEAR);
501 } else if (scaled_width < scaled_height) { /* letter */
502 centre_vertically(adjusted_mode,
503 scaled_width / pipe_src_w);
505 *border = LVDS_BORDER_ENABLE;
506 if (pipe_src_w != adjusted_mode->crtc_hdisplay) {
507 bits = panel_fitter_scaling(pipe_src_w,
508 adjusted_mode->crtc_hdisplay);
510 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
511 bits << PFIT_VERT_SCALE_SHIFT);
512 *pfit_control |= (PFIT_ENABLE |
513 VERT_INTERP_BILINEAR |
514 HORIZ_INTERP_BILINEAR);
517 /* Aspects match, Let hw scale both directions */
518 *pfit_control |= (PFIT_ENABLE |
519 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
520 VERT_INTERP_BILINEAR |
521 HORIZ_INTERP_BILINEAR);
525 static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
526 const struct drm_connector_state *conn_state)
528 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
529 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
530 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
531 struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
532 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
533 int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
535 /* Native modes don't need fitting */
536 if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
537 adjusted_mode->crtc_vdisplay == pipe_src_h)
540 switch (conn_state->scaling_mode) {
541 case DRM_MODE_SCALE_CENTER:
543 * For centered modes, we have to calculate border widths &
544 * heights and modify the values programmed into the CRTC.
546 centre_horizontally(adjusted_mode, pipe_src_w);
547 centre_vertically(adjusted_mode, pipe_src_h);
548 border = LVDS_BORDER_ENABLE;
550 case DRM_MODE_SCALE_ASPECT:
551 /* Scale but preserve the aspect ratio */
552 if (DISPLAY_VER(dev_priv) >= 4)
553 i965_scale_aspect(crtc_state, &pfit_control);
555 i9xx_scale_aspect(crtc_state, &pfit_control,
556 &pfit_pgm_ratios, &border);
558 case DRM_MODE_SCALE_FULLSCREEN:
560 * Full scaling, even if it changes the aspect ratio.
561 * Fortunately this is all done for us in hw.
563 if (pipe_src_h != adjusted_mode->crtc_vdisplay ||
564 pipe_src_w != adjusted_mode->crtc_hdisplay) {
565 pfit_control |= PFIT_ENABLE;
566 if (DISPLAY_VER(dev_priv) >= 4)
567 pfit_control |= PFIT_SCALING_AUTO;
569 pfit_control |= (VERT_AUTO_SCALE |
570 VERT_INTERP_BILINEAR |
572 HORIZ_INTERP_BILINEAR);
576 MISSING_CASE(conn_state->scaling_mode);
580 /* 965+ wants fuzzy fitting */
581 /* FIXME: handle multiple panels by failing gracefully */
582 if (DISPLAY_VER(dev_priv) >= 4)
583 pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY;
586 if ((pfit_control & PFIT_ENABLE) == 0) {
591 /* Make sure pre-965 set dither correctly for 18bpp panels. */
592 if (DISPLAY_VER(dev_priv) < 4 && crtc_state->pipe_bpp == 18)
593 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
595 crtc_state->gmch_pfit.control = pfit_control;
596 crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
597 crtc_state->gmch_pfit.lvds_border_bits = border;
602 int intel_panel_fitting(struct intel_crtc_state *crtc_state,
603 const struct drm_connector_state *conn_state)
605 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
606 struct drm_i915_private *i915 = to_i915(crtc->base.dev);
609 return gmch_panel_fitting(crtc_state, conn_state);
611 return pch_panel_fitting(crtc_state, conn_state);
614 enum drm_connector_status
615 intel_panel_detect(struct drm_connector *connector, bool force)
617 struct drm_i915_private *i915 = to_i915(connector->dev);
619 if (!INTEL_DISPLAY_ENABLED(i915))
620 return connector_status_disconnected;
622 return connector_status_connected;
626 intel_panel_mode_valid(struct intel_connector *connector,
627 const struct drm_display_mode *mode)
629 const struct drm_display_mode *fixed_mode =
630 intel_panel_fixed_mode(connector, mode);
635 if (mode->hdisplay != fixed_mode->hdisplay)
638 if (mode->vdisplay != fixed_mode->vdisplay)
641 if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(fixed_mode))
647 int intel_panel_init(struct intel_connector *connector)
649 struct intel_panel *panel = &connector->panel;
651 intel_backlight_init_funcs(panel);
653 drm_dbg_kms(connector->base.dev,
654 "[CONNECTOR:%d:%s] DRRS type: %s\n",
655 connector->base.base.id, connector->base.name,
656 intel_drrs_type_str(intel_panel_drrs_type(connector)));
661 void intel_panel_fini(struct intel_connector *connector)
663 struct intel_panel *panel = &connector->panel;
664 struct drm_display_mode *fixed_mode, *next;
666 intel_backlight_destroy(panel);
668 intel_bios_fini_panel(panel);
670 list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) {
671 list_del(&fixed_mode->head);
672 drm_mode_destroy(connector->base.dev, fixed_mode);