Hi, ykzhao<br><br>Amazing~ It works OK now without fuzzy screen.<br>thanks a lot :)<br><br><div class="gmail_quote">2010/1/29 Zhenyu Wang <span dir="ltr"><<a href="mailto:zhenyuw@linux.intel.com">zhenyuw@linux.intel.com</a>></span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">On 2010.01.29 12:33:34 +0800, CSJ wrote:<br>
</div><div class="im">> Hi Zhenyu,<br>
><br>
> Attached dmesg log is using 2.6.33-rc5 kernel with drm.debug=6<br>
> Boot Into console mode, after insmod i915.ko modeset=1<br>
> Both internal and external monitor are black.<br>
><br>
> After executing xinit, I can see xterm on external monitor.<br>
> (but internal monitor is still black)<br>
> so that I dump dmesg as attached file.<br>
><br>
<br>
</div>Hi, it looks the problem is that we don't handle dual channel<br>
LVDS correctly. Please try to test below patch to .33-rc5.<br>
<br>
thanks.<br>
<br>
>From d4d565de0f0ad8443c3b2a2a18fa20ee9f840bec Mon Sep 17 00:00:00 2001<br>
From: Zhenyu Wang <<a href="mailto:zhenyuw@linux.intel.com">zhenyuw@linux.intel.com</a>><br>
Date: Fri, 29 Jan 2010 16:58:42 +0800<br>
Subject: [PATCH] drm/i915: Rework DPLL calculation parameters for Ironlake<br>
<br>
Got Ironlake DPLL parameter table, which reflects the hardware<br>
optimized values. So this one trys to list DPLL parameters for<br>
different output types, should potential fix clock issue seen<br>
on new Arrandale CPUs.<br>
<br>
Signed-off-by: Zhenyu Wang <<a href="mailto:zhenyuw@linux.intel.com">zhenyuw@linux.intel.com</a>><br>
---<br>
drivers/gpu/drm/i915/intel_display.c | 213 ++++++++++++++++++++++++++--------<br>
1 files changed, 163 insertions(+), 50 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c<br>
index 2cc489b..69adbd6 100644<br>
--- a/drivers/gpu/drm/i915/intel_display.c<br>
+++ b/drivers/gpu/drm/i915/intel_display.c<br>
@@ -240,33 +240,86 @@ struct intel_limit {<br>
#define IRONLAKE_DOT_MAX 350000<br>
#define IRONLAKE_VCO_MIN 1760000<br>
#define IRONLAKE_VCO_MAX 3510000<br>
-#define IRONLAKE_N_MIN 1<br>
-#define IRONLAKE_N_MAX 6<br>
-#define IRONLAKE_M_MIN 79<br>
-#define IRONLAKE_M_MAX 127<br>
#define IRONLAKE_M1_MIN 12<br>
#define IRONLAKE_M1_MAX 22<br>
#define IRONLAKE_M2_MIN 5<br>
#define IRONLAKE_M2_MAX 9<br>
-#define IRONLAKE_P_SDVO_DAC_MIN 5<br>
-#define IRONLAKE_P_SDVO_DAC_MAX 80<br>
-#define IRONLAKE_P_LVDS_MIN 28<br>
-#define IRONLAKE_P_LVDS_MAX 112<br>
-#define IRONLAKE_P1_MIN 1<br>
-#define IRONLAKE_P1_MAX 8<br>
-#define IRONLAKE_P2_SDVO_DAC_SLOW 10<br>
-#define IRONLAKE_P2_SDVO_DAC_FAST 5<br>
-#define IRONLAKE_P2_LVDS_SLOW 14 /* single channel */<br>
-#define IRONLAKE_P2_LVDS_FAST 7 /* double channel */<br>
#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */<br>
<br>
-#define IRONLAKE_P_DISPLAY_PORT_MIN 10<br>
-#define IRONLAKE_P_DISPLAY_PORT_MAX 20<br>
-#define IRONLAKE_P2_DISPLAY_PORT_FAST 10<br>
-#define IRONLAKE_P2_DISPLAY_PORT_SLOW 10<br>
-#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0<br>
-#define IRONLAKE_P1_DISPLAY_PORT_MIN 1<br>
-#define IRONLAKE_P1_DISPLAY_PORT_MAX 2<br>
+/* We have parameter ranges for different type of outputs. */<br>
+<br>
+/* DAC & HDMI Refclk 120Mhz */<br>
+#define IRONLAKE_DAC_N_MIN 1<br>
+#define IRONLAKE_DAC_N_MAX 5<br>
+#define IRONLAKE_DAC_M_MIN 79<br>
+#define IRONLAKE_DAC_M_MAX 127<br>
+#define IRONLAKE_DAC_P_MIN 5<br>
+#define IRONLAKE_DAC_P_MAX 80<br>
+#define IRONLAKE_DAC_P1_MIN 1<br>
+#define IRONLAKE_DAC_P1_MAX 8<br>
+#define IRONLAKE_DAC_P2_SLOW 10<br>
+#define IRONLAKE_DAC_P2_FAST 5<br>
+<br>
+/* LVDS single-channel 120Mhz */<br>
+#define IRONLAKE_LVDS_S_N_MIN 1<br>
+#define IRONLAKE_LVDS_S_N_MAX 3<br>
+#define IRONLAKE_LVDS_S_M_MIN 79<br>
+#define IRONLAKE_LVDS_S_M_MAX 118<br>
+#define IRONLAKE_LVDS_S_P_MIN 28<br>
+#define IRONLAKE_LVDS_S_P_MAX 112<br>
+#define IRONLAKE_LVDS_S_P1_MIN 2<br>
+#define IRONLAKE_LVDS_S_P1_MAX 8<br>
+#define IRONLAKE_LVDS_S_P2_SLOW 14<br>
+#define IRONLAKE_LVDS_S_P2_FAST 14<br>
+<br>
+/* LVDS double-channel 120Mhz */<br>
+#define IRONLAKE_LVDS_D_N_MIN 1<br>
+#define IRONLAKE_LVDS_D_N_MAX 3<br>
+#define IRONLAKE_LVDS_D_M_MIN 79<br>
+#define IRONLAKE_LVDS_D_M_MAX 127<br>
+#define IRONLAKE_LVDS_D_P_MIN 14<br>
+#define IRONLAKE_LVDS_D_P_MAX 56<br>
+#define IRONLAKE_LVDS_D_P1_MIN 2<br>
+#define IRONLAKE_LVDS_D_P1_MAX 8<br>
+#define IRONLAKE_LVDS_D_P2_SLOW 7<br>
+#define IRONLAKE_LVDS_D_P2_FAST 7<br>
+<br>
+/* LVDS single-channel SSC 100Mhz */<br>
+#define IRONLAKE_LVDS_S_SSC_N_MIN 1<br>
+#define IRONLAKE_LVDS_S_SSC_N_MAX 2<br>
+#define IRONLAKE_LVDS_S_SSC_M_MIN 79<br>
+#define IRONLAKE_LVDS_S_SSC_M_MAX 126<br>
+#define IRONLAKE_LVDS_S_SSC_P_MIN 28<br>
+#define IRONLAKE_LVDS_S_SSC_P_MAX 112<br>
+#define IRONLAKE_LVDS_S_SSC_P1_MIN 2<br>
+#define IRONLAKE_LVDS_S_SSC_P1_MAX 8<br>
+#define IRONLAKE_LVDS_S_SSC_P2_SLOW 14<br>
+#define IRONLAKE_LVDS_S_SSC_P2_FAST 14<br>
+<br>
+/* LVDS double-channel SSC 100Mhz */<br>
+#define IRONLAKE_LVDS_D_SSC_N_MIN 1<br>
+#define IRONLAKE_LVDS_D_SSC_N_MAX 3<br>
+#define IRONLAKE_LVDS_D_SSC_M_MIN 79<br>
+#define IRONLAKE_LVDS_D_SSC_M_MAX 126<br>
+#define IRONLAKE_LVDS_D_SSC_P_MIN 14<br>
+#define IRONLAKE_LVDS_D_SSC_P_MAX 42<br>
+#define IRONLAKE_LVDS_D_SSC_P1_MIN 2<br>
+#define IRONLAKE_LVDS_D_SSC_P1_MAX 6<br>
+#define IRONLAKE_LVDS_D_SSC_P2_SLOW 7<br>
+#define IRONLAKE_LVDS_D_SSC_P2_FAST 7<br>
+<br>
+/* DisplayPort */<br>
+#define IRONLAKE_DP_N_MIN 1<br>
+#define IRONLAKE_DP_N_MAX 2<br>
+#define IRONLAKE_DP_M_MIN 81<br>
+#define IRONLAKE_DP_M_MAX 90<br>
+#define IRONLAKE_DP_P_MIN 10<br>
+#define IRONLAKE_DP_P_MAX 20<br>
+#define IRONLAKE_DP_P2_FAST 10<br>
+#define IRONLAKE_DP_P2_SLOW 10<br>
+#define IRONLAKE_DP_P2_LIMIT 0<br>
+#define IRONLAKE_DP_P1_MIN 1<br>
+#define IRONLAKE_DP_P1_MAX 2<br>
<br>
static bool<br>
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,<br>
@@ -474,33 +527,78 @@ static const intel_limit_t intel_limits_pineview_lvds = {<br>
.find_pll = intel_find_best_PLL,<br>
};<br>
<br>
-static const intel_limit_t intel_limits_ironlake_sdvo = {<br>
+static const intel_limit_t intel_limits_ironlake_dac = {<br>
.dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },<br>
.vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },<br>
- .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX },<br>
- .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX },<br>
+ .n = { .min = IRONLAKE_DAC_N_MIN, .max = IRONLAKE_DAC_N_MAX },<br>
+ .m = { .min = IRONLAKE_DAC_M_MIN, .max = IRONLAKE_DAC_M_MAX },<br>
.m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },<br>
.m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },<br>
- .p = { .min = IRONLAKE_P_SDVO_DAC_MIN, .max = IRONLAKE_P_SDVO_DAC_MAX },<br>
- .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX },<br>
+ .p = { .min = IRONLAKE_DAC_P_MIN, .max = IRONLAKE_DAC_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_DAC_P1_MIN, .max = IRONLAKE_DAC_P1_MAX },<br>
.p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,<br>
- .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW,<br>
- .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST },<br>
+ .p2_slow = IRONLAKE_DAC_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_DAC_P2_FAST },<br>
.find_pll = intel_g4x_find_best_PLL,<br>
};<br>
<br>
-static const intel_limit_t intel_limits_ironlake_lvds = {<br>
+static const intel_limit_t intel_limits_ironlake_single_lvds = {<br>
.dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },<br>
.vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },<br>
- .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX },<br>
- .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX },<br>
+ .n = { .min = IRONLAKE_LVDS_S_N_MIN, .max = IRONLAKE_LVDS_S_N_MAX },<br>
+ .m = { .min = IRONLAKE_LVDS_S_M_MIN, .max = IRONLAKE_LVDS_S_M_MAX },<br>
.m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },<br>
.m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },<br>
- .p = { .min = IRONLAKE_P_LVDS_MIN, .max = IRONLAKE_P_LVDS_MAX },<br>
- .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX },<br>
+ .p = { .min = IRONLAKE_LVDS_S_P_MIN, .max = IRONLAKE_LVDS_S_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_LVDS_S_P1_MIN, .max = IRONLAKE_LVDS_S_P1_MAX },<br>
.p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,<br>
- .p2_slow = IRONLAKE_P2_LVDS_SLOW,<br>
- .p2_fast = IRONLAKE_P2_LVDS_FAST },<br>
+ .p2_slow = IRONLAKE_LVDS_S_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_LVDS_S_P2_FAST },<br>
+ .find_pll = intel_g4x_find_best_PLL,<br>
+};<br>
+<br>
+static const intel_limit_t intel_limits_ironlake_double_lvds = {<br>
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },<br>
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },<br>
+ .n = { .min = IRONLAKE_LVDS_D_N_MIN, .max = IRONLAKE_LVDS_D_N_MAX },<br>
+ .m = { .min = IRONLAKE_LVDS_D_M_MIN, .max = IRONLAKE_LVDS_D_M_MAX },<br>
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },<br>
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },<br>
+ .p = { .min = IRONLAKE_LVDS_D_P_MIN, .max = IRONLAKE_LVDS_D_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_LVDS_D_P1_MIN, .max = IRONLAKE_LVDS_D_P1_MAX },<br>
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,<br>
+ .p2_slow = IRONLAKE_LVDS_D_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_LVDS_D_P2_FAST },<br>
+ .find_pll = intel_g4x_find_best_PLL,<br>
+};<br>
+<br>
+static const intel_limit_t intel_limits_ironlake_single_lvds_ssc = {<br>
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },<br>
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },<br>
+ .n = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX },<br>
+ .m = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX },<br>
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },<br>
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },<br>
+ .p = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX },<br>
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,<br>
+ .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST },<br>
+ .find_pll = intel_g4x_find_best_PLL,<br>
+};<br>
+<br>
+static const intel_limit_t intel_limits_ironlake_double_lvds_ssc = {<br>
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },<br>
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },<br>
+ .n = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX },<br>
+ .m = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX },<br>
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },<br>
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },<br>
+ .p = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX },<br>
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,<br>
+ .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST },<br>
.find_pll = intel_g4x_find_best_PLL,<br>
};<br>
<br>
@@ -509,34 +607,49 @@ static const intel_limit_t intel_limits_ironlake_display_port = {<br>
.max = IRONLAKE_DOT_MAX },<br>
.vco = { .min = IRONLAKE_VCO_MIN,<br>
.max = IRONLAKE_VCO_MAX},<br>
- .n = { .min = IRONLAKE_N_MIN,<br>
- .max = IRONLAKE_N_MAX },<br>
- .m = { .min = IRONLAKE_M_MIN,<br>
- .max = IRONLAKE_M_MAX },<br>
+ .n = { .min = IRONLAKE_DP_N_MIN,<br>
+ .max = IRONLAKE_DP_N_MAX },<br>
+ .m = { .min = IRONLAKE_DP_M_MIN,<br>
+ .max = IRONLAKE_DP_M_MAX },<br>
.m1 = { .min = IRONLAKE_M1_MIN,<br>
.max = IRONLAKE_M1_MAX },<br>
.m2 = { .min = IRONLAKE_M2_MIN,<br>
.max = IRONLAKE_M2_MAX },<br>
- .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN,<br>
- .max = IRONLAKE_P_DISPLAY_PORT_MAX },<br>
- .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN,<br>
- .max = IRONLAKE_P1_DISPLAY_PORT_MAX},<br>
- .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT,<br>
- .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW,<br>
- .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST },<br>
+ .p = { .min = IRONLAKE_DP_P_MIN,<br>
+ .max = IRONLAKE_DP_P_MAX },<br>
+ .p1 = { .min = IRONLAKE_DP_P1_MIN,<br>
+ .max = IRONLAKE_DP_P1_MAX},<br>
+ .p2 = { .dot_limit = IRONLAKE_DP_P2_LIMIT,<br>
+ .p2_slow = IRONLAKE_DP_P2_SLOW,<br>
+ .p2_fast = IRONLAKE_DP_P2_FAST },<br>
.find_pll = intel_find_pll_ironlake_dp,<br>
};<br>
<br>
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)<br>
{<br>
+ struct drm_device *dev = crtc->dev;<br>
+ struct drm_i915_private *dev_priv = dev->dev_private;<br>
const intel_limit_t *limit;<br>
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))<br>
- limit = &intel_limits_ironlake_lvds;<br>
- else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||<br>
+<br>
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {<br>
+ if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==<br>
+ LVDS_CLKB_POWER_UP) {<br>
+ /* LVDS dual channel */<br>
+ if (dev_priv->lvds_use_ssc)<br>
+ limit = &intel_limits_ironlake_double_lvds_ssc;<br>
+ else<br>
+ limit = &intel_limits_ironlake_double_lvds;<br>
+ } else {<br>
+ if (dev_priv->lvds_use_ssc)<br>
+ limit = &intel_limits_ironlake_single_lvds_ssc;<br>
+ else<br>
+ limit = &intel_limits_ironlake_single_lvds;<br>
+ }<br>
+ } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||<br>
HAS_eDP)<br>
limit = &intel_limits_ironlake_display_port;<br>
else<br>
- limit = &intel_limits_ironlake_sdvo;<br>
+ limit = &intel_limits_ironlake_dac;<br>
<br>
return limit;<br>
}<br>
<font color="#888888">--<br>
1.6.6<br>
</font><div><div></div><div class="h5"><br>
<br>
--<br>
Open Source Technology Center, Intel ltd.<br>
<br>
$gpg --keyserver <a href="http://wwwkeys.pgp.net" target="_blank">wwwkeys.pgp.net</a> --recv-keys 4D781827<br>
</div></div><br>-----BEGIN PGP SIGNATURE-----<br>
Version: GnuPG v1.4.10 (GNU/Linux)<br>
<br>
iEYEARECAAYFAktipKYACgkQsQQaM014GCcwbwCfRGqdrnrDxpHZvvtvf/aZeMV1<br>
9RgAnjdXKyZ6fj1zys70um667EkEh2Bl<br>
=iW1w<br>
-----END PGP SIGNATURE-----<br>
<br></blockquote></div><br>