Home | History | Annotate | Line # | Download | only in src
      1 /* -*- c-basic-offset: 4 -*- */
      2 /*
      3  * Copyright  2006 Intel Corporation
      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 FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * Authors:
     25  *    Eric Anholt <eric (at) anholt.net>
     26  *
     27  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include <unistd.h>
     34 #include <string.h>
     35 #include <assert.h>
     36 #include <stdlib.h>
     37 #include <math.h>
     38 #include <sys/ioctl.h>
     39 
     40 #include "xf86.h"
     41 #include "i830.h"
     42 #include "i830_bios.h"
     43 #include "i830_display.h"
     44 #include "i830_debug.h"
     45 #include "xf86Modes.h"
     46 
     47 typedef struct {
     48     /* given values */
     49     int n;
     50     int m1, m2;
     51     int p1, p2;
     52     /* derived values */
     53     int	dot;
     54     int	vco;
     55     int	m;
     56     int	p;
     57 } intel_clock_t;
     58 
     59 typedef struct {
     60     int	min, max;
     61 } intel_range_t;
     62 
     63 typedef struct {
     64     int	dot_limit;
     65     int	p2_slow, p2_fast;
     66 } intel_p2_t;
     67 
     68 #define INTEL_P2_NUM		      2
     69 
     70 typedef struct intel_limit intel_limit_t;
     71 struct intel_limit {
     72     intel_range_t   dot, vco, n, m, m1, m2, p, p1;
     73     intel_p2_t	    p2;
     74     Bool (* find_pll)(const intel_limit_t *, xf86CrtcPtr,
     75                       int, int, intel_clock_t *);
     76 };
     77 
     78 #define I8XX_DOT_MIN		  25000
     79 #define I8XX_DOT_MAX		 350000
     80 #define I8XX_VCO_MIN		 930000
     81 #define I8XX_VCO_MAX		1400000
     82 #define I8XX_N_MIN		      3
     83 #define I8XX_N_MAX		     16
     84 #define I8XX_M_MIN		     96
     85 #define I8XX_M_MAX		    140
     86 #define I8XX_M1_MIN		     18
     87 #define I8XX_M1_MAX		     26
     88 #define I8XX_M2_MIN		      6
     89 #define I8XX_M2_MAX		     16
     90 #define I8XX_P_MIN		      4
     91 #define I8XX_P_MAX		    128
     92 #define I8XX_P1_MIN		      2
     93 #define I8XX_P1_MAX		     33
     94 #define I8XX_P1_LVDS_MIN	      1
     95 #define I8XX_P1_LVDS_MAX	      6
     96 #define I8XX_P2_SLOW		      4
     97 #define I8XX_P2_FAST		      2
     98 #define I8XX_P2_LVDS_SLOW	      14
     99 #define I8XX_P2_LVDS_FAST	      7
    100 #define I8XX_P2_SLOW_LIMIT	 165000
    101 
    102 #define I9XX_DOT_MIN		  20000
    103 #define I9XX_DOT_MAX		 400000
    104 #define I9XX_VCO_MIN		1400000
    105 #define I9XX_VCO_MAX		2800000
    106 #define IGD_VCO_MIN		1700000
    107 #define IGD_VCO_MAX		3500000
    108 
    109 /* Haven't found any reason to go this fast, but newer chips support it */
    110 #define I96X_VCO_MAX		3200000
    111 
    112 /*
    113  * These values are taken from the broadwater/crestline PLL spreadsheet.
    114  * All of the defines here are for the programmed register value, not
    115  * the 'counter' value (e.g. Ncounter = Nregister + 2)
    116  */
    117 #define I9XX_N_MIN		      1
    118 #define I9XX_N_MAX		      6
    119 /* IGD's Ncounter is a ring counter */
    120 #define IGD_N_MIN		      3
    121 #define IGD_N_MAX		      6
    122 #define I9XX_M_MIN		     70
    123 #define I9XX_M_MAX		    120
    124 #define IGD_M_MIN		      2
    125 #define IGD_M_MAX		    256
    126 
    127 /* these two come from the calm1 macro */
    128 #define I9XX_M1_MIN		     10
    129 #define I9XX_M1_MAX		     22
    130 #define I9XX_M2_MIN		      5
    131 #define I9XX_M2_MAX		      9
    132 /* IGD M1 is reserved, and must be 0 */
    133 #define IGD_M1_MIN		      0
    134 #define IGD_M1_MAX		      0
    135 #define IGD_M2_MIN		      0
    136 #define IGD_M2_MAX		      254
    137 
    138 #define I9XX_P_SDVO_DAC_MIN	      5
    139 #define I9XX_P_SDVO_DAC_MAX	     80
    140 #define I9XX_P_LVDS_MIN		      7
    141 #define I9XX_P_LVDS_MAX		     98
    142 #define IGD_P_LVDS_MIN		      7
    143 #define IGD_P_LVDS_MAX		     112
    144 #define I9XX_P1_MIN		      1
    145 #define I9XX_P1_MAX		      8
    146 #define I9XX_P2_SDVO_DAC_SLOW		     10
    147 #define I9XX_P2_SDVO_DAC_FAST		      5
    148 #define I9XX_P2_SDVO_DAC_SLOW_LIMIT	 200000
    149 #define I9XX_P2_LVDS_SLOW		     14
    150 #define I9XX_P2_LVDS_FAST		      7
    151 #define I9XX_P2_LVDS_SLOW_LIMIT		 112000
    152 
    153 #define INTEL_LIMIT_I8XX_DVO_DAC    0
    154 #define INTEL_LIMIT_I8XX_LVDS	    1
    155 #define INTEL_LIMIT_I9XX_SDVO_DAC   2
    156 #define INTEL_LIMIT_I9XX_LVDS	    3
    157 #define INTEL_LIMIT_IGD_SDVO_DAC    4
    158 #define INTEL_LIMIT_IGD_LVDS	    5
    159 #define INTEL_LIMIT_G4X_SDVO	    6
    160 #define INTEL_LIMIT_G4X_HDMI_DAC    7
    161 #define INTEL_LIMIT_G4X_SINGLE_LVDS 8
    162 #define INTEL_LIMIT_G4X_DUAL_LVDS   9
    163 
    164 /*The parameter is for SDVO on G4x platform*/
    165 #define G4X_VCO_MIN                1750000
    166 #define G4X_VCO_MAX                3500000
    167 #define G4X_DOT_SDVO_MIN           25000
    168 #define G4X_DOT_SDVO_MAX           270000
    169 #define G4X_N_SDVO_MIN             1
    170 #define G4X_N_SDVO_MAX             4
    171 #define G4X_M_SDVO_MIN             104
    172 #define G4X_M_SDVO_MAX             138
    173 #define G4X_M1_SDVO_MIN            17
    174 #define G4X_M1_SDVO_MAX            23
    175 #define G4X_M2_SDVO_MIN            5
    176 #define G4X_M2_SDVO_MAX            11
    177 #define G4X_P_SDVO_MIN             10
    178 #define G4X_P_SDVO_MAX             30
    179 #define G4X_P1_SDVO_MIN            1
    180 #define G4X_P1_SDVO_MAX            3
    181 #define G4X_P2_SDVO_SLOW           10
    182 #define G4X_P2_SDVO_FAST           10
    183 #define G4X_P2_SDVO_LIMIT          270000
    184 
    185 /*The parameter is for HDMI_DAC on G4x platform*/
    186 #define G4X_DOT_HDMI_DAC_MIN           22000
    187 #define G4X_DOT_HDMI_DAC_MAX           400000
    188 #define G4X_N_HDMI_DAC_MIN             1
    189 #define G4X_N_HDMI_DAC_MAX             4
    190 #define G4X_M_HDMI_DAC_MIN             104
    191 #define G4X_M_HDMI_DAC_MAX             138
    192 #define G4X_M1_HDMI_DAC_MIN            16
    193 #define G4X_M1_HDMI_DAC_MAX            23
    194 #define G4X_M2_HDMI_DAC_MIN            5
    195 #define G4X_M2_HDMI_DAC_MAX            11
    196 #define G4X_P_HDMI_DAC_MIN             5
    197 #define G4X_P_HDMI_DAC_MAX             80
    198 #define G4X_P1_HDMI_DAC_MIN            1
    199 #define G4X_P1_HDMI_DAC_MAX            8
    200 #define G4X_P2_HDMI_DAC_SLOW           10
    201 #define G4X_P2_HDMI_DAC_FAST           5
    202 #define G4X_P2_HDMI_DAC_LIMIT          165000
    203 
    204 /*The parameter is for SINGLE_LVDS on G4x platform*/
    205 #define G4X_DOT_SINGLE_LVDS_MIN           20000
    206 #define G4X_DOT_SINGLE_LVDS_MAX           115000
    207 #define G4X_N_SINGLE_LVDS_MIN             1
    208 #define G4X_N_SINGLE_LVDS_MAX             3
    209 #define G4X_M_SINGLE_LVDS_MIN             104
    210 #define G4X_M_SINGLE_LVDS_MAX             138
    211 #define G4X_M1_SINGLE_LVDS_MIN            17
    212 #define G4X_M1_SINGLE_LVDS_MAX            23
    213 #define G4X_M2_SINGLE_LVDS_MIN            5
    214 #define G4X_M2_SINGLE_LVDS_MAX            11
    215 #define G4X_P_SINGLE_LVDS_MIN             28
    216 #define G4X_P_SINGLE_LVDS_MAX             112
    217 #define G4X_P1_SINGLE_LVDS_MIN            2
    218 #define G4X_P1_SINGLE_LVDS_MAX            8
    219 #define G4X_P2_SINGLE_LVDS_SLOW           14
    220 #define G4X_P2_SINGLE_LVDS_FAST           14
    221 #define G4X_P2_SINGLE_LVDS_LIMIT          0
    222 
    223 /*The parameter is for DUAL_LVDS on G4x platform*/
    224 #define G4X_DOT_DUAL_LVDS_MIN           80000
    225 #define G4X_DOT_DUAL_LVDS_MAX           224000
    226 #define G4X_N_DUAL_LVDS_MIN             1
    227 #define G4X_N_DUAL_LVDS_MAX             3
    228 #define G4X_M_DUAL_LVDS_MIN             104
    229 #define G4X_M_DUAL_LVDS_MAX             138
    230 #define G4X_M1_DUAL_LVDS_MIN            17
    231 #define G4X_M1_DUAL_LVDS_MAX            23
    232 #define G4X_M2_DUAL_LVDS_MIN            5
    233 #define G4X_M2_DUAL_LVDS_MAX            11
    234 #define G4X_P_DUAL_LVDS_MIN             14
    235 #define G4X_P_DUAL_LVDS_MAX             42
    236 #define G4X_P1_DUAL_LVDS_MIN            2
    237 #define G4X_P1_DUAL_LVDS_MAX            6
    238 #define G4X_P2_DUAL_LVDS_SLOW           7
    239 #define G4X_P2_DUAL_LVDS_FAST           7
    240 #define G4X_P2_DUAL_LVDS_LIMIT          0
    241 
    242 static Bool
    243 intel_find_pll_i8xx_and_i9xx(const intel_limit_t *, xf86CrtcPtr,
    244                              int, int, intel_clock_t *);
    245 static Bool
    246 intel_find_pll_g4x(const intel_limit_t *, xf86CrtcPtr,
    247                    int, int, intel_clock_t *);
    248 static void
    249 i830_crtc_load_lut(xf86CrtcPtr crtc);
    250 
    251 static const intel_limit_t intel_limits[] = {
    252     { /* INTEL_LIMIT_I8XX_DVO_DAC */
    253         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
    254         .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
    255         .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
    256         .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
    257         .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
    258         .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
    259         .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
    260         .p1  = { .min = I8XX_P1_MIN,		.max = I8XX_P1_MAX },
    261 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
    262 		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
    263         .find_pll = intel_find_pll_i8xx_and_i9xx,
    264     },
    265     { /* INTEL_LIMIT_I8XX_LVDS */
    266         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
    267         .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
    268         .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
    269         .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
    270         .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
    271         .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
    272         .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
    273         .p1  = { .min = I8XX_P1_LVDS_MIN,	.max = I8XX_P1_LVDS_MAX },
    274 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
    275 		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
    276         .find_pll = intel_find_pll_i8xx_and_i9xx,
    277     },
    278     { /* INTEL_LIMIT_I9XX_SDVO_DAC */
    279         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
    280         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
    281         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
    282         .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
    283         .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
    284         .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
    285         .p   = { .min = I9XX_P_SDVO_DAC_MIN,	.max = I9XX_P_SDVO_DAC_MAX },
    286         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
    287 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
    288 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
    289         .find_pll = intel_find_pll_i8xx_and_i9xx,
    290     },
    291     { /* INTEL_LIMIT_I9XX_LVDS */
    292         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
    293         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
    294         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
    295         .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
    296         .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
    297         .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
    298         .p   = { .min = I9XX_P_LVDS_MIN,	.max = I9XX_P_LVDS_MAX },
    299         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
    300 	/* The single-channel range is 25-112Mhz, and dual-channel
    301 	 * is 80-224Mhz.  Prefer single channel as much as possible.
    302 	 */
    303 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
    304 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
    305         .find_pll = intel_find_pll_i8xx_and_i9xx,
    306     },
    307     { /* INTEL_LIMIT_IGD_SDVO */
    308         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX},
    309         .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
    310         .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
    311         .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
    312         .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
    313         .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
    314         .p   = { .min = I9XX_P_SDVO_DAC_MIN,    .max = I9XX_P_SDVO_DAC_MAX },
    315         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
    316 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
    317 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
    318         .find_pll = intel_find_pll_i8xx_and_i9xx,
    319     },
    320     { /* INTEL_LIMIT_IGD_LVDS */
    321         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
    322         .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
    323         .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
    324         .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
    325         .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
    326         .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
    327         .p   = { .min = IGD_P_LVDS_MIN,	.max = IGD_P_LVDS_MAX },
    328         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
    329 	/* IGD only supports single-channel mode. */
    330 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
    331 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
    332         .find_pll = intel_find_pll_i8xx_and_i9xx,
    333     },
    334     /* below parameter and function is for G4X Chipset Family*/
    335     {   /* INTEL_LIMIT_G4X_SDVO */
    336         .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
    337         .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
    338         .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
    339         .m   = { .min = G4X_M_SDVO_MIN,         .max = G4X_M_SDVO_MAX },
    340         .m1  = { .min = G4X_M1_SDVO_MIN,        .max = G4X_M1_SDVO_MAX },
    341         .m2  = { .min = G4X_M2_SDVO_MIN,        .max = G4X_M2_SDVO_MAX },
    342         .p   = { .min = G4X_P_SDVO_MIN,         .max = G4X_P_SDVO_MAX },
    343         .p1  = { .min = G4X_P1_SDVO_MIN,        .max = G4X_P1_SDVO_MAX},
    344         .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
    345                  .p2_slow = G4X_P2_SDVO_SLOW,
    346                  .p2_fast = G4X_P2_SDVO_FAST },
    347         .find_pll = intel_find_pll_g4x,
    348     },
    349     {   /* INTEL_LIMIT_G4X_HDMI_DAC */
    350         .dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
    351         .vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
    352         .n   = { .min = G4X_N_HDMI_DAC_MIN,	.max = G4X_N_HDMI_DAC_MAX },
    353         .m   = { .min = G4X_M_HDMI_DAC_MIN,	.max = G4X_M_HDMI_DAC_MAX },
    354         .m1  = { .min = G4X_M1_HDMI_DAC_MIN,	.max = G4X_M1_HDMI_DAC_MAX },
    355         .m2  = { .min = G4X_M2_HDMI_DAC_MIN,	.max = G4X_M2_HDMI_DAC_MAX },
    356         .p   = { .min = G4X_P_HDMI_DAC_MIN,	.max = G4X_P_HDMI_DAC_MAX },
    357         .p1  = { .min = G4X_P1_HDMI_DAC_MIN,	.max = G4X_P1_HDMI_DAC_MAX},
    358         .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
    359                  .p2_slow = G4X_P2_HDMI_DAC_SLOW,
    360                  .p2_fast = G4X_P2_HDMI_DAC_FAST },
    361         .find_pll = intel_find_pll_g4x,
    362     },
    363     {   /* INTEL_LIMIT_G4X_SINGLE_LVDS */
    364         .dot = { .min = G4X_DOT_SINGLE_LVDS_MIN,
    365                  .max = G4X_DOT_SINGLE_LVDS_MAX },
    366         .vco = { .min = G4X_VCO_MIN,
    367                  .max = G4X_VCO_MAX },
    368         .n   = { .min = G4X_N_SINGLE_LVDS_MIN,
    369                  .max = G4X_N_SINGLE_LVDS_MAX },
    370         .m   = { .min = G4X_M_SINGLE_LVDS_MIN,
    371                  .max = G4X_M_SINGLE_LVDS_MAX },
    372         .m1  = { .min = G4X_M1_SINGLE_LVDS_MIN,
    373                  .max = G4X_M1_SINGLE_LVDS_MAX },
    374         .m2  = { .min = G4X_M2_SINGLE_LVDS_MIN,
    375                  .max = G4X_M2_SINGLE_LVDS_MAX },
    376         .p   = { .min = G4X_P_SINGLE_LVDS_MIN,
    377                  .max = G4X_P_SINGLE_LVDS_MAX },
    378         .p1  = { .min = G4X_P1_SINGLE_LVDS_MIN,
    379                  .max = G4X_P1_SINGLE_LVDS_MAX },
    380         .p2  = { .dot_limit = G4X_P2_SINGLE_LVDS_LIMIT,
    381                  .p2_slow = G4X_P2_SINGLE_LVDS_SLOW,
    382                  .p2_fast = G4X_P2_SINGLE_LVDS_FAST },
    383         .find_pll = intel_find_pll_g4x,
    384     },
    385     {   /* INTEL_LIMIT_G4X_DUAL_LVDS */
    386         .dot = { .min = G4X_DOT_DUAL_LVDS_MIN,
    387                  .max = G4X_DOT_DUAL_LVDS_MAX },
    388         .vco = { .min = G4X_VCO_MIN,
    389                  .max = G4X_VCO_MAX},
    390         .n   = { .min = G4X_N_DUAL_LVDS_MIN,
    391                  .max = G4X_N_DUAL_LVDS_MAX },
    392         .m   = { .min = G4X_M_DUAL_LVDS_MIN,
    393                  .max = G4X_M_DUAL_LVDS_MAX },
    394         .m1  = { .min = G4X_M1_DUAL_LVDS_MIN,
    395                  .max = G4X_M1_DUAL_LVDS_MAX },
    396         .m2  = { .min = G4X_M2_DUAL_LVDS_MIN,
    397                  .max = G4X_M2_DUAL_LVDS_MAX },
    398         .p   = { .min = G4X_P_DUAL_LVDS_MIN,
    399                  .max = G4X_P_DUAL_LVDS_MAX },
    400         .p1  = { .min = G4X_P1_DUAL_LVDS_MIN,
    401                  .max = G4X_P1_DUAL_LVDS_MAX},
    402         .p2  = { .dot_limit = G4X_P2_DUAL_LVDS_LIMIT,
    403                  .p2_slow = G4X_P2_DUAL_LVDS_SLOW,
    404                  .p2_fast = G4X_P2_DUAL_LVDS_FAST },
    405         .find_pll = intel_find_pll_g4x,
    406     },
    407 };
    408 
    409 static const intel_limit_t *intel_limit_g4x (xf86CrtcPtr crtc)
    410 {
    411     ScrnInfoPtr	pScrn = crtc->scrn;
    412     I830Ptr	pI830 = I830PTR(pScrn);
    413     const intel_limit_t *limit;
    414 
    415     if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
    416         if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) {
    417             /* LVDS with dual channel */
    418             limit = &intel_limits[INTEL_LIMIT_G4X_DUAL_LVDS];
    419         } else /* LVDS with single channel */
    420             limit = &intel_limits[INTEL_LIMIT_G4X_SINGLE_LVDS];
    421     } else if (i830PipeHasType (crtc, I830_OUTPUT_HDMI) ||
    422                i830PipeHasType (crtc, I830_OUTPUT_ANALOG)) {
    423         limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
    424     } else if (i830PipeHasType (crtc, I830_OUTPUT_SDVO)) {
    425         limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
    426     } else /* The option is for other outputs */
    427         limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
    428     return limit;
    429 }
    430 
    431 static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
    432 {
    433     ScrnInfoPtr	pScrn = crtc->scrn;
    434     I830Ptr	pI830 = I830PTR(pScrn);
    435     const intel_limit_t *limit;
    436 
    437     if (IS_G4X(pI830)) {
    438         limit = intel_limit_g4x(crtc);
    439     } else if (IS_I9XX(pI830) && !IS_IGD(pI830)) {
    440 	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
    441 	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
    442 	else
    443 	    limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
    444     } else if (IS_IGD(pI830)) {
    445 	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
    446 	    limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
    447 	else
    448 	    limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
    449     } else {
    450 	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
    451 	    limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
    452 	else
    453 	    limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
    454     }
    455 
    456     return limit;
    457 }
    458 
    459 /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
    460 
    461 static void i8xx_clock(int refclk, intel_clock_t *clock)
    462 {
    463     clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
    464     clock->p = clock->p1 * clock->p2;
    465     clock->vco = refclk * clock->m / (clock->n + 2);
    466     clock->dot = clock->vco / clock->p;
    467 }
    468 
    469 /** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
    470 
    471 static void i9xx_clock(int refclk, intel_clock_t *clock)
    472 {
    473     clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
    474     clock->p = clock->p1 * clock->p2;
    475     clock->vco = refclk * clock->m / (clock->n + 2);
    476     clock->dot = clock->vco / clock->p;
    477 }
    478 
    479 /* m1 is reserved as 0 in IGD, n is a ring counter */
    480 static void igd_clock(int refclk, intel_clock_t *clock)
    481 {
    482     clock->m = clock->m2 + 2;
    483     clock->p = clock->p1 * clock->p2;
    484     clock->vco = refclk * clock->m / clock->n;
    485     clock->dot = clock->vco / clock->p;
    486 }
    487 
    488 static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock)
    489 {
    490     if (IS_I9XX(pI830)) {
    491 	if (IS_IGD(pI830))
    492 	    igd_clock(refclk, clock);
    493 	else
    494 	    i9xx_clock (refclk, clock);
    495     } else
    496 	i8xx_clock (refclk, clock);
    497 }
    498 
    499 static void
    500 i830PrintPll(ScrnInfoPtr pScrn, char *prefix, intel_clock_t *clock)
    501 {
    502     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    503 	       "%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, "
    504 	       "(p %d, p1 %d, p2 %d))\n",
    505 	       prefix, clock->dot, clock->vco,
    506 	       clock->m, clock->m1, clock->m2,
    507 	       clock->n,
    508 	       clock->p, clock->p1, clock->p2);
    509 }
    510 
    511 /**
    512  * Returns whether any output on the specified pipe is of the specified type
    513  */
    514 Bool
    515 i830PipeHasType (xf86CrtcPtr crtc, int type)
    516 {
    517     ScrnInfoPtr	pScrn = crtc->scrn;
    518     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    519     int		i;
    520 
    521     for (i = 0; i < xf86_config->num_output; i++)
    522     {
    523 	xf86OutputPtr  output = xf86_config->output[i];
    524 	if (output->crtc == crtc)
    525 	{
    526 	    I830OutputPrivatePtr    intel_output = output->driver_private;
    527 	    if (intel_output->type == type)
    528 		return TRUE;
    529 	}
    530     }
    531     return FALSE;
    532 }
    533 
    534 #define i830PllInvalid(s)   { /* ErrorF (s) */; return FALSE; }
    535 /**
    536  * Returns whether the given set of divisors are valid for a given refclk with
    537  * the given outputs.
    538  */
    539 
    540 static Bool
    541 i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
    542 {
    543     const intel_limit_t *limit = intel_limit (crtc);
    544     ScrnInfoPtr pScrn = crtc->scrn;
    545     I830Ptr pI830 = I830PTR(pScrn);
    546 
    547     if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
    548 	i830PllInvalid ("p1 out of range\n");
    549     if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
    550 	i830PllInvalid ("p out of range\n");
    551     if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
    552 	i830PllInvalid ("m2 out of range\n");
    553     if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
    554 	i830PllInvalid ("m1 out of range\n");
    555     if (clock->m1 <= clock->m2 && !IS_IGD(pI830))
    556 	i830PllInvalid ("m1 <= m2\n");
    557     if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
    558 	i830PllInvalid ("m out of range\n");
    559     if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
    560 	i830PllInvalid ("n out of range\n");
    561     if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
    562 	i830PllInvalid ("vco out of range\n");
    563     /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
    564      * output, etc., rather than just a single range.
    565      */
    566     if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
    567 	i830PllInvalid ("dot out of range\n");
    568 
    569     return TRUE;
    570 }
    571 
    572 static Bool
    573 intel_find_pll_i8xx_and_i9xx(const intel_limit_t * limit, xf86CrtcPtr crtc,
    574 	                     int target, int refclk, intel_clock_t *best_clock)
    575 {
    576     ScrnInfoPtr pScrn = crtc->scrn;
    577     I830Ptr pI830 = I830PTR(pScrn);
    578     intel_clock_t clock;
    579     int err = target;
    580 
    581     if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
    582     {
    583 	/* For LVDS, if the panel is on, just rely on its current settings for
    584 	 * dual-channel.  We haven't figured out how to reliably set up
    585 	 * different single/dual channel state, if we even can.
    586 	 */
    587 	if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
    588 	    clock.p2 = limit->p2.p2_fast;
    589 	else
    590 	    clock.p2 = limit->p2.p2_slow;
    591     } else {
    592 	if (target < limit->p2.dot_limit)
    593 	    clock.p2 = limit->p2.p2_slow;
    594 	else
    595 	    clock.p2 = limit->p2.p2_fast;
    596     }
    597 
    598     memset (best_clock, 0, sizeof (*best_clock));
    599 
    600     for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++)
    601     {
    602 	for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++)
    603 	{
    604 	    /* m1 is always 0 in IGD */
    605 	    if (clock.m2 >= clock.m1 && !IS_IGD(pI830))
    606 		break;
    607 	    for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++)
    608 	    {
    609 		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++)
    610 		{
    611 		    int this_err;
    612 
    613 		    intel_clock (pI830, refclk, &clock);
    614 
    615 		    if (!i830PllIsValid(crtc, &clock))
    616 			continue;
    617 
    618 		    this_err = abs(clock.dot - target);
    619 		    if (this_err < err) {
    620 			*best_clock = clock;
    621 			err = this_err;
    622 		    }
    623 		}
    624 	    }
    625 	}
    626     }
    627     return (err != target);
    628 }
    629 
    630 static Bool
    631 intel_find_pll_g4x(const intel_limit_t * limit, xf86CrtcPtr crtc,
    632                    int target, int refclk, intel_clock_t *best_clock)
    633 {
    634     ScrnInfoPtr pScrn = crtc->scrn;
    635     I830Ptr pI830 = I830PTR(pScrn);
    636     intel_clock_t clock;
    637     int  max_n;
    638     Bool found = FALSE;
    639     int err_most = target * 0.0048;
    640 
    641     if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
    642     {
    643         /* For LVDS, if the panel is on, just rely on its current settings for
    644          * dual-channel.  We haven't figured out how to reliably set up
    645          * different single/dual channel state, if we even can.
    646          */
    647         if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
    648             clock.p2 = limit->p2.p2_fast;
    649         else
    650             clock.p2 = limit->p2.p2_slow;
    651     } else {
    652         if (target < limit->p2.dot_limit)
    653             clock.p2 = limit->p2.p2_slow;
    654         else
    655             clock.p2 = limit->p2.p2_fast;
    656     }
    657 
    658     max_n = limit->n.max;
    659     /* based on hardware requirement prefer smaller n to precision */
    660     for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
    661         /* based on hardware requirement prefere larger m1,m2, p1*/
    662         for (clock.m1 = limit->m1.max;
    663             clock.m1 >= limit->m1.min; clock.m1--) {
    664             for (clock.m2 = limit->m2.max;
    665                 clock.m2 >= limit->m2.min; clock.m2--) {
    666                 for (clock.p1 = limit->p1.max;
    667                     clock.p1 >= limit->p1.min; clock.p1--) {
    668                     int this_err;
    669 
    670                     intel_clock (pI830, refclk, &clock);
    671                     if (!i830PllIsValid(crtc, &clock))
    672                         continue;
    673                     this_err = abs(clock.dot - target) ;
    674                     if (this_err < err_most) {
    675                         memcpy(best_clock, &clock, sizeof(intel_clock_t));
    676                         err_most = this_err;
    677                         /* prefer smaller n to precision */
    678                         max_n = clock.n;
    679                         found = TRUE;
    680                     }
    681                 }
    682             }
    683         }
    684     }
    685     return found;
    686 }
    687 
    688 void
    689 i830WaitForVblank(ScrnInfoPtr pScreen)
    690 {
    691     /* Wait for 20ms, i.e. one cycle at 50hz. */
    692     usleep(30000);
    693 }
    694 
    695 void
    696 i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
    697 {
    698     ScrnInfoPtr pScrn = crtc->scrn;
    699     I830Ptr pI830 = I830PTR(pScrn);
    700     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
    701     int plane = intel_crtc->plane;
    702     unsigned long Start, Offset, Stride;
    703     int dspbase = (plane == 0 ? DSPABASE : DSPBBASE);
    704     int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
    705     int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
    706     int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
    707 
    708     Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
    709     Stride = pScrn->displayWidth * pI830->cpp;
    710     if (pI830->front_buffer == NULL) {
    711 	/* During startup we may be called as part of monitor detection while
    712 	 * there is no memory allocation done, so just supply a dummy base
    713 	 * address.
    714 	 */
    715 	Start = 0;
    716     } else if (crtc->rotatedData != NULL) {
    717 	/* offset is done by shadow painting code, not here */
    718 	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
    719 	Offset = 0;
    720 	Stride = intel_crtc->rotate_mem->pitch;
    721     } else {
    722 	Start = pI830->front_buffer->offset;
    723     }
    724 
    725     crtc->x = x;
    726     crtc->y = y;
    727 
    728     OUTREG(dspstride, Stride);
    729     if (IS_I965G(pI830)) {
    730         OUTREG(dspbase, Offset);
    731 	POSTING_READ(dspbase);
    732         OUTREG(dspsurf, Start);
    733 	POSTING_READ(dspsurf);
    734 	OUTREG(dsptileoff, (y << 16) | x);
    735     } else {
    736 	OUTREG(dspbase, Start + Offset);
    737 	POSTING_READ(dspbase);
    738     }
    739 }
    740 
    741 /*
    742  * Both crtc activation and video overlay enablement on pipe B
    743  * will fail on i830 if pipe A is not running. This function
    744  * makes sure pipe A is active for these cases
    745  */
    746 
    747 int
    748 i830_crtc_pipe (xf86CrtcPtr crtc)
    749 {
    750     if (crtc == NULL)
    751 	return 0;
    752     return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
    753 }
    754 
    755 static xf86CrtcPtr
    756 i830_crtc_for_pipe (ScrnInfoPtr scrn, int pipe)
    757 {
    758     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    759     int			c;
    760 
    761     for (c = 0; c < xf86_config->num_crtc; c++)
    762     {
    763 	xf86CrtcPtr crtc = xf86_config->crtc[c];
    764 	if (i830_crtc_pipe (crtc) == pipe)
    765 	    return crtc;
    766     }
    767     return NULL;
    768 }
    769 
    770 Bool
    771 i830_pipe_a_require_activate (ScrnInfoPtr scrn)
    772 {
    773     xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
    774     /* VESA 640x480x72Hz mode to set on the pipe */
    775     static DisplayModeRec   mode = {
    776 	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
    777 	31500,
    778 	640, 664, 704, 832, 0,
    779 	480, 489, 491, 520, 0,
    780 	V_NHSYNC | V_NVSYNC,
    781 	0, 0,
    782 	0, 0, 0, 0, 0, 0, 0,
    783 	0, 0, 0, 0, 0, 0,
    784 	FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
    785     };
    786 
    787     if (!crtc)
    788 	return FALSE;
    789     if (crtc->enabled)
    790 	return FALSE;
    791     xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
    792     crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
    793     crtc->funcs->dpms (crtc, DPMSModeOn);
    794     return TRUE;
    795 }
    796 
    797 void
    798 i830_pipe_a_require_deactivate (ScrnInfoPtr scrn)
    799 {
    800     xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
    801 
    802     if (!crtc)
    803 	return;
    804     if (crtc->enabled)
    805 	return;
    806     crtc->funcs->dpms (crtc, DPMSModeOff);
    807     return;
    808 }
    809 
    810 /* FIXME: use pixmap private instead if possible */
    811 static Bool
    812 i830_display_tiled(xf86CrtcPtr crtc)
    813 {
    814     ScrnInfoPtr pScrn = crtc->scrn;
    815     I830Ptr pI830 = I830PTR(pScrn);
    816 
    817     /* Rotated data is currently linear, allocated either via XAA or EXA */
    818     if (crtc->rotatedData)
    819 	return FALSE;
    820 
    821     if (pI830->front_buffer && pI830->front_buffer->tiling != TILE_NONE)
    822 	return TRUE;
    823 
    824     return FALSE;
    825 }
    826 
    827 /*
    828  * Several restrictions:
    829  *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
    830  *   - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
    831  *   - no alpha buffer discard
    832  *   - no dual wide display
    833  *   - progressive mode only (DSP[AB]CNTR)
    834  *   - uncompressed fb is <= 2048 in width, 0 mod 8
    835  *   - uncompressed fb is <= 1536 in height, 0 mod 2
    836  *   - SR display watermarks must be equal between 16bpp and 32bpp?
    837  *
    838  * FIXME: verify above conditions are true
    839  *
    840  * Enable 8xx style FB compression
    841  */
    842 static void
    843 i830_enable_fb_compression_8xx(xf86CrtcPtr crtc)
    844 {
    845     ScrnInfoPtr pScrn = crtc->scrn;
    846     I830Ptr pI830 = I830PTR(pScrn);
    847     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
    848     uint32_t fbc_ctl = 0;
    849     unsigned long compressed_stride;
    850     int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
    851     unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
    852     unsigned long interval = 1000;
    853 
    854     if (INREG(FBC_CONTROL) & FBC_CTL_EN)
    855 	return;
    856 
    857     compressed_stride = pI830->compressed_front_buffer->size /
    858 	FBC_LL_SIZE;
    859 
    860     if (uncompressed_stride < compressed_stride)
    861 	compressed_stride = uncompressed_stride;
    862 
    863     /* FBC_CTL wants 64B units */
    864     compressed_stride = (compressed_stride / 64) - 1;
    865 
    866     /* Set it up... */
    867     /* Wait for compressing bit to clear */
    868     while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
    869 	; /* nothing */
    870     i830WaitForVblank(pScrn);
    871     OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
    872     OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + 6);
    873     OUTREG(FBC_CONTROL2, FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM |
    874 	   FBC_CTL_CPU_FENCE | plane);
    875     OUTREG(FBC_FENCE_OFF, crtc->y);
    876 
    877     /* Zero buffers */
    878     memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
    879 	   pI830->compressed_front_buffer->size);
    880     memset(pI830->FbBase + pI830->compressed_ll_buffer->offset, 0,
    881 	   pI830->compressed_ll_buffer->size);
    882 
    883     /* enable it... */
    884     fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
    885     fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
    886     fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
    887     fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE;
    888     fbc_ctl |= pI830->front_buffer->fence_nr;
    889     OUTREG(FBC_CONTROL, fbc_ctl);
    890 }
    891 
    892 /*
    893  * Disable 8xx style FB compression
    894  */
    895 static void
    896 i830_disable_fb_compression_8xx(xf86CrtcPtr crtc)
    897 {
    898     ScrnInfoPtr pScrn = crtc->scrn;
    899     I830Ptr pI830 = I830PTR(pScrn);
    900     uint32_t fbc_ctl;
    901 
    902     /* Disable compression */
    903     fbc_ctl = INREG(FBC_CONTROL);
    904     fbc_ctl &= ~FBC_CTL_EN;
    905     OUTREG(FBC_CONTROL, fbc_ctl);
    906 
    907     /* Wait for compressing bit to clear */
    908     while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
    909 	; /* nothing */
    910 }
    911 
    912 static void
    913 i830_disable_fb_compression2(xf86CrtcPtr crtc)
    914 {
    915     ScrnInfoPtr pScrn = crtc->scrn;
    916     I830Ptr pI830 = I830PTR(pScrn);
    917     uint32_t dpfc_ctl;
    918 
    919     /* Disable compression */
    920     dpfc_ctl = INREG(DPFC_CONTROL);
    921     dpfc_ctl &= ~DPFC_CTL_EN;
    922     OUTREG(DPFC_CONTROL, dpfc_ctl);
    923     i830WaitForVblank(pScrn);
    924 }
    925 
    926 static void
    927 i830_enable_fb_compression2(xf86CrtcPtr crtc)
    928 {
    929     ScrnInfoPtr pScrn = crtc->scrn;
    930     I830Ptr pI830 = I830PTR(pScrn);
    931     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
    932     int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB);
    933     unsigned long stall_watermark = 200, frames = 50;
    934 
    935     if (INREG(DPFC_CONTROL) & DPFC_CTL_EN)
    936 	return;
    937 
    938     /* Set it up... */
    939     i830_disable_fb_compression2(crtc);
    940     OUTREG(DPFC_CB_BASE, pI830->compressed_front_buffer->offset);
    941     /* Update i830_memory.c too if compression ratio changes */
    942     OUTREG(DPFC_CONTROL, plane | DPFC_CTL_FENCE_EN | DPFC_CTL_LIMIT_4X |
    943 	   pI830->front_buffer->fence_nr);
    944     OUTREG(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
    945 	   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
    946 	   (frames << DPFC_RECOMP_TIMER_COUNT_SHIFT));
    947     OUTREG(DPFC_FENCE_YOFF, crtc->y);
    948 
    949     /* Zero buffers */
    950     memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
    951 	   pI830->compressed_front_buffer->size);
    952 
    953     /* enable it... */
    954     OUTREG(DPFC_CONTROL, INREG(DPFC_CONTROL) | DPFC_CTL_EN);
    955 }
    956 
    957 static void
    958 i830_enable_fb_compression(xf86CrtcPtr crtc)
    959 {
    960     ScrnInfoPtr pScrn = crtc->scrn;
    961     I830Ptr pI830 = I830PTR(pScrn);
    962 
    963     if (IS_GM45(pI830))
    964 	return i830_enable_fb_compression2(crtc);
    965 
    966     i830_enable_fb_compression_8xx(crtc);
    967 }
    968 
    969 static void
    970 i830_disable_fb_compression(xf86CrtcPtr crtc)
    971 {
    972     ScrnInfoPtr pScrn = crtc->scrn;
    973     I830Ptr pI830 = I830PTR(pScrn);
    974 
    975     if (IS_GM45(pI830))
    976 	return i830_disable_fb_compression2(crtc);
    977 
    978     i830_disable_fb_compression_8xx(crtc);
    979 }
    980 
    981 static Bool
    982 i830_use_fb_compression(xf86CrtcPtr crtc)
    983 {
    984     ScrnInfoPtr pScrn = crtc->scrn;
    985     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    986     I830Ptr pI830 = I830PTR(pScrn);
    987     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
    988     unsigned long uncompressed_size;
    989     int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
    990     int i, count = 0;
    991 
    992     /* Only available on one pipe at a time */
    993     for (i = 0; i < xf86_config->num_crtc; i++) {
    994 	if (xf86_config->crtc[i]->enabled)
    995 	    count++;
    996     }
    997 
    998     /* Here we disable it to catch one->two pipe enabled configs */
    999     if (count > 1) {
   1000 	if (i830_fb_compression_supported(pI830))
   1001 	    i830_disable_fb_compression(crtc);
   1002 	return FALSE;
   1003     }
   1004 
   1005     if (!pI830->fb_compression)
   1006 	return FALSE;
   1007 
   1008     if (!i830_display_tiled(crtc))
   1009 	return FALSE;
   1010 
   1011     /* Pre-965 only supports plane A */
   1012     if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
   1013 	return FALSE;
   1014 
   1015     /* Need 15, 16, or 32 (w/alpha) pixel format */
   1016     if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
   1017 	  pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
   1018 	return FALSE;
   1019 
   1020     /* Can't cache more lines than we can track */
   1021     if (crtc->mode.VDisplay > FBC_LL_SIZE)
   1022 	return FALSE;
   1023 
   1024     /*
   1025      * Make sure the compressor doesn't go past the end of our compressed
   1026      * buffer if the uncompressed size is large.
   1027      */
   1028     uncompressed_size = crtc->mode.HDisplay * crtc->mode.VDisplay *
   1029 	pI830->cpp;
   1030     if (pI830->compressed_front_buffer->size < uncompressed_size)
   1031 	return FALSE;
   1032 
   1033     /*
   1034      * No checks for pixel multiply, incl. horizontal, or interlaced modes
   1035      * since they're currently unused.
   1036      */
   1037     return TRUE;
   1038 }
   1039 
   1040 #if defined(DRM_IOCTL_MODESET_CTL)
   1041 static void i830_modeset_ctl(xf86CrtcPtr crtc, int pre)
   1042 {
   1043     ScrnInfoPtr pScrn = crtc->scrn;
   1044     I830Ptr pI830 = I830PTR(pScrn);
   1045     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1046     struct drm_modeset_ctl modeset;
   1047 
   1048     if (pI830->directRenderingType <= DRI_NONE)
   1049       return;
   1050 
   1051     modeset.crtc = intel_crtc->pipe;
   1052 
   1053     /*
   1054      * DPMS will be called many times (especially off), but we only
   1055      * want to catch the transition from on->off and off->on.
   1056      */
   1057     if (pre && intel_crtc->dpms_mode != DPMSModeOff) {
   1058 	/* On -> off is a pre modeset */
   1059 	modeset.cmd = _DRM_PRE_MODESET;
   1060 	ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
   1061     } else if (!pre && intel_crtc->dpms_mode == DPMSModeOff) {
   1062 	/* Off -> on means post modeset */
   1063 	modeset.cmd = _DRM_POST_MODESET;
   1064 	ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
   1065     }
   1066 }
   1067 #else
   1068 static void i830_modeset_ctl(xf86CrtcPtr crtc, int dpms_state)
   1069 {
   1070     return;
   1071 }
   1072 #endif /* DRM_IOCTL_MODESET_CTL */
   1073 
   1074 static void
   1075 i830_disable_vga_plane (xf86CrtcPtr crtc)
   1076 {
   1077     ScrnInfoPtr pScrn = crtc->scrn;
   1078     I830Ptr pI830 = I830PTR(pScrn);
   1079     uint8_t sr01;
   1080 
   1081     /*
   1082      * Bug #17235: G4X machine needs following steps
   1083      * for disable VGA.
   1084      * - set bit 5 of SR01;
   1085      * - Wait 30us;
   1086      * - disable vga plane;
   1087      * - restore SR01;
   1088      */
   1089     if (IS_G4X(pI830)) {
   1090 	OUTREG8(SRX, 1);
   1091 	sr01 = INREG8(SRX + 1);
   1092 	OUTREG8(SRX + 1, sr01 | (1 << 5));
   1093 	usleep(30);
   1094     }
   1095 
   1096     OUTREG(VGACNTRL, VGA_DISP_DISABLE);
   1097     i830WaitForVblank(pScrn);
   1098 
   1099     /* restore SR01 */
   1100     if (IS_G4X(pI830)) {
   1101 	OUTREG8(SRX, 1);
   1102 	OUTREG8(SRX + 1, sr01);
   1103     }
   1104 }
   1105 
   1106 static void
   1107 i830_crtc_enable(xf86CrtcPtr crtc)
   1108 {
   1109     ScrnInfoPtr pScrn = crtc->scrn;
   1110     I830Ptr pI830 = I830PTR(pScrn);
   1111     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1112     int pipe = intel_crtc->pipe;
   1113     int plane = intel_crtc->plane;
   1114     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
   1115     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
   1116     int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
   1117     int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
   1118     uint32_t temp;
   1119 
   1120     /* Enable the DPLL */
   1121     temp = INREG(dpll_reg);
   1122     if ((temp & DPLL_VCO_ENABLE) == 0)
   1123     {
   1124 	OUTREG(dpll_reg, temp);
   1125 	POSTING_READ(dpll_reg);
   1126 	/* Wait for the clocks to stabilize. */
   1127 	usleep(150);
   1128 	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
   1129 	POSTING_READ(dpll_reg);
   1130 	/* Wait for the clocks to stabilize. */
   1131 	usleep(150);
   1132 	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
   1133 	POSTING_READ(dpll_reg);
   1134 	/* Wait for the clocks to stabilize. */
   1135 	usleep(150);
   1136     }
   1137 
   1138     /* Enable the pipe */
   1139     temp = INREG(pipeconf_reg);
   1140     if ((temp & PIPEACONF_ENABLE) == 0)
   1141 	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
   1142 
   1143     /* Enable the plane */
   1144     temp = INREG(dspcntr_reg);
   1145     if ((temp & DISPLAY_PLANE_ENABLE) == 0)
   1146     {
   1147 	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
   1148 	/* Flush the plane changes */
   1149 	OUTREG(dspbase_reg, INREG(dspbase_reg));
   1150     }
   1151 
   1152     i830_crtc_load_lut(crtc);
   1153 
   1154     /* Give the overlay scaler a chance to enable if it's on this pipe */
   1155     i830_crtc_dpms_video(crtc, TRUE);
   1156 
   1157     /* Reenable compression if needed */
   1158     if (i830_use_fb_compression(crtc))
   1159 	i830_enable_fb_compression(crtc);
   1160     i830_modeset_ctl(crtc, 0);
   1161 }
   1162 
   1163 void
   1164 i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
   1165 {
   1166     ScrnInfoPtr pScrn = crtc->scrn;
   1167     I830Ptr pI830 = I830PTR(pScrn);
   1168     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1169     int pipe = intel_crtc->pipe;
   1170     int plane = intel_crtc->plane;
   1171     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
   1172     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
   1173     int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
   1174     int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
   1175     uint32_t temp;
   1176 
   1177     i830_modeset_ctl(crtc, 1);
   1178     /* Shut off compression if in use */
   1179     if (i830_use_fb_compression(crtc))
   1180 	i830_disable_fb_compression(crtc);
   1181 
   1182     /* Give the overlay scaler a chance to disable if it's on this pipe */
   1183     i830_crtc_dpms_video(crtc, FALSE);
   1184 
   1185     /*
   1186      * The documentation says :
   1187      * - Disable planes (VGA or hires)
   1188      * - Disable pipe
   1189      * - Disable VGA display
   1190      */
   1191 
   1192     /* Disable display plane */
   1193     temp = INREG(dspcntr_reg);
   1194     if ((temp & DISPLAY_PLANE_ENABLE) != 0)
   1195     {
   1196 	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
   1197 	/* Flush the plane changes */
   1198 	OUTREG(dspbase_reg, INREG(dspbase_reg));
   1199 	POSTING_READ(dspbase_reg);
   1200     }
   1201 
   1202     if (!IS_I9XX(pI830)) {
   1203 	/* Wait for vblank for the disable to take effect */
   1204 	i830WaitForVblank(pScrn);
   1205     }
   1206 
   1207     /* May need to leave pipe A on */
   1208     if (disable_pipe)
   1209     {
   1210 	/* Next, disable display pipes */
   1211 	temp = INREG(pipeconf_reg);
   1212 	if ((temp & PIPEACONF_ENABLE) != 0) {
   1213 	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
   1214 	    POSTING_READ(pipeconf_reg);
   1215 	}
   1216 
   1217 	/* Wait for vblank for the disable to take effect. */
   1218 	i830WaitForVblank(pScrn);
   1219 
   1220 	temp = INREG(dpll_reg);
   1221 	if ((temp & DPLL_VCO_ENABLE) != 0) {
   1222 	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
   1223 	    POSTING_READ(dpll_reg);
   1224 	}
   1225 
   1226 	/* Wait for the clocks to turn off. */
   1227 	usleep(150);
   1228     }
   1229 
   1230     /* Disable the VGA plane that we never use. */
   1231     i830_disable_vga_plane (crtc);
   1232 }
   1233 
   1234 /**
   1235  * Sets the power management mode of the pipe and plane.
   1236  *
   1237  * This code should probably grow support for turning the cursor off and back
   1238  * on appropriately at the same time as we're turning the pipe off/on.
   1239  */
   1240 static void
   1241 i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
   1242 {
   1243     ScrnInfoPtr pScrn = crtc->scrn;
   1244     I830Ptr pI830 = I830PTR(pScrn);
   1245     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1246     int pipe = intel_crtc->pipe;
   1247     Bool disable_pipe = TRUE;
   1248 
   1249     /* XXX: When our outputs are all unaware of DPMS modes other than off and
   1250      * on, we should map those modes to DPMSModeOff in the CRTC.
   1251      */
   1252     switch (mode) {
   1253     case DPMSModeOn:
   1254     case DPMSModeStandby:
   1255     case DPMSModeSuspend:
   1256 	i830_crtc_enable(crtc);
   1257 	break;
   1258     case DPMSModeOff:
   1259 	if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
   1260 	    disable_pipe = FALSE;
   1261 	i830_crtc_disable(crtc, disable_pipe);
   1262 	intel_crtc->enabled = FALSE;
   1263 	break;
   1264     }
   1265 
   1266     intel_crtc->dpms_mode = mode;
   1267 }
   1268 
   1269 static Bool
   1270 i830_crtc_lock (xf86CrtcPtr crtc)
   1271 {
   1272     /* Sync the engine before mode switch, to finish any outstanding
   1273      * WAIT_FOR_EVENTS that may rely on CRTC state.
   1274      */
   1275     I830Sync(crtc->scrn);
   1276 
   1277     return FALSE;
   1278 }
   1279 
   1280 static void
   1281 i830_crtc_unlock (xf86CrtcPtr crtc)
   1282 {
   1283 }
   1284 
   1285 static void
   1286 i830_crtc_prepare (xf86CrtcPtr crtc)
   1287 {
   1288     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
   1289     /* Temporarily turn off FB compression during modeset */
   1290     if (i830_use_fb_compression(crtc))
   1291         i830_disable_fb_compression(crtc);
   1292     if (intel_crtc->enabled)
   1293 	crtc->funcs->hide_cursor (crtc);
   1294     crtc->funcs->dpms (crtc, DPMSModeOff);
   1295 }
   1296 
   1297 static void
   1298 i830_crtc_commit (xf86CrtcPtr crtc)
   1299 {
   1300     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
   1301     Bool		deactivate = FALSE;
   1302 
   1303     if (!intel_crtc->enabled && intel_crtc->pipe != 0)
   1304 	deactivate = i830_pipe_a_require_activate (crtc->scrn);
   1305 
   1306     intel_crtc->enabled = TRUE;
   1307 
   1308     crtc->funcs->dpms (crtc, DPMSModeOn);
   1309     if (crtc->scrn->pScreen != NULL)
   1310 	xf86_reload_cursors (crtc->scrn->pScreen);
   1311     if (deactivate)
   1312 	i830_pipe_a_require_deactivate (crtc->scrn);
   1313 
   1314     /* Reenable FB compression if possible */
   1315     if (i830_use_fb_compression(crtc))
   1316 	i830_enable_fb_compression(crtc);
   1317 }
   1318 
   1319 void
   1320 i830_output_prepare (xf86OutputPtr output)
   1321 {
   1322     output->funcs->dpms (output, DPMSModeOff);
   1323 }
   1324 
   1325 void
   1326 i830_output_commit (xf86OutputPtr output)
   1327 {
   1328     output->funcs->dpms (output, DPMSModeOn);
   1329 }
   1330 
   1331 static Bool
   1332 i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
   1333 		     DisplayModePtr adjusted_mode)
   1334 {
   1335     return TRUE;
   1336 }
   1337 
   1338 /** Returns the core display clock speed for i830 - i945 */
   1339 static int
   1340 i830_get_core_clock_speed(ScrnInfoPtr pScrn)
   1341 {
   1342     I830Ptr pI830 = I830PTR(pScrn);
   1343 
   1344     /* Core clock values taken from the published datasheets.
   1345      * The 830 may go up to 166 Mhz, which we should check.
   1346      */
   1347     if (IS_I945G(pI830) || (IS_G33CLASS(pI830) && !IS_IGDGM(pI830)))
   1348 	return 400000;
   1349     else if (IS_I915G(pI830))
   1350 	return 333000;
   1351     else if (IS_I945GM(pI830) || IS_845G(pI830) || IS_IGDGM(pI830))
   1352 	return 200000;
   1353     else if (IS_I915GM(pI830)) {
   1354 	uint16_t gcfgc;
   1355 
   1356       pci_device_cfg_read_u16 (pI830->PciInfo, &gcfgc, I915_GCFGC);
   1357       if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
   1358 	    return 133000;
   1359 	else {
   1360 	    switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
   1361 	    case I915_DISPLAY_CLOCK_333_MHZ:
   1362 		return 333000;
   1363 	    default:
   1364 	    case I915_DISPLAY_CLOCK_190_200_MHZ:
   1365 		return 190000;
   1366 	    }
   1367 	}
   1368     } else if (IS_I865G(pI830))
   1369 	return 266000;
   1370     else if (IS_I855(pI830)) {
   1371         struct pci_device *bridge = intel_host_bridge ();
   1372 	uint16_t hpllcc;
   1373 	pci_device_cfg_read_u16 (bridge, &hpllcc, I855_HPLLCC);
   1374 
   1375 	/* Assume that the hardware is in the high speed state.  This
   1376 	 * should be the default.
   1377 	 */
   1378 	switch (hpllcc & I855_CLOCK_CONTROL_MASK) {
   1379 	case I855_CLOCK_133_200:
   1380 	case I855_CLOCK_100_200:
   1381 	    return 200000;
   1382 	case I855_CLOCK_166_250:
   1383 	    return 250000;
   1384 	case I855_CLOCK_100_133:
   1385 	    return 133000;
   1386 	}
   1387     } else /* 852, 830 */
   1388 	return 133000;
   1389 
   1390     return 0; /* Silence gcc warning */
   1391 }
   1392 
   1393 /**
   1394  * Return the pipe currently connected to the panel fitter,
   1395  * or -1 if the panel fitter is not present or not in use
   1396  */
   1397 static int
   1398 i830_panel_fitter_pipe(I830Ptr pI830)
   1399 {
   1400     uint32_t pfit_control;
   1401 
   1402     /* i830 doesn't have a panel fitter */
   1403     if (IS_I830(pI830))
   1404 	return -1;
   1405 
   1406     pfit_control = INREG(PFIT_CONTROL);
   1407 
   1408     /* See if the panel fitter is in use */
   1409     if ((pfit_control & PFIT_ENABLE) == 0)
   1410 	return -1;
   1411 
   1412     /* 965 can place panel fitter on either pipe */
   1413     if (IS_I965G(pI830))
   1414 	return (pfit_control & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
   1415 
   1416     /* older chips can only use pipe 1 */
   1417     return 1;
   1418 }
   1419 
   1420 /**
   1421  * Sets up the DSPARB register to split the display fifo appropriately between
   1422  * the display planes.
   1423  *
   1424  * Adjusting this register requires that the planes be off.
   1425  */
   1426 static void
   1427 i830_update_dsparb(ScrnInfoPtr pScrn)
   1428 {
   1429    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1430    I830Ptr pI830 = I830PTR(pScrn);
   1431    int total_hdisplay = 0, planea_hdisplay = 0, planeb_hdisplay = 0;
   1432    int fifo_entries = 0, planea_entries = 0, planeb_entries = 0, i;
   1433 
   1434    if ((INREG(DSPACNTR) & DISPLAY_PLANE_ENABLE) &&
   1435        (INREG(DSPBCNTR) & DISPLAY_PLANE_ENABLE))
   1436        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1437 		  "tried to update DSPARB with both planes enabled!\n");
   1438 
   1439   /*
   1440     * FIFO entries will be split based on programmed modes
   1441     */
   1442    if (IS_I965GM(pI830))
   1443        fifo_entries = 127;
   1444    else if (IS_I9XX(pI830))
   1445        fifo_entries = 95;
   1446    else if (IS_MOBILE(pI830)) {
   1447        fifo_entries = 255;
   1448    } else {
   1449 	/* The 845/865 only have a AEND field.  Though the field size would
   1450 	* allow 128 entries, the 865 rendered the cursor wrong then.
   1451 	* The BIOS set it up for 96.
   1452 	*/
   1453 	fifo_entries = 95;
   1454    }
   1455 
   1456    for (i = 0; i < xf86_config->num_crtc; i++) {
   1457       xf86CrtcPtr crtc = xf86_config->crtc[i];
   1458       I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1459       if (crtc->enabled) {
   1460 	  total_hdisplay += crtc->mode.HDisplay;
   1461 	  if (intel_crtc->plane == 0)
   1462 	      planea_hdisplay = crtc->mode.HDisplay;
   1463 	  else
   1464 	      planeb_hdisplay = crtc->mode.HDisplay;
   1465       }
   1466    }
   1467 
   1468    planea_entries = fifo_entries * planea_hdisplay / total_hdisplay;
   1469    planeb_entries = fifo_entries * planeb_hdisplay / total_hdisplay;
   1470 
   1471    if (IS_I9XX(pI830))
   1472        OUTREG(DSPARB,
   1473 	      ((planea_entries + planeb_entries) << DSPARB_CSTART_SHIFT) |
   1474 	      (planea_entries << DSPARB_BSTART_SHIFT));
   1475    else if (IS_MOBILE(pI830))
   1476        OUTREG(DSPARB,
   1477 	      ((planea_entries + planeb_entries) << DSPARB_BEND_SHIFT) |
   1478 	      (planea_entries << DSPARB_AEND_SHIFT));
   1479    else
   1480        OUTREG(DSPARB, planea_entries << DSPARB_AEND_SHIFT);
   1481 }
   1482 
   1483 /**
   1484  * Sets up registers for the given mode/adjusted_mode pair.
   1485  *
   1486  * The clocks, CRTCs and outputs attached to this CRTC must be off.
   1487  *
   1488  * This shouldn't enable any clocks, CRTCs, or outputs, but they should
   1489  * be easily turned on/off after this.
   1490  */
   1491 static void
   1492 i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
   1493 		   DisplayModePtr adjusted_mode,
   1494 		   int x, int y)
   1495 {
   1496     ScrnInfoPtr pScrn = crtc->scrn;
   1497     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1498     I830Ptr pI830 = I830PTR(pScrn);
   1499     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1500     I830OutputPrivatePtr intel_output;
   1501     int pipe = intel_crtc->pipe;
   1502     int plane = intel_crtc->plane;
   1503     int fp_reg = (pipe == 0) ? FPA0 : FPB0;
   1504     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
   1505     int dpll_md_reg = (pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
   1506     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
   1507     int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
   1508     int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
   1509     int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
   1510     int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
   1511     int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
   1512     int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
   1513     int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
   1514     int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
   1515     int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
   1516     int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
   1517     int i, num_outputs = 0;
   1518     int refclk;
   1519     intel_clock_t clock;
   1520     uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
   1521     Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
   1522     Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
   1523     const intel_limit_t *limit;
   1524 
   1525     /* Set up some convenient bools for what outputs are connected to
   1526      * our pipe, used in DPLL setup.
   1527      */
   1528     for (i = 0; i < xf86_config->num_output; i++) {
   1529 	xf86OutputPtr  output = xf86_config->output[i];
   1530 	intel_output = output->driver_private;
   1531 
   1532 	if (output->crtc != crtc)
   1533 	    continue;
   1534 
   1535 	switch (intel_output->type) {
   1536 	case I830_OUTPUT_LVDS:
   1537 	    is_lvds = TRUE;
   1538 	    lvds_bits = intel_output->lvds_bits;
   1539 	    break;
   1540 	case I830_OUTPUT_SDVO:
   1541 	case I830_OUTPUT_HDMI:
   1542 	    is_sdvo = TRUE;
   1543 	    if (intel_output->needs_tv_clock)
   1544 		is_tv = TRUE;
   1545 	    break;
   1546 	case I830_OUTPUT_DVO_TMDS:
   1547 	case I830_OUTPUT_DVO_LVDS:
   1548 	case I830_OUTPUT_DVO_TVOUT:
   1549 	    is_dvo = TRUE;
   1550 	    break;
   1551 	case I830_OUTPUT_TVOUT:
   1552 	    is_tv = TRUE;
   1553 	    break;
   1554 	case I830_OUTPUT_ANALOG:
   1555 	    is_crt = TRUE;
   1556 	    break;
   1557 	}
   1558 
   1559 	num_outputs++;
   1560     }
   1561 
   1562     if (num_outputs > 1)
   1563 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n");
   1564 
   1565     /* Don't use SSC when cloned */
   1566     if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2) {
   1567 	refclk = pI830->lvds_ssc_freq * 1000;
   1568 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1569 		   "using SSC reference clock of %d MHz\n", refclk / 1000);
   1570     } else if (IS_I9XX(pI830)) {
   1571 	refclk = 96000;
   1572     } else {
   1573 	refclk = 48000;
   1574     }
   1575 
   1576     /*
   1577      * Returns a set of divisors for the desired target clock with the given
   1578      * refclk, or FALSE.  The returned values represent the clock equation:
   1579      * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
   1580      */
   1581     limit = intel_limit (crtc);
   1582     ok = limit->find_pll(limit, crtc, adjusted_mode->Clock, refclk, &clock);
   1583     if (!ok)
   1584 	FatalError("Couldn't find PLL settings for mode!\n");
   1585 
   1586     if (fabs(adjusted_mode->Clock - clock.dot) / clock.dot > .02) {
   1587 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   1588 		   "Chosen PLL clock of %.1f Mhz more than 2%% away from "
   1589 		   "desired %.1f Mhz\n",
   1590 		   (float)clock.dot / 1000,
   1591 		   (float)adjusted_mode->Clock / 1000);
   1592     }
   1593 
   1594     /* SDVO TV has fixed PLL values depends on its clock range,
   1595        this mirrors vbios setting. */
   1596     if (is_sdvo && is_tv) {
   1597 	if (adjusted_mode->Clock >= 100000 &&
   1598 		adjusted_mode->Clock < 140500) {
   1599 	    clock.p1 = 2;
   1600 	    clock.p2 = 10;
   1601 	    clock.n = 3;
   1602 	    clock.m1 = 16;
   1603 	    clock.m2 = 8;
   1604 	} else if (adjusted_mode->Clock >= 140500 &&
   1605 		adjusted_mode->Clock <= 200000) {
   1606 	    clock.p1 = 1;
   1607 	    clock.p2 = 10;
   1608 	    clock.n = 6;
   1609 	    clock.m1 = 12;
   1610 	    clock.m2 = 8;
   1611 	}
   1612     }
   1613 
   1614     if (IS_IGD(pI830))
   1615 	fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
   1616     else
   1617 	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
   1618 
   1619     dpll = DPLL_VGA_MODE_DIS;
   1620     if (IS_I9XX(pI830)) {
   1621 	if (is_lvds)
   1622 	    dpll |= DPLLB_MODE_LVDS;
   1623 	else
   1624 	    dpll |= DPLLB_MODE_DAC_SERIAL;
   1625 	if (is_sdvo)
   1626 	{
   1627 	    dpll |= DPLL_DVO_HIGH_SPEED;
   1628 	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)))
   1629 	    {
   1630 		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
   1631 		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
   1632 	    }
   1633 	}
   1634 
   1635 	/* compute bitmask from p1 value */
   1636 	if (IS_IGD(pI830))
   1637 	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
   1638 	else
   1639 	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
   1640 	switch (clock.p2) {
   1641 	case 5:
   1642 	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
   1643 	    break;
   1644 	case 7:
   1645 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
   1646 	    break;
   1647 	case 10:
   1648 	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
   1649 	    break;
   1650 	case 14:
   1651 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
   1652 	    break;
   1653 	}
   1654 	if (IS_I965G(pI830) && !IS_GM45(pI830))
   1655 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
   1656     } else {
   1657 	if (is_lvds) {
   1658 	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
   1659 	} else {
   1660 	    if (clock.p1 == 2)
   1661 		dpll |= PLL_P1_DIVIDE_BY_TWO;
   1662 	    else
   1663 		dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
   1664 	    if (clock.p2 == 4)
   1665 		dpll |= PLL_P2_DIVIDE_BY_4;
   1666 	}
   1667     }
   1668 
   1669     if (is_sdvo && is_tv)
   1670 	dpll |= PLL_REF_INPUT_TVCLKINBC;
   1671     else if (is_tv)
   1672     {
   1673 	/* XXX: just matching BIOS for now */
   1674 /*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
   1675 	dpll |= 3;
   1676     }
   1677     else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2)
   1678 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
   1679     else
   1680 	dpll |= PLL_REF_INPUT_DREFCLK;
   1681 
   1682     /* Set up the display plane register */
   1683     dspcntr = DISPPLANE_GAMMA_ENABLE;
   1684     switch (pScrn->bitsPerPixel) {
   1685     case 8:
   1686 	dspcntr |= DISPPLANE_8BPP;
   1687 	break;
   1688     case 16:
   1689 	if (pScrn->depth == 15)
   1690 	    dspcntr |= DISPPLANE_15_16BPP;
   1691 	else
   1692 	    dspcntr |= DISPPLANE_16BPP;
   1693 	break;
   1694     case 32:
   1695 	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
   1696 	break;
   1697     default:
   1698 	FatalError("unknown display bpp\n");
   1699     }
   1700 
   1701     if (pipe == 0)
   1702 	dspcntr |= DISPPLANE_SEL_PIPE_A;
   1703     else
   1704 	dspcntr |= DISPPLANE_SEL_PIPE_B;
   1705 
   1706     if (IS_I965G(pI830) && i830_display_tiled(crtc))
   1707 	dspcntr |= DISPLAY_PLANE_TILED;
   1708 
   1709     pipeconf = INREG(pipeconf_reg);
   1710     if (pipe == 0 && !IS_I965G(pI830))
   1711     {
   1712 	/* Enable pixel doubling when the dot clock is > 90% of the (display)
   1713 	 * core speed.
   1714 	 *
   1715 	 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
   1716 	 * pipe == 0 check?
   1717 	 */
   1718 	if (mode->Clock > i830_get_core_clock_speed(pScrn) * 9 / 10)
   1719 	    pipeconf |= PIPEACONF_DOUBLE_WIDE;
   1720 	else
   1721 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
   1722     }
   1723     /*
   1724      * This "shouldn't" be needed as the dpms on code
   1725      * will be run after the mode is set. On 9xx, it helps.
   1726      * On 855, it can lock up the chip (and the entire machine)
   1727      */
   1728     if (!IS_I85X (pI830))
   1729     {
   1730 	dspcntr |= DISPLAY_PLANE_ENABLE;
   1731 	pipeconf |= PIPEACONF_ENABLE;
   1732 	dpll |= DPLL_VCO_ENABLE;
   1733     }
   1734 
   1735     /* Disable the panel fitter if it was on our pipe */
   1736     if (i830_panel_fitter_pipe (pI830) == pipe)
   1737 	OUTREG(PFIT_CONTROL, 0);
   1738 
   1739     if (pI830->debug_modes) {
   1740 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1741 		   "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
   1742 	xf86PrintModeline(pScrn->scrnIndex, mode);
   1743 	if (!xf86ModesEqual(mode, adjusted_mode)) {
   1744 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1745 		       "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
   1746 	    xf86PrintModeline(pScrn->scrnIndex, adjusted_mode);
   1747 	}
   1748 	i830PrintPll(pScrn, "chosen", &clock);
   1749     }
   1750 
   1751     if (dpll & DPLL_VCO_ENABLE)
   1752     {
   1753 	OUTREG(fp_reg, fp);
   1754 	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
   1755 	POSTING_READ(dpll_reg);
   1756 	usleep(150);
   1757     }
   1758 
   1759     /* The LVDS pin pair needs to be on before the DPLLs are enabled.
   1760      * This is an exception to the general rule that mode_set doesn't turn
   1761      * things on.
   1762      */
   1763     if (is_lvds)
   1764     {
   1765 	uint32_t lvds = INREG(LVDS);
   1766 
   1767 	lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
   1768 	/* Set the B0-B3 data pairs corresponding to whether we're going to
   1769 	 * set the DPLLs for dual-channel mode or not.
   1770 	 */
   1771 	if (clock.p2 == I9XX_P2_LVDS_FAST)
   1772 	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
   1773 	else
   1774 	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
   1775 
   1776 	if (pI830->lvds_24_bit_mode) {
   1777 	    /* Option set which requests 24-bit mode
   1778 	     * (LVDS_A3_POWER_UP, as opposed to 18-bit mode) here; we
   1779 	     * still need to look more thoroughly into how panels
   1780 	     * behave in the two modes.  This option enables that
   1781 	     * experimentation.
   1782 	     */
   1783 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1784 		       "Selecting less common 24 bit TMDS pixel format.\n");
   1785 	    lvds |= LVDS_A3_POWER_UP;
   1786 	    lvds |= LVDS_DATA_FORMAT_DOT_ONE;
   1787 	} else {
   1788 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1789 		       "Selecting standard 18 bit TMDS pixel format.\n");
   1790 	}
   1791 
   1792 	/* Enable dithering if we're in 18-bit mode. */
   1793 	if (IS_I965G(pI830))
   1794 	{
   1795 	    if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
   1796 		lvds &= ~LVDS_DITHER_ENABLE;
   1797 	    else
   1798 		lvds |= LVDS_DITHER_ENABLE;
   1799 	}
   1800 
   1801 	lvds |= lvds_bits;
   1802 
   1803 	OUTREG(LVDS, lvds);
   1804 	POSTING_READ(LVDS);
   1805     }
   1806 
   1807     OUTREG(fp_reg, fp);
   1808     OUTREG(dpll_reg, dpll);
   1809     POSTING_READ(dpll_reg);
   1810     /* Wait for the clocks to stabilize. */
   1811     usleep(150);
   1812 
   1813     if (IS_I965G(pI830)) {
   1814 	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
   1815 	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
   1816 	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
   1817     } else {
   1818 	/* write it again -- the BIOS does, after all */
   1819 	OUTREG(dpll_reg, dpll);
   1820     }
   1821     POSTING_READ(dpll_reg);
   1822     /* Wait for the clocks to stabilize. */
   1823     usleep(150);
   1824 
   1825     if (!DSPARB_HWCONTROL(pI830))
   1826 	i830_update_dsparb(pScrn);
   1827 
   1828     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
   1829 	((adjusted_mode->CrtcHTotal - 1) << 16));
   1830     OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
   1831 	((adjusted_mode->CrtcHBlankEnd - 1) << 16));
   1832     OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
   1833 	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
   1834     OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
   1835 	((adjusted_mode->CrtcVTotal - 1) << 16));
   1836 
   1837     OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
   1838 	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
   1839     OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
   1840 	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
   1841     /* pipesrc and dspsize control the size that is scaled from, which should
   1842      * always be the user's requested size.
   1843      */
   1844     OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
   1845     OUTREG(dsppos_reg, 0);
   1846     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
   1847     OUTREG(pipeconf_reg, pipeconf);
   1848     POSTING_READ(pipeconf_reg);
   1849     i830WaitForVblank(pScrn);
   1850 
   1851     OUTREG(dspcntr_reg, dspcntr);
   1852     /* Flush the plane changes */
   1853     i830PipeSetBase(crtc, x, y);
   1854 
   1855     i830WaitForVblank(pScrn);
   1856 }
   1857 
   1858 
   1859 /** Loads the palette/gamma unit for the CRTC with the prepared values */
   1860 static void
   1861 i830_crtc_load_lut(xf86CrtcPtr crtc)
   1862 {
   1863     ScrnInfoPtr pScrn = crtc->scrn;
   1864     I830Ptr pI830 = I830PTR(pScrn);
   1865     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1866     int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
   1867     int i;
   1868 
   1869     /* The clocks have to be on to load the palette. */
   1870     if (!crtc->enabled)
   1871 	return;
   1872 
   1873     for (i = 0; i < 256; i++) {
   1874 	OUTREG(palreg + 4 * i,
   1875 	       (intel_crtc->lut_r[i] << 16) |
   1876 	       (intel_crtc->lut_g[i] << 8) |
   1877 	       intel_crtc->lut_b[i]);
   1878     }
   1879 }
   1880 
   1881 /** Sets the color ramps on behalf of RandR */
   1882 static void
   1883 i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
   1884 		    int size)
   1885 {
   1886     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1887     int i;
   1888 
   1889     assert(size == 256);
   1890 
   1891     for (i = 0; i < 256; i++) {
   1892 	intel_crtc->lut_r[i] = red[i] >> 8;
   1893 	intel_crtc->lut_g[i] = green[i] >> 8;
   1894 	intel_crtc->lut_b[i] = blue[i] >> 8;
   1895     }
   1896 
   1897     i830_crtc_load_lut(crtc);
   1898 }
   1899 
   1900 /**
   1901  * Allocates memory for a locked-in-framebuffer shadow of the given
   1902  * width and height for this CRTC's rotated shadow framebuffer.
   1903  */
   1904 
   1905 static void *
   1906 i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
   1907 {
   1908     ScrnInfoPtr pScrn = crtc->scrn;
   1909     I830Ptr pI830 = I830PTR(pScrn);
   1910     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1911     unsigned long rotate_pitch;
   1912     int align = KB(4), size;
   1913 
   1914     width = i830_pad_drawable_width(width, pI830->cpp);
   1915     rotate_pitch = width * pI830->cpp;
   1916     size = rotate_pitch * height;
   1917 
   1918     assert(intel_crtc->rotate_mem == NULL);
   1919     intel_crtc->rotate_mem = i830_allocate_memory(pScrn, "rotated crtc",
   1920 						  size, rotate_pitch, align,
   1921 						  0, TILE_NONE);
   1922     if (intel_crtc->rotate_mem == NULL) {
   1923 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1924 		   "Couldn't allocate shadow memory for rotated CRTC\n");
   1925 	return NULL;
   1926     }
   1927     memset(pI830->FbBase + intel_crtc->rotate_mem->offset, 0, size);
   1928 
   1929     return pI830->FbBase + intel_crtc->rotate_mem->offset;
   1930 }
   1931 
   1932 /**
   1933  * Creates a pixmap for this CRTC's rotated shadow framebuffer.
   1934  */
   1935 static PixmapPtr
   1936 i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
   1937 {
   1938     ScrnInfoPtr pScrn = crtc->scrn;
   1939     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1940     I830Ptr pI830 = I830PTR(pScrn);
   1941     int rotate_pitch;
   1942     PixmapPtr rotate_pixmap;
   1943 
   1944     if (!data)
   1945 	data = i830_crtc_shadow_allocate (crtc, width, height);
   1946 
   1947     rotate_pitch = i830_pad_drawable_width(width, pI830->cpp) * pI830->cpp;
   1948 
   1949     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
   1950 					   width, height,
   1951 					   pScrn->depth,
   1952 					   pScrn->bitsPerPixel,
   1953 					   rotate_pitch,
   1954 					   data);
   1955 
   1956     if (rotate_pixmap == NULL) {
   1957 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1958 		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
   1959     }
   1960     if (intel_crtc->rotate_mem && intel_crtc->rotate_mem->bo)
   1961 	i830_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_mem->bo);
   1962     return rotate_pixmap;
   1963 }
   1964 
   1965 static void
   1966 i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
   1967 {
   1968     ScrnInfoPtr pScrn = crtc->scrn;
   1969     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
   1970 
   1971     if (rotate_pixmap) {
   1972 	i830_set_pixmap_bo(rotate_pixmap, NULL);
   1973 	FreeScratchPixmapHeader(rotate_pixmap);
   1974     }
   1975 
   1976     if (data) {
   1977 	/* Be sure to sync acceleration before the memory gets unbound. */
   1978 	I830Sync(pScrn);
   1979 	i830_free_memory(pScrn, intel_crtc->rotate_mem);
   1980 	intel_crtc->rotate_mem = NULL;
   1981     }
   1982 }
   1983 
   1984 #if RANDR_13_INTERFACE
   1985 static void
   1986 i830_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
   1987 {
   1988     if (crtc->enabled)
   1989 	i830PipeSetBase(crtc, x, y);
   1990 }
   1991 #endif
   1992 
   1993 /* The screen bo has changed, reset each active crtc to point at
   1994  * the same location that it currently points at, but in the new bo
   1995  */
   1996 void
   1997 i830_set_new_crtc_bo(ScrnInfoPtr pScrn)
   1998 {
   1999     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   2000     int			i;
   2001 
   2002     for (i = 0; i < xf86_config->num_crtc; i++) {
   2003 	xf86CrtcPtr crtc = xf86_config->crtc[i];
   2004 
   2005 	if (crtc->enabled && !crtc->transform_in_use)
   2006 	    i830PipeSetBase(crtc, crtc->x, crtc->y);
   2007     }
   2008 }
   2009 
   2010 void
   2011 i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
   2012 {
   2013     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   2014     I830Ptr pI830 = I830PTR(pScrn);
   2015     int i;
   2016 
   2017     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
   2018 
   2019     for (i = 0; i < xf86_config->num_crtc; i++) {
   2020 	xf86CrtcPtr crtc = xf86_config->crtc[i];
   2021 	I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
   2022 	uint32_t dspcntr = intel_crtc->plane == 0 ? INREG(DSPACNTR) :
   2023 	    INREG(DSPBCNTR);
   2024 	uint32_t pipeconf = i == 0 ? INREG(PIPEACONF) :
   2025 	    INREG(PIPEBCONF);
   2026 	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
   2027 	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
   2028 
   2029 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   2030 		   "  Pipe %c is %s\n",
   2031 		   'A' + i, crtc->enabled ? "on" : "off");
   2032 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   2033 		   "  Display plane %c is now %s and connected to pipe %c.\n",
   2034 		   'A' + intel_crtc->plane,
   2035 		   hw_plane_enable ? "enabled" : "disabled",
   2036 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
   2037 	if (hw_pipe_enable != crtc->enabled) {
   2038 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   2039 		       "  Hardware claims pipe %c is %s while software "
   2040 		       "believes it is %s\n",
   2041 		       'A' + i, hw_pipe_enable ? "on" : "off",
   2042 		       crtc->enabled ? "on" : "off");
   2043 	}
   2044 	if (hw_plane_enable != crtc->enabled) {
   2045 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   2046 		       "  Hardware claims plane %c is %s while software "
   2047 		       "believes it is %s\n",
   2048 		       'A' + i, hw_plane_enable ? "on" : "off",
   2049 		       crtc->enabled ? "on" : "off");
   2050 	}
   2051     }
   2052 
   2053     for (i = 0; i < xf86_config->num_output; i++) {
   2054 	xf86OutputPtr	output = xf86_config->output[i];
   2055 	xf86CrtcPtr	crtc = output->crtc;
   2056 	I830CrtcPrivatePtr	intel_crtc = crtc ? crtc->driver_private : NULL;
   2057 
   2058 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   2059 		   "  Output %s is connected to pipe %s\n",
   2060 		   output->name, intel_crtc == NULL ? "none" :
   2061 		   (intel_crtc->pipe == 0 ? "A" : "B"));
   2062     }
   2063 }
   2064 
   2065 /**
   2066  * Get a pipe with a simple mode set on it for doing load-based monitor
   2067  * detection.
   2068  *
   2069  * It will be up to the load-detect code to adjust the pipe as appropriate for
   2070  * its requirements.  The pipe will be connected to no other outputs.
   2071  *
   2072  * Currently this code will only succeed if there is a pipe with no outputs
   2073  * configured for it.  In the future, it could choose to temporarily disable
   2074  * some outputs to free up a pipe for its use.
   2075  *
   2076  * \return crtc, or NULL if no pipes are available.
   2077  */
   2078 
   2079 /* VESA 640x480x72Hz mode to set on the pipe */
   2080 static DisplayModeRec   load_detect_mode = {
   2081     NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
   2082     31500,
   2083     640, 664, 704, 832, 0,
   2084     480, 489, 491, 520, 0,
   2085     V_NHSYNC | V_NVSYNC,
   2086     0, 0,
   2087 
   2088     640, 640, 664, 704, 832, 832, 0,
   2089     480, 489, 489, 491, 520, 520,
   2090     FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
   2091 };
   2092 
   2093 xf86CrtcPtr
   2094 i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode)
   2095 {
   2096     ScrnInfoPtr		    pScrn = output->scrn;
   2097     xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   2098     I830OutputPrivatePtr    intel_output = output->driver_private;
   2099     I830CrtcPrivatePtr	    intel_crtc;
   2100     xf86CrtcPtr		    supported_crtc =NULL;
   2101     xf86CrtcPtr		    crtc = NULL;
   2102     int			    i;
   2103 
   2104     if (output->crtc)
   2105     {
   2106 	crtc = output->crtc;
   2107 	/*
   2108 	 * Make sure the crtc and output are running
   2109 	 */
   2110 	intel_crtc = crtc->driver_private;
   2111 	*dpms_mode = intel_crtc->dpms_mode;
   2112 	if (intel_crtc->dpms_mode != DPMSModeOn)
   2113 	{
   2114 	    crtc->funcs->dpms (crtc, DPMSModeOn);
   2115 	    output->funcs->dpms (output, DPMSModeOn);
   2116 	}
   2117 	return crtc;
   2118     }
   2119 
   2120     for (i = 0; i < xf86_config->num_crtc; i++)
   2121     {
   2122 	xf86CrtcPtr possible_crtc;
   2123 	if (!(output->possible_crtcs & (1 << i)))
   2124 	    continue;
   2125 	possible_crtc = xf86_config->crtc[i];
   2126 	if (!possible_crtc->enabled)
   2127 	{
   2128 	    crtc = possible_crtc;
   2129 	    break;
   2130 	}
   2131 	if (!supported_crtc)
   2132 	    supported_crtc = possible_crtc;
   2133     }
   2134     if (!crtc)
   2135     {
   2136 	crtc = supported_crtc;
   2137 	if (!crtc)
   2138 	    return NULL;
   2139     }
   2140 
   2141     output->crtc = crtc;
   2142     intel_output->load_detect_temp = TRUE;
   2143 
   2144     intel_crtc = crtc->driver_private;
   2145     *dpms_mode = intel_crtc->dpms_mode;
   2146 
   2147     if (!crtc->enabled)
   2148     {
   2149 	if (!mode)
   2150 	    mode = &load_detect_mode;
   2151 	xf86CrtcSetMode (crtc, mode, RR_Rotate_0, 0, 0);
   2152     }
   2153     else
   2154     {
   2155 	if (intel_crtc->dpms_mode != DPMSModeOn)
   2156 	    crtc->funcs->dpms (crtc, DPMSModeOn);
   2157 
   2158 	/* Add this output to the crtc */
   2159 	output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
   2160 	output->funcs->commit (output);
   2161     }
   2162     /* let the output get through one full cycle before testing */
   2163     i830WaitForVblank (pScrn);
   2164 
   2165     return crtc;
   2166 }
   2167 
   2168 void
   2169 i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode)
   2170 {
   2171     ScrnInfoPtr		    pScrn = output->scrn;
   2172     I830OutputPrivatePtr    intel_output = output->driver_private;
   2173     xf86CrtcPtr		    crtc = output->crtc;
   2174 
   2175     if (intel_output->load_detect_temp)
   2176     {
   2177 	output->crtc = NULL;
   2178 	intel_output->load_detect_temp = FALSE;
   2179 	crtc->enabled = xf86CrtcInUse (crtc);
   2180 	xf86DisableUnusedFunctions(pScrn);
   2181     }
   2182     /*
   2183      * Switch crtc and output back off if necessary
   2184      */
   2185     if (crtc->enabled && dpms_mode != DPMSModeOn)
   2186     {
   2187 	if (output->crtc == crtc)
   2188 	    output->funcs->dpms (output, dpms_mode);
   2189 	crtc->funcs->dpms (crtc, dpms_mode);
   2190     }
   2191 }
   2192 
   2193 /* Returns the clock of the currently programmed mode of the given pipe. */
   2194 static int
   2195 i830_crtc_clock_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
   2196 {
   2197     I830Ptr pI830 = I830PTR(pScrn);
   2198     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
   2199     int pipe = intel_crtc->pipe;
   2200     uint32_t dpll = INREG((pipe == 0) ? DPLL_A : DPLL_B);
   2201     uint32_t fp;
   2202     intel_clock_t clock;
   2203 
   2204     if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
   2205 	fp = INREG((pipe == 0) ? FPA0 : FPB0);
   2206     else
   2207 	fp = INREG((pipe == 0) ? FPA1 : FPB1);
   2208 
   2209     clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
   2210     if (IS_IGD(pI830)) {
   2211 	clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
   2212 	clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
   2213     } else {
   2214 	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
   2215 	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
   2216     }
   2217     if (IS_I9XX(pI830)) {
   2218 	if (IS_IGD(pI830))
   2219 	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
   2220 			   DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
   2221 	else
   2222 	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
   2223 			   DPLL_FPA01_P1_POST_DIV_SHIFT);
   2224 
   2225 	switch (dpll & DPLL_MODE_MASK) {
   2226 	case DPLLB_MODE_DAC_SERIAL:
   2227 	    clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
   2228 	    break;
   2229 	case DPLLB_MODE_LVDS:
   2230 	    clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
   2231 	    break;
   2232 	default:
   2233 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   2234 		       "Unknown DPLL mode %08x in programmed mode\n",
   2235 		       (int)(dpll & DPLL_MODE_MASK));
   2236 	    return 0;
   2237 	}
   2238 
   2239 	if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
   2240 	    intel_clock(pI830, 100000, &clock);
   2241 	else
   2242 	    intel_clock(pI830, 96000, &clock);
   2243     } else {
   2244 	Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
   2245 
   2246 	if (is_lvds) {
   2247 	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
   2248 			   DPLL_FPA01_P1_POST_DIV_SHIFT);
   2249 
   2250 	    /* if LVDS is dual-channel, p2 = 7 */
   2251 	    if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
   2252 		clock.p2 = 7;
   2253 	    else
   2254 		clock.p2 = 14;
   2255 
   2256 	    if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
   2257 		intel_clock(pI830, 66000, &clock); /* XXX: might not be 66MHz */
   2258 	    else
   2259 		intel_clock(pI830, 48000, &clock);
   2260 	} else {
   2261 	    if (dpll & PLL_P1_DIVIDE_BY_TWO) {
   2262 		clock.p1 = 2;
   2263 	    } else {
   2264 		clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
   2265 		    DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
   2266 	    }
   2267 	    if (dpll & PLL_P2_DIVIDE_BY_4)
   2268 		clock.p2 = 4;
   2269 	    else
   2270 		clock.p2 = 2;
   2271 
   2272 	    intel_clock(pI830, 48000, &clock);
   2273 	}
   2274     }
   2275 
   2276     /* XXX: It would be nice to validate the clocks, but we can't reuse
   2277      * i830PllIsValid() because it relies on the xf86_config output
   2278      * configuration being accurate, which it isn't necessarily.
   2279      */
   2280     if (0)
   2281 	i830PrintPll(pScrn, "probed", &clock);
   2282 
   2283     return clock.dot;
   2284 }
   2285 
   2286 /** Returns the currently programmed mode of the given pipe. */
   2287 DisplayModePtr
   2288 i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
   2289 {
   2290     I830Ptr pI830 = I830PTR(pScrn);
   2291     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
   2292     int pipe = intel_crtc->pipe;
   2293     DisplayModePtr mode;
   2294     int htot = INREG((pipe == 0) ? HTOTAL_A : HTOTAL_B);
   2295     int hsync = INREG((pipe == 0) ? HSYNC_A : HSYNC_B);
   2296     int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
   2297     int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
   2298 
   2299     mode = xcalloc(1, sizeof(DisplayModeRec));
   2300     if (mode == NULL)
   2301 	return NULL;
   2302 
   2303     mode->Clock = i830_crtc_clock_get(pScrn, crtc);
   2304     mode->HDisplay = (htot & 0xffff) + 1;
   2305     mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
   2306     mode->HSyncStart = (hsync & 0xffff) + 1;
   2307     mode->HSyncEnd = ((hsync & 0xffff0000) >> 16) + 1;
   2308     mode->VDisplay = (vtot & 0xffff) + 1;
   2309     mode->VTotal = ((vtot & 0xffff0000) >> 16) + 1;
   2310     mode->VSyncStart = (vsync & 0xffff) + 1;
   2311     mode->VSyncEnd = ((vsync & 0xffff0000) >> 16) + 1;
   2312     xf86SetModeDefaultName(mode);
   2313     xf86SetModeCrtc(mode, 0);
   2314 
   2315     return mode;
   2316 }
   2317 
   2318 static const xf86CrtcFuncsRec i830_crtc_funcs = {
   2319     .dpms = i830_crtc_dpms,
   2320     .save = NULL, /* XXX */
   2321     .restore = NULL, /* XXX */
   2322     .lock = i830_crtc_lock,
   2323     .unlock = i830_crtc_unlock,
   2324     .mode_fixup = i830_crtc_mode_fixup,
   2325     .prepare = i830_crtc_prepare,
   2326     .mode_set = i830_crtc_mode_set,
   2327     .commit = i830_crtc_commit,
   2328     .gamma_set = i830_crtc_gamma_set,
   2329     .shadow_create = i830_crtc_shadow_create,
   2330     .shadow_allocate = i830_crtc_shadow_allocate,
   2331     .shadow_destroy = i830_crtc_shadow_destroy,
   2332     .set_cursor_colors = i830_crtc_set_cursor_colors,
   2333     .set_cursor_position = i830_crtc_set_cursor_position,
   2334     .show_cursor = i830_crtc_show_cursor,
   2335     .hide_cursor = i830_crtc_hide_cursor,
   2336     .load_cursor_argb = i830_crtc_load_cursor_argb,
   2337     .destroy = NULL, /* XXX */
   2338 #if RANDR_13_INTERFACE
   2339     .set_origin = i830_crtc_set_origin,
   2340 #endif
   2341 };
   2342 
   2343 void
   2344 i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
   2345 {
   2346     xf86CrtcPtr crtc;
   2347     I830CrtcPrivatePtr intel_crtc;
   2348     int i;
   2349 
   2350     crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
   2351     if (crtc == NULL)
   2352 	return;
   2353 
   2354     intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
   2355     intel_crtc->pipe = pipe;
   2356     intel_crtc->dpms_mode = DPMSModeOff;
   2357     intel_crtc->plane = pipe;
   2358 
   2359     /* Initialize the LUTs for when we turn on the CRTC. */
   2360     for (i = 0; i < 256; i++) {
   2361 	intel_crtc->lut_r[i] = i;
   2362 	intel_crtc->lut_g[i] = i;
   2363 	intel_crtc->lut_b[i] = i;
   2364     }
   2365     crtc->driver_private = intel_crtc;
   2366 }
   2367 
   2368