aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2012-01-10 18:09:36 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-01-16 15:21:15 -0500
commitcec2f356d59d9e070413e5966a3c5a1af136d948 (patch)
treec4f404a3a9a99d434b40801f12fde76e8890e88f /drivers/gpu/drm/i915/intel_display.c
parent0b8ecdda1943a05c8e7896f0b5f1addf39269927 (diff)
drm/i915: Only look for matching clocks for LVDS downclock
This patch enforces that the downclock clock source is the same as the preferred clock source for LVDS. This fixes a bug where the driver chooses a downclock clock source with a different P than the preferred mode clock source. This happened even if the preferred clock source implemented an acceptable rate for the downclock. The result of this bug is that downclock is disabled. Signed-off-by: Sean Paul <seanpaul@chromium.org> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 29743dee54c2..15f2b52ea704 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -75,7 +75,7 @@ struct intel_limit {
75 intel_range_t dot, vco, n, m, m1, m2, p, p1; 75 intel_range_t dot, vco, n, m, m1, m2, p, p1;
76 intel_p2_t p2; 76 intel_p2_t p2;
77 bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, 77 bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
78 int, int, intel_clock_t *); 78 int, int, intel_clock_t *, intel_clock_t *);
79}; 79};
80 80
81/* FDI */ 81/* FDI */
@@ -83,17 +83,21 @@ struct intel_limit {
83 83
84static bool 84static bool
85intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 85intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
86 int target, int refclk, intel_clock_t *best_clock); 86 int target, int refclk, intel_clock_t *match_clock,
87 intel_clock_t *best_clock);
87static bool 88static bool
88intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 89intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
89 int target, int refclk, intel_clock_t *best_clock); 90 int target, int refclk, intel_clock_t *match_clock,
91 intel_clock_t *best_clock);
90 92
91static bool 93static bool
92intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, 94intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
93 int target, int refclk, intel_clock_t *best_clock); 95 int target, int refclk, intel_clock_t *match_clock,
96 intel_clock_t *best_clock);
94static bool 97static bool
95intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, 98intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
96 int target, int refclk, intel_clock_t *best_clock); 99 int target, int refclk, intel_clock_t *match_clock,
100 intel_clock_t *best_clock);
97 101
98static inline u32 /* units of 100MHz */ 102static inline u32 /* units of 100MHz */
99intel_fdi_link_freq(struct drm_device *dev) 103intel_fdi_link_freq(struct drm_device *dev)
@@ -515,7 +519,8 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
515 519
516static bool 520static bool
517intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 521intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
518 int target, int refclk, intel_clock_t *best_clock) 522 int target, int refclk, intel_clock_t *match_clock,
523 intel_clock_t *best_clock)
519 524
520{ 525{
521 struct drm_device *dev = crtc->dev; 526 struct drm_device *dev = crtc->dev;
@@ -562,6 +567,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
562 if (!intel_PLL_is_valid(dev, limit, 567 if (!intel_PLL_is_valid(dev, limit,
563 &clock)) 568 &clock))
564 continue; 569 continue;
570 if (match_clock &&
571 clock.p != match_clock->p)
572 continue;
565 573
566 this_err = abs(clock.dot - target); 574 this_err = abs(clock.dot - target);
567 if (this_err < err) { 575 if (this_err < err) {
@@ -578,7 +586,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
578 586
579static bool 587static bool
580intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 588intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
581 int target, int refclk, intel_clock_t *best_clock) 589 int target, int refclk, intel_clock_t *match_clock,
590 intel_clock_t *best_clock)
582{ 591{
583 struct drm_device *dev = crtc->dev; 592 struct drm_device *dev = crtc->dev;
584 struct drm_i915_private *dev_priv = dev->dev_private; 593 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -625,6 +634,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
625 if (!intel_PLL_is_valid(dev, limit, 634 if (!intel_PLL_is_valid(dev, limit,
626 &clock)) 635 &clock))
627 continue; 636 continue;
637 if (match_clock &&
638 clock.p != match_clock->p)
639 continue;
628 640
629 this_err = abs(clock.dot - target); 641 this_err = abs(clock.dot - target);
630 if (this_err < err_most) { 642 if (this_err < err_most) {
@@ -642,7 +654,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
642 654
643static bool 655static bool
644intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, 656intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
645 int target, int refclk, intel_clock_t *best_clock) 657 int target, int refclk, intel_clock_t *match_clock,
658 intel_clock_t *best_clock)
646{ 659{
647 struct drm_device *dev = crtc->dev; 660 struct drm_device *dev = crtc->dev;
648 intel_clock_t clock; 661 intel_clock_t clock;
@@ -668,7 +681,8 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
668/* DisplayPort has only two frequencies, 162MHz and 270MHz */ 681/* DisplayPort has only two frequencies, 162MHz and 270MHz */
669static bool 682static bool
670intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, 683intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
671 int target, int refclk, intel_clock_t *best_clock) 684 int target, int refclk, intel_clock_t *match_clock,
685 intel_clock_t *best_clock)
672{ 686{
673 intel_clock_t clock; 687 intel_clock_t clock;
674 if (target < 200000) { 688 if (target < 200000) {
@@ -5038,7 +5052,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
5038 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. 5052 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
5039 */ 5053 */
5040 limit = intel_limit(crtc, refclk); 5054 limit = intel_limit(crtc, refclk);
5041 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); 5055 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
5056 &clock);
5042 if (!ok) { 5057 if (!ok) {
5043 DRM_ERROR("Couldn't find PLL settings for mode!\n"); 5058 DRM_ERROR("Couldn't find PLL settings for mode!\n");
5044 return -EINVAL; 5059 return -EINVAL;
@@ -5048,21 +5063,17 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
5048 intel_crtc_update_cursor(crtc, true); 5063 intel_crtc_update_cursor(crtc, true);
5049 5064
5050 if (is_lvds && dev_priv->lvds_downclock_avail) { 5065 if (is_lvds && dev_priv->lvds_downclock_avail) {
5066 /*
5067 * Ensure we match the reduced clock's P to the target clock.
5068 * If the clocks don't match, we can't switch the display clock
5069 * by using the FP0/FP1. In such case we will disable the LVDS
5070 * downclock feature.
5071 */
5051 has_reduced_clock = limit->find_pll(limit, crtc, 5072 has_reduced_clock = limit->find_pll(limit, crtc,
5052 dev_priv->lvds_downclock, 5073 dev_priv->lvds_downclock,
5053 refclk, 5074 refclk,
5075 &clock,
5054 &reduced_clock); 5076 &reduced_clock);
5055 if (has_reduced_clock && (clock.p != reduced_clock.p)) {
5056 /*
5057 * If the different P is found, it means that we can't
5058 * switch the display clock by using the FP0/FP1.
5059 * In such case we will disable the LVDS downclock
5060 * feature.
5061 */
5062 DRM_DEBUG_KMS("Different P is found for "
5063 "LVDS clock/downclock\n");
5064 has_reduced_clock = 0;
5065 }
5066 } 5077 }
5067 /* SDVO TV has fixed PLL values depend on its clock range, 5078 /* SDVO TV has fixed PLL values depend on its clock range,
5068 this mirrors vbios setting. */ 5079 this mirrors vbios setting. */
@@ -5583,7 +5594,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5583 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. 5594 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
5584 */ 5595 */
5585 limit = intel_limit(crtc, refclk); 5596 limit = intel_limit(crtc, refclk);
5586 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); 5597 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
5598 &clock);
5587 if (!ok) { 5599 if (!ok) {
5588 DRM_ERROR("Couldn't find PLL settings for mode!\n"); 5600 DRM_ERROR("Couldn't find PLL settings for mode!\n");
5589 return -EINVAL; 5601 return -EINVAL;
@@ -5593,21 +5605,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5593 intel_crtc_update_cursor(crtc, true); 5605 intel_crtc_update_cursor(crtc, true);
5594 5606
5595 if (is_lvds && dev_priv->lvds_downclock_avail) { 5607 if (is_lvds && dev_priv->lvds_downclock_avail) {
5608 /*
5609 * Ensure we match the reduced clock's P to the target clock.
5610 * If the clocks don't match, we can't switch the display clock
5611 * by using the FP0/FP1. In such case we will disable the LVDS
5612 * downclock feature.
5613 */
5596 has_reduced_clock = limit->find_pll(limit, crtc, 5614 has_reduced_clock = limit->find_pll(limit, crtc,
5597 dev_priv->lvds_downclock, 5615 dev_priv->lvds_downclock,
5598 refclk, 5616 refclk,
5617 &clock,
5599 &reduced_clock); 5618 &reduced_clock);
5600 if (has_reduced_clock && (clock.p != reduced_clock.p)) {
5601 /*
5602 * If the different P is found, it means that we can't
5603 * switch the display clock by using the FP0/FP1.
5604 * In such case we will disable the LVDS downclock
5605 * feature.
5606 */
5607 DRM_DEBUG_KMS("Different P is found for "
5608 "LVDS clock/downclock\n");
5609 has_reduced_clock = 0;
5610 }
5611 } 5619 }
5612 /* SDVO TV has fixed PLL values depend on its clock range, 5620 /* SDVO TV has fixed PLL values depend on its clock range,
5613 this mirrors vbios setting. */ 5621 this mirrors vbios setting. */