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>