]> git.pld-linux.org Git - packages/X11.git/blob - X11-6.8.2-add-i945-support.patch
- another try
[packages/X11.git] / X11-6.8.2-add-i945-support.patch
1 --- xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile.i945  2005-08-18 19:40:12.000000000 -0400
2 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile       2005-08-18 19:40:24.000000000 -0400
3 @@ -37,14 +37,14 @@
4  
5  #if !I830Only
6  I810SRCS = i810_cursor.c i810_accel.c i810_memory.c i810_wmark.c i810_dga.c \
7 -          i810_video.c i810_io.c
8 +          i810_video.c i810_io.c i830_modes.c
9  I810OBJS = i810_cursor.o i810_accel.o i810_memory.o i810_wmark.o i810_dga.o \
10 -          i810_video.o i810_io.o
11 +          i810_video.o i810_io.o i830_modes.o
12  #endif
13  I830SRCS = i830_driver.c i830_memory.c i830_cursor.c i830_accel.c i830_io.c \
14 -          i830_dga.c $(I830SRCS1) $(I830SRCS2)
15 +          i830_dga.c i830_shadow.c $(I830SRCS1) $(I830SRCS2)
16  I830OBJS = i830_driver.o i830_memory.o i830_cursor.o i830_accel.o i830_io.o \
17 -          i830_dga.o $(I830OBJS1) $(I830OBJS2)
18 +          i830_dga.o i830_shadow.o $(I830OBJS1) $(I830OBJS2)
19  
20  SRCS =         i810_driver.c \
21         $(I810SRCS) $(I830SRCS) $(DRISRCS)
22 @@ -121,6 +121,7 @@
23  InstallDriverSDKNonExecFile(i830_dri.h,$(DRIVERSDKDIR)/drivers/i810)
24  InstallDriverSDKNonExecFile(i830_driver.c,$(DRIVERSDKDIR)/drivers/i810)
25  InstallDriverSDKNonExecFile(i830_memory.c,$(DRIVERSDKDIR)/drivers/i810)
26 +InstallDriverSDKNonExecFile(i830_shadow.c,$(DRIVERSDKDIR)/drivers/i810)
27  InstallDriverSDKNonExecFile(i830_video.c,$(DRIVERSDKDIR)/drivers/i810)
28  
29  InstallDriverSDKObjectModule(i810,$(DRIVERSDKMODULEDIR),drivers)
30 --- xc/programs/Xserver/hw/xfree86/drivers/i810/common.h.i945   2005-08-18 19:40:12.000000000 -0400
31 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/common.h        2005-08-18 19:40:24.000000000 -0400
32 @@ -2,7 +2,7 @@
33  /**************************************************************************
34  
35  Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
36 -Copyright © 2002 David Dawes
37 +Copyright © 2002 David Dawes
38  
39  All Rights Reserved.
40  
41 @@ -79,6 +79,7 @@
42  extern const char *I810ddcSymbols[];
43  extern const char *I810fbSymbols[];
44  extern const char *I810xaaSymbols[];
45 +extern const char *I810shadowFBSymbols[];
46  #ifdef XF86DRI
47  extern const char *I810driSymbols[];
48  extern const char *I810drmSymbols[];
49 @@ -305,6 +306,22 @@
50  #define PCI_CHIP_I915_G_BRIDGE    0x2580
51  #endif
52  
53 +#ifndef PCI_CHIP_I915_GM
54 +#define PCI_CHIP_I915_GM          0x2592
55 +#define PCI_CHIP_I915_GM_BRIDGE           0x2590
56 +#endif
57 +
58 +#ifndef PCI_CHIP_E7221_G
59 +#define PCI_CHIP_E7221_G          0x258A
60 +/* Same as I915_G_BRIDGE */
61 +#define PCI_CHIP_E7221_G_BRIDGE           0x2580
62 +#endif
63 +
64 +#ifndef PCI_CHIP_I945_G
65 +#define PCI_CHIP_I945_G        0x2772
66 +#define PCI_CHIP_I945_G_BRIDGE 0x2770
67 +#endif
68 +
69  #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||   \
70                         pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
71                         pI810->PciInfo->chipType == PCI_CHIP_I810_E)
72 @@ -312,10 +329,14 @@
73  #define IS_I830(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I830_M)
74  #define IS_845G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_845_G)
75  #define IS_I85X(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM)
76 +#define IS_I852(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
77 +#define IS_I855(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
78  #define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G)
79 -#define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G)
80 +#define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G)
81 +#define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
82 +#define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
83  
84 -#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810))
85 +#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810))
86  
87  #define GTT_PAGE_SIZE                  KB(4)
88  #define ROUND_TO(x, y)                 (((x) + (y) - 1) / (y) * (y))
89 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man.i945   2005-08-18 19:40:12.000000000 -0400
90 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man        2005-08-18 19:40:24.000000000 -0400
91 @@ -25,7 +25,7 @@
92  .SH SUPPORTED HARDWARE
93  .B i810
94  supports the i810, i810-DC100, i810e, i815, 830M, 845G, 852GM, 855GM,
95 -865G and 915G chipsets.
96 +865G, 915G and 915GM chipsets.
97  
98  .SH CONFIGURATION DETAILS
99  Please refer to __xconfigfile__(__filemansuffix__) for general configuration
100 @@ -191,6 +191,17 @@
101  the machine has booted, but unfortunately it doesn't always work and
102  is extremely dependent upon the Video BIOS.
103  Default: disabled
104 +.TP
105 +.BI "Option \*qRotate\*q \*qCW\*q"
106 +.TP
107 +.BI "Option \*qRotate\*q \*qCCW\*q"
108 +Rotate the desktop 90 degrees clockwise or counterclockwise.  This option 
109 +forces the ShadowFB option on, and disables acceleration.
110 +Default: no rotation.
111 +.TP
112 +.BI "Option \*qShadowFB\*q \*q" boolean \*q
113 +Enable or disable use of the shadow framebuffer layer.  This option
114 +disables acceleration.  Default: off.
115  
116  .SH "SEE ALSO"
117  __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
118 @@ -199,5 +210,5 @@
119  Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu.  830M and 845G
120  support reworked for XFree86 4.3 by David Dawes and Keith Whitwell.
121  852GM, 855GM, and 865G support added by David Dawes and Keith Whitwell.
122 -915G support added by Alan Hourihane and Keith Whitwell.
123 +915G and 915GM support added by Alan Hourihane and Keith Whitwell.
124  Dual Head, Clone and lid status support added by Alan Hourihane.
125 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c.i945       2005-08-18 19:40:12.000000000 -0400
126 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c    2005-08-18 19:40:24.000000000 -0400
127 @@ -259,7 +259,7 @@
128  #ifdef XF86DRI
129     /* VT switching tries to do this.  
130      */
131 -   if ((!pI810->LockHeld && pI810->directRenderingEnabled) || !pScrn->vtSema) {
132 +   if (!pI810->LockHeld && pI810->directRenderingEnabled) {
133        return;
134     }
135  #endif
136 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c.i945 2005-08-18 19:40:12.000000000 -0400
137 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c      2005-08-18 19:40:24.000000000 -0400
138 @@ -1498,10 +1498,10 @@
139             return FALSE;
140          }
141        if (pI810->cursorARGBHandle != 0)
142 -        if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
143 -           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
144 -           return FALSE;
145 -        }
146 +         if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
147 +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
148 +             return FALSE;
149 +         }
150        if (pI810->agpAcquired == TRUE)
151          drmAgpRelease(pI810->drmSubFD);
152        pI810->agpAcquired = FALSE;
153 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.h.i945 2005-08-18 19:40:12.000000000 -0400
154 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.h      2005-08-18 19:40:24.000000000 -0400
155 @@ -3,7 +3,6 @@
156  #ifndef _I810_DRI_
157  #define _I810_DRI_
158  
159 -#include "xf86dri.h"
160  #include "xf86drm.h"
161  #include "i810_common.h"
162  
163 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c.i945      2005-08-18 19:40:12.000000000 -0400
164 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c   2005-08-18 19:40:24.000000000 -0400
165 @@ -74,7 +74,7 @@
166  #include "fb.h"
167  #include "miscstruct.h"
168  #include "xf86xv.h"
169 -#include "Xv.h"
170 +#include <X11/extensions/Xv.h>
171  #include "vbe.h"
172  
173  #include "i810.h"
174 @@ -129,6 +129,9 @@
175     {PCI_CHIP_I855_GM,          "852GM/855GM"},
176     {PCI_CHIP_I865_G,           "865G"},
177     {PCI_CHIP_I915_G,           "915G"},
178 +   {PCI_CHIP_E7221_G,          "E7221 (i915)"},
179 +   {PCI_CHIP_I915_GM,          "915GM"},
180 +   {PCI_CHIP_I945_G,           "945G"},
181     {-1,                                NULL}
182  };
183  
184 @@ -144,6 +147,9 @@
185     {PCI_CHIP_I855_GM,          PCI_CHIP_I855_GM,       RES_SHARED_VGA},
186     {PCI_CHIP_I865_G,           PCI_CHIP_I865_G,        RES_SHARED_VGA},
187     {PCI_CHIP_I915_G,           PCI_CHIP_I915_G,        RES_SHARED_VGA},
188 +   {PCI_CHIP_E7221_G,          PCI_CHIP_E7221_G,       RES_SHARED_VGA},
189 +   {PCI_CHIP_I915_GM,          PCI_CHIP_I915_GM,       RES_SHARED_VGA},
190 +   {PCI_CHIP_I945_G,           PCI_CHIP_I945_G,        RES_SHARED_VGA},
191     {-1,                                -1, RES_UNDEFINED }
192  };
193  
194 @@ -262,6 +268,11 @@
195     NULL
196  };
197  
198 +const char *I810shadowFBSymbols[] = {
199 +    "ShadowFBInit",
200 +    NULL
201 +};
202 +
203  #ifdef XF86DRI
204  const char *I810drmSymbols[] = {
205     "drmAddBufs",
206 @@ -303,13 +314,6 @@
207     NULL
208  };
209  
210 -#ifdef XF86DRI
211 -
212 -static const char *driShadowFBSymbols[] = {
213 -    "ShadowFBInit",
214 -    NULL
215 -};
216 -
217  const char *I810shadowSymbols[] = {
218      "shadowInit",
219      "shadowSetup",
220 @@ -317,9 +321,7 @@
221      NULL
222  };
223  
224 -#endif
225 -
226 -#endif /* I830_ONLY */
227 +#endif 
228  
229  #ifndef I810_DEBUG
230  int I810_DEBUG = (0
231 @@ -388,7 +390,7 @@
232                         I810drmSymbols,
233                         I810driSymbols,
234                         I810shadowSymbols,
235 -                       driShadowFBSymbols,
236 +                       I810shadowFBSymbols,
237  #endif
238                         I810vbeSymbols, vbeOptionalSymbols,
239                         I810ddcSymbols, I810int10Symbols, NULL);
240 @@ -560,6 +562,9 @@
241             case PCI_CHIP_I830_M:
242             case PCI_CHIP_I855_GM:
243             case PCI_CHIP_I915_G:
244 +           case PCI_CHIP_E7221_G:
245 +           case PCI_CHIP_I915_GM:
246 +           case PCI_CHIP_I945_G:
247                xf86SetEntitySharable(usedChips[i]);
248  
249                /* Allocate an entity private if necessary */            
250 @@ -1080,7 +1088,7 @@
251                     "Couldn't load shadowfb module:\n");
252         }
253         else {
254 -        xf86LoaderReqSymLists(driShadowFBSymbols, NULL);
255 +        xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
256         }
257       }
258       
259 @@ -1729,6 +1737,21 @@
260     i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
261  
262     /*
263 +    * the KGA fix in vgaHW.c results in the first
264 +    * scanline and the first character clock (8 pixels)
265 +    * of each scanline thereafter on display with an i810
266 +    * to be blank. Restoring CRTC 3, 5, & 22 to their
267 +    * "theoretical" values corrects the problem. KAO.
268 +    */
269 +   pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
270 +   pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
271 +        | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
272 +   pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
273 +
274 +   i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
275 +   vgaHWVBlankKGA(mode, pVga, 8, 0);
276 +
277 +   /*
278      * The following workarounds are needed to get video overlay working
279      * at 1024x768 and 1280x1024 display resolutions.
280      */
281 @@ -1787,7 +1810,6 @@
282  {
283     vgaHWPtr hwp;
284     I810Ptr pI810;
285 -   vgaRegPtr pVga;
286  
287     hwp = VGAHWPTR(pScrn);
288     pI810 = I810PTR(pScrn);
289 @@ -1796,18 +1818,6 @@
290  
291     if (!vgaHWInit(pScrn, mode))
292        return FALSE;
293 -   /*
294 -    * the KGA fix in vgaHW.c results in the first
295 -    * scanline and the first character clock (8 pixels)
296 -    * of each scanline thereafter on display with an i810
297 -    * to be blank. Restoring CRTC 3, 5, & 22 to their
298 -    * "theoretical" values corrects the problem. KAO.
299 -    */
300 -   pVga = &VGAHWPTR(pScrn)->ModeReg;
301 -   pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
302 -   pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
303 -        | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
304 -   pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
305  
306     pScrn->vtSema = TRUE;
307  
308 @@ -2097,8 +2107,8 @@
309  
310  #ifdef XF86DRI
311     /*
312 -    * Setup DRI after visuals have been established, but before cfbScreenInit
313 -    * is called.   cfbScreenInit will eventually call into the drivers
314 +    * Setup DRI after visuals have been established, but before fbScreenInit
315 +    * is called.   fbScreenInit will eventually call into the drivers
316      * InitGLXVisuals call back.
317      */
318     /*
319 @@ -2241,7 +2251,7 @@
320  
321  #ifdef XF86DRI
322     if (pI810->directRenderingEnabled) {
323 -      /* Now that mi, cfb, drm and others have done their thing,
324 +      /* Now that mi, fb, drm and others have done their thing,
325         * complete the DRI setup.
326         */
327        pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
328 @@ -2255,9 +2265,9 @@
329  #endif
330  
331     if (pI810->directRenderingEnabled) {
332 -      xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering enabled\n");
333 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
334     } else {
335 -      xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering disabled\n");
336 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
337     }
338  
339     pScreen->SaveScreen = I810SaveScreen;
340 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i810_hwmc.c.i945        2005-08-18 19:40:12.000000000 -0400
341 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i810_hwmc.c     2005-08-18 19:40:24.000000000 -0400
342 @@ -50,8 +50,8 @@
343  
344  #include "xf86xv.h"
345  #include "xf86xvmc.h"
346 -#include "Xv.h"
347 -#include "XvMC.h"
348 +#include <X11/extensions/Xv.h>
349 +#include <X11/extensions/XvMC.h>
350  #include "xaa.h"
351  #include "xaalocal.h"
352  #include "dixstruct.h"
353 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830.h.i945     2005-08-18 19:40:12.000000000 -0400
354 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830.h  2005-08-18 19:40:24.000000000 -0400
355 @@ -75,7 +75,7 @@
356  
357  /*
358   * The mode handling is based upon the VESA driver written by
359 - * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>.
360 + * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>.
361   */
362  
363  #define PIPE_NONE      0<<0
364 @@ -91,7 +91,7 @@
365  typedef struct _VESARec {
366     /* SVGA state */
367     pointer state, pstate;
368 -   int statePage, stateSize, stateMode;
369 +   int statePage, stateSize, stateMode, stateRefresh;
370     CARD32 *savedPal;
371     int savedScanlinePitch;
372     xf86MonPtr monitor;
373 @@ -165,13 +165,17 @@
374  
375     Bool newPipeSwitch;
376  
377 +   Bool fakeSwitch;
378 +   
379 +   int fixedPipe;
380 +
381     Bool Clone;
382     int CloneRefresh;
383     int CloneHDisplay;
384     int CloneVDisplay;
385  
386     I830EntPtr entityPrivate;   
387 -   int pipe;
388 +   int pipe, origPipe;
389     int init;
390  
391     unsigned int bufferOffset;          /* for I830SelectBuffer */
392 @@ -234,6 +238,7 @@
393  
394     int MonType1;
395     int MonType2;
396 +   Bool specifiedMonitor;
397  
398     DGAModePtr DGAModes;
399     int numDGAModes;
400 @@ -297,7 +302,15 @@
401     drm_handle_t ring_map;
402  #endif
403  
404 +   /* Broken-out options. */
405     OptionInfoPtr Options;
406 +   int rotate;
407 +   Bool shadowFB;
408 +
409 +   /* Support for shadowFB and rotation. */
410 +   unsigned char *shadowPtr;
411 +   int shadowPitch;
412 +   void (*PointerMoved)(int, int, int);
413  
414     /* Stolen memory support */
415     Bool StolenOnly;
416 @@ -320,10 +333,11 @@
417     /* Use BIOS call 0x5f05 to set the refresh rate. */
418     Bool useExtendedRefresh;
419  
420 -   Bool checkLid;
421 +   Bool checkDevices;
422     int monitorSwitch;
423     int operatingDevices;
424     int savedDevices;
425 +   int lastDevice1, lastDevice2;
426  
427     /* These are indexed by the display types */
428     Bool displayAttached[NumDisplayTypes];
429 @@ -343,6 +357,7 @@
430     Bool starting;
431     Bool closing;
432     Bool suspended;
433 +   Bool leaving;
434  
435     /* fbOffset converted to (x, y). */
436     int xoffset;
437 @@ -353,7 +368,7 @@
438     Bool displayInfo;
439     Bool devicePresence;
440  
441 -   OsTimerPtr lidTimer;
442 +   OsTimerPtr devicesTimer;
443  } I830Rec;
444  
445  #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
446 @@ -390,6 +405,7 @@
447  extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
448  extern Bool I830DRIScreenInit(ScreenPtr pScreen);
449  extern Bool I830DRIDoMappings(ScreenPtr pScreen);
450 +extern Bool I830DRIResume(ScreenPtr pScreen);
451  extern void I830DRICloseScreen(ScreenPtr pScreen);
452  extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen);
453  #endif
454 @@ -423,13 +439,27 @@
455  
456  extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
457  
458 +extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
459 +                                       VbeInfoBlock *vbe);
460 +extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
461 +extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
462 +extern void I830PrintModes(ScrnInfoPtr pScrn);
463 +extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
464 +extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
465 +extern void I830PointerMoved(int index, int x, int y);
466 +extern void I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
467 +extern void I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
468 +extern void I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
469 +extern void I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
470 +extern void I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
471 +
472  /*
473   * 12288 is set as the maximum, chosen because it is enough for
474   * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
475   */
476  #define I830_MAXIMUM_VBIOS_MEM         12288
477 -#define I830_DEFAULT_VIDEOMEM_2D       (MB(8) / 1024)
478 -#define I830_DEFAULT_VIDEOMEM_3D       (MB(32) / 1024)
479 +#define I830_DEFAULT_VIDEOMEM_2D       (MB(32) / 1024)
480 +#define I830_DEFAULT_VIDEOMEM_3D       (MB(64) / 1024)
481  
482  /* Flags for memory allocation function */
483  #define FROM_ANYWHERE                  0x00000000
484 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h.i945      2005-08-18 19:40:12.000000000 -0400
485 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h   2005-08-18 19:40:24.000000000 -0400
486 @@ -55,7 +55,8 @@
487  typedef struct {
488     enum {
489        I830_INIT_DMA = 0x01,
490 -      I830_CLEANUP_DMA = 0x02
491 +      I830_CLEANUP_DMA = 0x02,
492 +      I830_RESUME_DMA = 0x03
493     } func;
494     unsigned int mmio_offset;
495     int sarea_priv_offset;
496 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_cursor.c.i945      2005-08-18 19:40:12.000000000 -0400
497 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_cursor.c   2005-08-18 19:40:24.000000000 -0400
498 @@ -2,7 +2,7 @@
499  /**************************************************************************
500  
501  Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
502 -Copyright © 2002 David Dawes
503 +Copyright © 2002 David Dawes
504  All Rights Reserved.
505  
506  Permission is hereby granted, free of charge, to any person obtaining a
507 @@ -82,7 +82,7 @@
508  
509     DPRINTF(PFX, "I830InitHWCursor\n");
510     /* Initialise the HW cursor registers, leaving the cursor hidden. */
511 -   if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
512 +   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
513        temp = INREG(CURSOR_A_CONTROL);
514        temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
515                 MCURSOR_PIPE_SELECT);
516 @@ -304,7 +304,7 @@
517     }
518  
519     /* have to upload the base for the new position */
520 -   if (IS_I915G(pI830)) {
521 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
522        if (pI830->CursorIsARGB)
523           OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
524        else
525 @@ -335,7 +335,7 @@
526            pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
527  
528     pI830->cursorOn = TRUE;
529 -   if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
530 +   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
531        temp = INREG(CURSOR_A_CONTROL);
532        temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
533        if (pI830->CursorIsARGB)
534 @@ -383,7 +383,7 @@
535     DPRINTF(PFX, "I830HideCursor\n");
536  
537     pI830->cursorOn = FALSE;
538 -   if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
539 +   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
540        temp = INREG(CURSOR_A_CONTROL);
541        temp &= ~CURSOR_MODE;
542        temp |= CURSOR_MODE_DISABLE;
543 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c.i945 2005-08-18 19:40:12.000000000 -0400
544 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c      2005-08-18 19:40:24.000000000 -0400
545 @@ -2,7 +2,7 @@
546  /**************************************************************************
547  
548  Copyright 2001 VA Linux Systems Inc., Fremont, California.
549 -Copyright © 2002 by David Dawes
550 +Copyright © 2002 by David Dawes
551  
552  All Rights Reserved.
553  
554 @@ -163,6 +163,24 @@
555  }
556  
557  static Bool
558 +I830ResumeDma(ScrnInfoPtr pScrn)
559 +{
560 +   I830Ptr pI830 = I830PTR(pScrn);
561 +   drmI830Init info;
562 +
563 +   memset(&info, 0, sizeof(drmI830Init));
564 +   info.func = I830_RESUME_DMA;
565 +
566 +   if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
567 +                      &info, sizeof(drmI830Init))) {
568 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Resume Failed\n");
569 +      return FALSE;
570 +   }
571 +
572 +   return TRUE;
573 +}
574 +
575 +static Bool
576  I830SetParam(ScrnInfoPtr pScrn, int param, int value)
577  {
578     I830Ptr pI830 = I830PTR(pScrn);
579 @@ -510,7 +528,7 @@
580        return FALSE;
581     }
582  
583 -   /* Check the i830 DRM versioning */
584 +   /* Check the i915 DRM versioning */
585     {
586        drmVersionPtr version;
587  
588 @@ -568,10 +586,18 @@
589             drmFreeVersion(version);
590             return FALSE;
591          }
592 +        if (strncmp(version->name, I830KernelDriverName, strlen(I830KernelDriverName))) {
593 +           xf86DrvMsg(pScreen->myNum, X_WARNING, 
594 +                       "i830 Kernel module detected, Use the i915 Kernel module instead, aborting DRI init.\n");
595 +           I830DRICloseScreen(pScreen);
596 +           drmFreeVersion(version);
597 +           return FALSE;
598 +        }
599          pI830->drmMinor = version->version_minor;
600          drmFreeVersion(version);
601        }
602     }
603 +
604     return TRUE;
605  }
606  
607 @@ -655,7 +681,10 @@
608     xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] textures = 0x%08lx\n",
609               pI830DRI->textures);
610  
611 -   I830InitDma(pScrn);
612 +   if (!I830InitDma(pScrn)) {
613 +      DRICloseScreen(pScreen);
614 +      return FALSE;
615 +   }
616  
617     if (pI830->PciInfo->chipType != PCI_CHIP_845_G &&
618         pI830->PciInfo->chipType != PCI_CHIP_I830_M) {
619 @@ -742,6 +771,41 @@
620     return TRUE;
621  }
622  
623 +Bool
624 +I830DRIResume(ScreenPtr pScreen)
625 +{
626 +   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
627 +   I830Ptr pI830 = I830PTR(pScrn);
628 +   I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
629 +
630 +   DPRINTF(PFX, "I830DRIResume\n");
631 +
632 +   I830ResumeDma(pScrn);
633 +
634 +   {
635 +      pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
636 +                                              ((pciConfigPtr) pI830->
637 +                                               PciInfo->thisCard)->busnum,
638 +                                              ((pciConfigPtr) pI830->
639 +                                               PciInfo->thisCard)->devnum,
640 +                                              ((pciConfigPtr) pI830->
641 +                                               PciInfo->thisCard)->funcnum);
642 +
643 +      if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
644 +        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
645 +                   "[drm] failure adding irq handler\n");
646 +        pI830DRI->irq = 0;
647 +        return FALSE;
648 +      }
649 +      else
650 +        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
651 +                   "[drm] dma control initialized, using IRQ %d\n",
652 +                   pI830DRI->irq);
653 +   }
654 +
655 +   return FALSE;
656 +}
657 +
658  void
659  I830DRICloseScreen(ScreenPtr pScreen)
660  {
661 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c.i945      2005-08-18 19:40:12.000000000 -0400
662 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c   2005-08-18 19:40:24.000000000 -0400
663 @@ -2,7 +2,7 @@
664  /**************************************************************************
665  
666  Copyright 2001 VA Linux Systems Inc., Fremont, California.
667 -Copyright © 2002 by David Dawes
668 +Copyright © 2002 by David Dawes
669  
670  All Rights Reserved.
671  
672 @@ -49,7 +49,7 @@
673  
674  /*
675   * Mode handling is based on the VESA driver written by:
676 - * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
677 + * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
678   */
679  
680  /*
681 @@ -160,11 +160,12 @@
682  #include "vgaHW.h"
683  #include "mipointer.h"
684  #include "micmap.h"
685 +#include "shadowfb.h"
686  
687  #include "fb.h"
688  #include "miscstruct.h"
689  #include "xf86xv.h"
690 -#include "Xv.h"
691 +#include <X11/extensions/Xv.h>
692  #include "vbe.h"
693  #include "vbeModes.h"
694  
695 @@ -185,6 +186,9 @@
696     {PCI_CHIP_I855_GM,          "852GM/855GM"},
697     {PCI_CHIP_I865_G,           "865G"},
698     {PCI_CHIP_I915_G,           "915G"},
699 +   {PCI_CHIP_E7221_G,          "E7221 (i915)"},
700 +   {PCI_CHIP_I915_GM,          "915GM"},
701 +   {PCI_CHIP_I945_G,           "945G"},
702     {-1,                                NULL}
703  };
704  
705 @@ -194,6 +198,9 @@
706     {PCI_CHIP_I855_GM,          PCI_CHIP_I855_GM,       RES_SHARED_VGA},
707     {PCI_CHIP_I865_G,           PCI_CHIP_I865_G,        RES_SHARED_VGA},
708     {PCI_CHIP_I915_G,           PCI_CHIP_I915_G,        RES_SHARED_VGA},
709 +   {PCI_CHIP_E7221_G,          PCI_CHIP_E7221_G,       RES_SHARED_VGA},
710 +   {PCI_CHIP_I915_GM,          PCI_CHIP_I915_GM,       RES_SHARED_VGA},
711 +   {PCI_CHIP_I945_G,           PCI_CHIP_I945_G,        RES_SHARED_VGA},
712     {-1,                                -1,                     RES_UNDEFINED}
713  };
714  
715 @@ -218,8 +225,10 @@
716     OPTION_MONITOR_LAYOUT,
717     OPTION_CLONE,
718     OPTION_CLONE_REFRESH,
719 -   OPTION_CHECKLID,
720 -   OPTION_FLIP_PRIMARY
721 +   OPTION_CHECKDEVICES,
722 +   OPTION_FIXEDPIPE,
723 +   OPTION_SHADOW_FB,
724 +   OPTION_ROTATE
725  } I830Opts;
726  
727  static OptionInfoRec I830BIOSOptions[] = {
728 @@ -237,8 +246,10 @@
729     {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0},   FALSE},
730     {OPTION_CLONE,      "Clone",        OPTV_BOOLEAN,   {0},    FALSE},
731     {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER,  {0},    FALSE},
732 -   {OPTION_CHECKLID,    "CheckLid",    OPTV_BOOLEAN,   {0},    FALSE},
733 -   {OPTION_FLIP_PRIMARY,"FlipPrimary", OPTV_BOOLEAN,   {0},    FALSE},
734 +   {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,  {0},    FALSE},
735 +   {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR,   {0},    FALSE},
736 +   {OPTION_SHADOW_FB,   "ShadowFB",     OPTV_BOOLEAN,   {0},    FALSE},
737 +   {OPTION_ROTATE,      "Rotate",       OPTV_ANYSTR,    {0},    FALSE},
738     {-1,                        NULL,           OPTV_NONE,      {0},    FALSE}
739  };
740  /* *INDENT-ON* */
741 @@ -251,7 +262,7 @@
742  static Bool I830BIOSEnterVT(int scrnIndex, int flags);
743  static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
744                                VbeCRTCInfoBlock *block);
745 -static CARD32 I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg);
746 +static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
747  static Bool SetPipeAccess(ScrnInfoPtr pScrn);
748  static Bool IsPrimary(ScrnInfoPtr pScrn);
749  
750 @@ -363,11 +374,14 @@
751     ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
752  }
753  
754 -/* Various extended video BIOS functions. */
755 -static const int refreshes[] = {
756 -   43, 56, 60, 70, 72, 75, 85, 100, 120
757 +/* Various extended video BIOS functions. 
758 + * 100 and 120Hz aren't really supported, they work but only get close
759 + * to the requested refresh, and really not close enough.
760 + * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */
761 +const int i830refreshes[] = {
762 +   43, 56, 60, 70, 72, 75, 85 /* 100, 120 */
763  };
764 -static const int nrefreshes = sizeof(refreshes) / sizeof(refreshes[0]);
765 +static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]);
766  
767  static Bool
768  Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
769 @@ -390,7 +404,28 @@
770     }
771  }
772  
773 -#if 0
774 +static int
775 +GetToggleList(ScrnInfoPtr pScrn, int toggle)
776 +{
777 +   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
778 +
779 +   DPRINTF(PFX, "GetToggleList\n");
780 +
781 +   pVbe->pInt10->num = 0x10;
782 +   pVbe->pInt10->ax = 0x5f64;
783 +   pVbe->pInt10->bx = 0x500;
784
785 +   pVbe->pInt10->bx |= toggle;
786 +
787 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
788 +   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
789 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx);
790 +      return pVbe->pInt10->cx & 0xffff;
791 +   }
792 +
793 +   return 0;
794 +}
795 +
796  static int
797  BitToRefresh(int bits)
798  {
799 @@ -398,12 +433,12 @@
800  
801     for (i = 0; i < nrefreshes; i++)
802        if (bits & (1 << i))
803 -        return refreshes[i];
804 +        return i830refreshes[i];
805     return 0;
806  }
807  
808  static int
809 -GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
810 +GetRefreshRate(ScrnInfoPtr pScrn, int mode, int *availRefresh)
811  {
812     vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
813  
814 @@ -413,8 +448,6 @@
815     if (mode & 0x100)
816        return 0;
817  
818 -   SetPipeAccess(pScrn);
819 -
820     pVbe->pInt10->num = 0x10;
821     pVbe->pInt10->ax = 0x5f05;
822     pVbe->pInt10->bx = (mode & 0xff) | 0x100;
823 @@ -427,48 +460,181 @@
824     } else
825        return 0;
826  }
827 -#endif
828  
829 -static int
830 -SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
831 +struct panelid {
832 +       short hsize;
833 +       short vsize;
834 +       short fptype;
835 +       char redbpp;
836 +       char greenbpp;
837 +       char bluebpp;
838 +       char reservedbpp;
839 +       int rsvdoffscrnmemsize;
840 +       int rsvdoffscrnmemptr;
841 +       char reserved[14];
842 +};
843 +
844 +static void
845 +I830InterpretPanelID(int scrnIndex, unsigned char *tmp)
846  {
847 -   int i;
848 -   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
849 +    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
850 +    struct panelid *block = (struct panelid *)tmp;
851  
852 -   DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
853 +#define PANEL_DEFAULT_HZ 60
854  
855 -   /* Only 8-bit mode numbers are supported. */
856 -   if (mode & 0x100)
857 -      return 0;
858 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
859 +        "PanelID returned panel resolution : %dx%d\n", 
860 +                                               block->hsize, block->vsize);
861  
862 -   pVbe->pInt10->num = 0x10;
863 -   pVbe->pInt10->ax = 0x5f05;
864 -   pVbe->pInt10->bx = mode & 0xff;
865 +   /* If we get bogus values from this, don't accept it */
866 +   if (block->hsize == 0 || block->vsize == 0) {
867 +       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
868 +        "Bad Panel resolution - ignoring panelID\n");
869 +       
870 +       return;
871 +   }
872 +
873 +   /* If we have monitor timings then don't overwrite them */
874 +   if (pScrn->monitor->nHsync > 0 &&
875 +       pScrn->monitor->nVrefresh > 0)
876 +       return;
877 +
878 +   /* With panels, we're always assuming a refresh of 60Hz */
879 +
880 +   pScrn->monitor->nHsync = 1;
881 +   pScrn->monitor->nVrefresh = 1;
882 +
883 +   /* Give a little tolerance for the selected panel */
884 +   pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000;
885 +   pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000;
886 +   pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ;
887 +   pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ;
888 +}
889 +
890 +/* This should probably go into the VBE layer */
891 +static unsigned char *
892 +vbeReadPanelID(vbeInfoPtr pVbe)
893 +{
894 +    int RealOff = pVbe->real_mode_base;
895 +    pointer page = pVbe->memory;
896 +    unsigned char *tmp = NULL;
897 +    int screen = pVbe->pInt10->scrnIndex;
898 +
899 +    pVbe->pInt10->ax = 0x4F11;
900 +    pVbe->pInt10->bx = 0x01;
901 +    pVbe->pInt10->cx = 0;
902 +    pVbe->pInt10->dx = 0;
903 +    pVbe->pInt10->es = SEG_ADDR(RealOff);
904 +    pVbe->pInt10->di = SEG_OFF(RealOff);
905 +    pVbe->pInt10->num = 0x10;
906 +
907 +    xf86ExecX86int10(pVbe->pInt10);
908 +
909 +    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
910 +        xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
911 +       goto error;
912 +    }
913 +    switch (pVbe->pInt10->ax & 0xff00) {
914 +    case 0x0:
915 +       xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
916 +       tmp = (unsigned char *)xnfalloc(32); 
917 +       memcpy(tmp,page,32); 
918 +       break;
919 +    case 0x100:
920 +       xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");       
921 +       break;
922 +    default:
923 +       xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
924 +                      pVbe->pInt10->ax & 0xff00);
925 +       break;
926 +    }
927 +
928 + error:
929 +    return tmp;
930 +}
931 +
932 +static void
933 +vbeDoPanelID(vbeInfoPtr pVbe)
934 +{
935 +    unsigned char *PanelID_data;
936 +    
937 +    if (!pVbe) return;
938 +
939 +    PanelID_data = vbeReadPanelID(pVbe);
940 +
941 +    if (!PanelID_data) 
942 +       return;
943 +    
944 +    I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data);
945 +}
946 +
947 +int 
948 +I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh)
949 +{
950 +   int i;
951  
952     for (i = nrefreshes - 1; i >= 0; i--) {
953        /*
954         * Look for the highest value that the requested (refresh + 2) is
955         * greater than or equal to.
956         */
957 -      if (refreshes[i] <= (refresh + 2))
958 +      if (i830refreshes[i] <= (refresh + 2))
959          break;
960     }
961     /* i can be 0 if the requested refresh was higher than the max. */
962     if (i == 0) {
963 -      if (refresh >= refreshes[nrefreshes - 1])
964 +      if (refresh >= i830refreshes[nrefreshes - 1])
965           i = nrefreshes - 1;
966     }
967 +
968 +   return i;
969 +}
970 +
971 +static int
972 +SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
973 +{
974 +   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
975 +   int i = I830GetBestRefresh(pScrn, refresh);
976 +
977 +   DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
978 +
979     DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
980 -          refreshes[i], mode & 0xff);
981 +          i830refreshes[i], mode & 0xff);
982 +
983 +   /* Only 8-bit mode numbers are supported. */
984 +   if (mode & 0x100)
985 +      return 0;
986 +
987 +   pVbe->pInt10->num = 0x10;
988 +   pVbe->pInt10->ax = 0x5f05;
989 +   pVbe->pInt10->bx = mode & 0xff;
990 +
991     pVbe->pInt10->cx = 1 << i;
992     xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
993     if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
994 -      return refreshes[i];
995 +      return i830refreshes[i];
996     else
997        return 0;
998  }
999  
1000  static Bool
1001 +SetPowerStatus(ScrnInfoPtr pScrn, int mode)
1002 +{
1003 +   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
1004 +
1005 +   pVbe->pInt10->num = 0x10;
1006 +   pVbe->pInt10->ax = 0x5f64;
1007 +   pVbe->pInt10->bx = 0x0800 | mode;
1008 +   pVbe->pInt10->cx = 0x0000;
1009 +
1010 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1011 +   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
1012 +      return TRUE;
1013 +  
1014 +   return FALSE;
1015 +}
1016 +
1017 +static Bool
1018  GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
1019                int devicesPipeA, int devicesPipeB, int *maxBandwidth,
1020                int *bandwidthPipeA, int *bandwidthPipeB)
1021 @@ -480,7 +646,7 @@
1022  
1023     /* Only 8-bit mode numbers are supported. */
1024     if ((modePipeA & 0x100) || (modePipeB & 0x100))
1025 -      return 0;
1026 +      return FALSE;
1027  
1028     pVbe->pInt10->num = 0x10;
1029     pVbe->pInt10->ax = 0x5f28;
1030 @@ -575,55 +741,144 @@
1031     pVbe->pInt10->bx = 0x100;
1032  
1033     xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1034 -   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
1035 +   if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
1036        return pVbe->pInt10->cx & 0xffff;
1037 -   else
1038 -      return -1;
1039 +   } else {
1040 +      if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */
1041 +         return PIPE_CRT;
1042 +      else
1043 +         return -1;
1044 +   }
1045  }
1046  
1047 -/* This is needed for SetDisplayDevices to work correctly on I915G
1048 - * and possibly later Video BIOS builds around 3272 (but not sure here).
1049 - * So enable for all chipsets now as it has no bad side effects, apart
1050 - * from slightly longer startup time.
1051 - */
1052 -#define I915G_WORKAROUND
1053 +static int
1054 +GetBIOSPipe(ScrnInfoPtr pScrn)
1055 +{
1056 +   I830Ptr pI830 = I830PTR(pScrn);
1057 +   vbeInfoPtr pVbe = pI830->pVbe;
1058 +   int pipe;
1059 +
1060 +   DPRINTF(PFX, "GetBIOSPipe:\n");
1061 +
1062 +   /* single pipe machines should always return Pipe A */
1063 +   if (pI830->availablePipes == 1) return 0;
1064 +
1065 +   pVbe->pInt10->num = 0x10;
1066 +   pVbe->pInt10->ax = 0x5f1c;
1067 +   pVbe->pInt10->bx = 0x100;
1068 +
1069 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1070 +   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
1071 +      if (pI830->newPipeSwitch) {
1072 +         pipe = ((pVbe->pInt10->bx & 0x0001));
1073 +      } else {
1074 +         pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
1075 +      }
1076 +      return pipe;
1077 +   }
1078 +
1079 +   /* failed, assume pipe A */
1080 +   return 0;
1081 +}
1082  
1083  static Bool
1084 -SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
1085 +SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
1086  {
1087     I830Ptr pI830 = I830PTR(pScrn);
1088     vbeInfoPtr pVbe = pI830->pVbe;
1089 -   CARD32 temp;
1090  
1091 -#ifdef I915G_WORKAROUND
1092 -   int getmode;
1093 -   int mode;
1094 +   DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
1095 +
1096 +   /* single pipe machines should always return TRUE */
1097 +   if (pI830->availablePipes == 1) return TRUE;
1098 +
1099 +   pVbe->pInt10->num = 0x10;
1100 +   pVbe->pInt10->ax = 0x5f1c;
1101 +   if (pI830->newPipeSwitch) {
1102 +      pVbe->pInt10->bx = pipe;
1103 +      pVbe->pInt10->cx = 0;
1104 +   } else {
1105 +      pVbe->pInt10->bx = 0x0;
1106 +      pVbe->pInt10->cx = pipe << 8;
1107 +   }
1108 +
1109 +   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1110 +   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
1111 +      return TRUE;
1112 +   }
1113 +       
1114 +   return FALSE;
1115 +}
1116 +
1117 +static Bool
1118 +SetPipeAccess(ScrnInfoPtr pScrn)
1119 +{
1120 +   I830Ptr pI830 = I830PTR(pScrn);
1121 +
1122 +   /* Don't try messing with the pipe, unless we're dual head */
1123 +   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) {
1124 +      if (!SetBIOSPipe(pScrn, pI830->pipe))
1125 +         return FALSE;
1126 +   }
1127 +   
1128 +   return TRUE;
1129 +}
1130 +
1131 +static Bool
1132 +I830Set640x480(ScrnInfoPtr pScrn)
1133 +{
1134 +   I830Ptr pI830 = I830PTR(pScrn);
1135 +   int m = 0x30; /* 640x480 8bpp */
1136 +
1137     switch (pScrn->depth) {
1138 -   case 8:
1139 -      mode = 0x30;
1140 -      break;
1141     case 15:
1142 -      mode = 0x40;
1143 -      break;
1144 +        m = 0x40;
1145 +        break;
1146     case 16:
1147 -      mode = 0x41;
1148 -      break;
1149 +        m = 0x41;
1150 +        break;
1151     case 24:
1152 -      mode = 0x50;
1153 -      break;
1154 -   default: 
1155 -      mode = 0x30;
1156 -      break;
1157 +        m = 0x50;
1158 +        break;
1159     }
1160 -   mode |= (1 << 15) | (1 << 14);
1161 +   m |= (1 << 15) | (1 << 14);
1162 +   return VBESetVBEMode(pI830->pVbe, m, NULL);
1163 +}
1164 +
1165 +/* This is needed for SetDisplayDevices to work correctly on I915G.
1166 + * Enable for all chipsets now as it has no bad side effects, apart
1167 + * from slightly longer startup time.
1168 + */
1169 +#define I915G_WORKAROUND
1170 +
1171 +static Bool
1172 +SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
1173 +{
1174 +   I830Ptr pI830 = I830PTR(pScrn);
1175 +   vbeInfoPtr pVbe = pI830->pVbe;
1176 +   CARD32 temp;
1177 +   int singlepipe = 0;
1178 +#ifdef I915G_WORKAROUND
1179 +   int getmode1;
1180 +   Bool setmode = FALSE;
1181  #endif
1182  
1183     DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
1184  
1185 +   if (!pI830->specifiedMonitor)
1186 +      return TRUE;
1187 +
1188  #ifdef I915G_WORKAROUND
1189 -   if (pI830->bios_version >= 3272) {
1190 -      VBEGetVBEMode(pVbe, &getmode);
1191 -      I830VESASetVBEMode(pScrn, mode, NULL);
1192 +   if (pI830->preinit)
1193 +      setmode = TRUE;
1194 +   if (pI830->leaving)
1195 +      setmode = FALSE;
1196 +   if (pI830->closing)
1197 +      setmode = FALSE;
1198 +        
1199 +   if (setmode) {
1200 +      VBEGetVBEMode(pVbe, &getmode1);
1201 +      I830Set640x480(pScrn);
1202     }
1203  #endif
1204  
1205 @@ -635,28 +890,146 @@
1206     xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1207     if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
1208  #ifdef I915G_WORKAROUND
1209 -      if (pI830->bios_version >= 3272)
1210 -         I830VESASetVBEMode(pScrn, getmode, NULL);
1211 +      if (setmode) {
1212 +        VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
1213 +      }
1214  #endif
1215 +      pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
1216 +      pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
1217 +
1218        return TRUE;
1219     }
1220  
1221  #ifdef I915G_WORKAROUND
1222 -   if (pI830->bios_version >= 3272)
1223 -      I830VESASetVBEMode(pScrn, getmode, NULL);
1224 +   if (setmode)
1225 +      VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
1226  #endif
1227  
1228 -   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1229 -        "SetDisplayDevices call failed, writing config directly to SWF0.\n");
1230 +   if (devices & 0xff) {
1231 +      pVbe->pInt10->num = 0x10;
1232 +      pVbe->pInt10->ax = 0x5f64;
1233 +      pVbe->pInt10->bx = 0x1;
1234 +      pVbe->pInt10->cx = devices & 0xff;
1235 +
1236 +      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1237 +      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
1238 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1239 +               "Successfully set display devices to 0x%x.\n",devices & 0xff);
1240 +         singlepipe = devices & 0xff00; /* set alternate */
1241 +      } else {
1242 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1243 +               "Failed to set display devices to 0x%x.\n",devices & 0xff);
1244 +         singlepipe = devices;
1245 +      }
1246 +   } else
1247 +      singlepipe = devices; 
1248 +
1249 +   if (singlepipe == devices && devices & 0xff00) {
1250 +      pVbe->pInt10->num = 0x10;
1251 +      pVbe->pInt10->ax = 0x5f64;
1252 +      pVbe->pInt10->bx = 0x1;
1253 +      pVbe->pInt10->cx = devices & 0xff00;
1254 +
1255 +      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1256 +      if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
1257 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1258 +               "Successfully set display devices to 0x%x.\n",devices & 0xff00);
1259 +         singlepipe = devices & 0xff; /* set alternate */
1260 +      } else {
1261 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1262 +               "Failed to set display devices to 0x%x.\n",devices & 0xff00);
1263 +         singlepipe = devices;
1264 +      }
1265 +   } 
1266 +
1267 +   /* LVDS doesn't exist on these */
1268 +   if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))
1269 +      singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8));
1270 +
1271 +   if (pI830->availablePipes == 1) 
1272 +      singlepipe &= 0xFF;
1273 +
1274 +   /* Disable LVDS */
1275 +   if (singlepipe & PIPE_LFP)  {
1276 +      /* LFP on PipeA is unlikely! */
1277 +      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
1278 +      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
1279 +      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
1280 +      /* Fix up LVDS */
1281 +      OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
1282 +      /* Enable LVDS */
1283 +      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
1284 +      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
1285 +      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
1286 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1287 +               "Enabling LVDS directly. Pipe A.\n");
1288 +   } else
1289 +   if (singlepipe & (PIPE_LFP << 8))  {
1290 +      OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
1291 +      OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
1292 +      while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
1293 +      /* Fix up LVDS */
1294 +      OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
1295 +      /* Enable LVDS */
1296 +      OUTREG(0x61200, INREG(0x61200) | 0x80000000);
1297 +      OUTREG(0x61204, INREG(0x61204) | 0x00000001);
1298 +      while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
1299 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1300 +               "Enabling LVDS directly. Pipe B.\n");
1301 +   }
1302 +   else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
1303 +      if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
1304 +         OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
1305 +         OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
1306 +         while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
1307 +         /* Fix up LVDS */
1308 +         OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
1309 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1310 +               "Disabling LVDS directly.\n");
1311 +      }
1312 +   }
1313 +
1314 +   /* Now try to program the registers directly if the BIOS failed. */
1315 +   temp = INREG(ADPA);
1316 +   temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK);
1317 +   temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
1318 +   /* Turn on ADPA */
1319 +   if (singlepipe & PIPE_CRT)  {
1320 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1321 +               "Enabling ADPA directly. Pipe A.\n");
1322 +      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT;
1323 +      OUTREG(ADPA, temp);
1324 +   } else
1325 +   if (singlepipe & (PIPE_CRT << 8)) {
1326 +      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1327 +               "Enabling ADPA directly. Pipe B.\n");
1328 +      temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT;
1329 +      OUTREG(ADPA, temp);
1330 +   } 
1331 +   else {
1332 +      if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) {
1333 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1334 +               "Disabling ADPA directly.\n");
1335 +         temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
1336 +         OUTREG(ADPA, temp);
1337 +      }
1338 +   }
1339 +
1340 +   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n");
1341     temp = INREG(SWF0);
1342     OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
1343  
1344 -   if (GetDisplayDevices(pScrn) != devices)
1345 +   if (GetDisplayDevices(pScrn) != devices) {
1346        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1347                  "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n",
1348                  GetDisplayDevices(pScrn), devices);
1349 +      return FALSE;
1350 +   }
1351  
1352 -   return FALSE;
1353 +   pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
1354 +   pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
1355 +
1356 +   return TRUE;
1357  }
1358  
1359  static Bool
1360 @@ -916,9 +1289,10 @@
1361     /* Check for active devices connected to each display pipe. */
1362     for (n = 0; n < pI830->availablePipes; n++) {
1363        pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
1364 -      if (pipe) {
1365 +      if (pipe)
1366          pI830->pipeEnabled[n] = TRUE;
1367 -      }
1368 +      else
1369 +        pI830->pipeEnabled[n] = FALSE;
1370     }
1371  
1372     GetPipeSizes(pScrn);
1373 @@ -942,7 +1316,7 @@
1374      * The GTT varying according the the FbMapSize and the popup is 4KB */
1375     range = (pI830->FbMapSize / (1024*1024)) + 4;
1376  
1377 -   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830)) {
1378 +   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
1379        switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
1380        case I855_GMCH_GMS_STOLEN_1M:
1381          memsize = MB(1) - KB(range);
1382 @@ -960,11 +1334,11 @@
1383          memsize = MB(32) - KB(range);
1384          break;
1385        case I915G_GMCH_GMS_STOLEN_48M:
1386 -        if (IS_I915G(pI830))
1387 +        if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
1388             memsize = MB(48) - KB(range);
1389          break;
1390        case I915G_GMCH_GMS_STOLEN_64M:
1391 -        if (IS_I915G(pI830))
1392 +        if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
1393             memsize = MB(64) - KB(range);
1394          break;
1395        }
1396 @@ -1331,157 +1705,189 @@
1397     }
1398  }
1399  
1400 -/*
1401 - * Use the native method instead of the vgahw method.  So far this is
1402 - * only used for 8-bit mode.
1403 - *
1404 - * XXX Look into using the 10-bit gamma correction mode for 15/16/24 bit,
1405 - * and see if a DirectColor visual can be offered.
1406 - */
1407  static void
1408  I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1409                 LOCO * colors, VisualPtr pVisual)
1410  {
1411     I830Ptr pI830;
1412 -   int i, index;
1413 +   int i,j, index;
1414     unsigned char r, g, b;
1415     CARD32 val, temp;
1416 +   int palreg;
1417 +   int dspreg, dspbase;
1418  
1419     DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
1420     pI830 = I830PTR(pScrn);
1421  
1422     if (pI830->pipe == 0) {
1423 -      /* It seems that an initial read is needed. */
1424 -      temp = INREG(PALETTE_A);
1425 +      palreg = PALETTE_A;
1426 +      dspreg = DSPACNTR;
1427 +      dspbase = DSPABASE;
1428 +   } else {
1429 +      palreg = PALETTE_B;
1430 +      dspreg = DSPBCNTR;
1431 +      dspbase = DSPBBASE;
1432 +   }
1433 +
1434 +   OUTREG(dspreg, INREG(dspreg) | DISPPLANE_GAMMA_ENABLE);
1435 +   OUTREG(dspbase, INREG(dspbase));
1436 +
1437 +   /* It seems that an initial read is needed. */
1438 +   temp = INREG(palreg);
1439 +
1440 +   switch(pScrn->depth) {
1441 +   case 15:
1442        for (i = 0; i < numColors; i++) {
1443 -        index = indices[i];
1444 -        r = colors[index].red;
1445 -        g = colors[index].green;
1446 -        b = colors[index].blue;
1447 -        val = (r << 16) | (g << 8) | b;
1448 -        OUTREG(PALETTE_A + index * 4, val);
1449 +         index = indices[i];
1450 +         r = colors[index].red;
1451 +         g = colors[index].green;
1452 +         b = colors[index].blue;
1453 +         for (j = 0; j < 8; j++) {
1454 +           val = (r << 16) | (g << 8) | b;
1455 +           OUTREG(palreg + index * 32 + (j * 4), val);
1456 +         }
1457        }
1458 -   }
1459 -   if (pI830->pipe == 1) {
1460 -      /* It seems that an initial read is needed. */
1461 -      temp = INREG(PALETTE_B);
1462 +      break;
1463 +   case 16:
1464        for (i = 0; i < numColors; i++) {
1465 +         index = indices[i / 2];
1466 +         r = colors[index].red;
1467 +         b = colors[index].blue;
1468 +         index = indices[i];
1469 +         g = colors[index].green;
1470 +
1471 +        val = (r << 16) | (g << 8) | b;
1472 +        OUTREG(palreg + index * 16, val);
1473 +        OUTREG(palreg + index * 16 + 4, val);
1474 +        OUTREG(palreg + index * 16 + 8, val);
1475 +        OUTREG(palreg + index * 16 + 12, val);
1476 +
1477 +         i++;
1478 +         index = indices[i];
1479 +         g = colors[index].green;
1480 +
1481 +        val = (r << 16) | (g << 8) | b;
1482 +        OUTREG(palreg + index * 16, val);
1483 +        OUTREG(palreg + index * 16 + 4, val);
1484 +        OUTREG(palreg + index * 16 + 8, val);
1485 +        OUTREG(palreg + index * 16 + 12, val);
1486 +      }
1487 +      break;
1488 +   default:
1489 +      for(i = 0; i < numColors; i++) {
1490          index = indices[i];
1491          r = colors[index].red;
1492          g = colors[index].green;
1493          b = colors[index].blue;
1494          val = (r << 16) | (g << 8) | b;
1495 -        OUTREG(PALETTE_B + index * 4, val);
1496 +        OUTREG(palreg + index * 4, val);
1497        }
1498 +      break;
1499     }
1500  }
1501  
1502 -static void
1503 -PreInitCleanup(ScrnInfoPtr pScrn)
1504 -{
1505 -   I830Ptr pI830 = I830PTR(pScrn);
1506 -
1507 -   if (IsPrimary(pScrn) && pI830->LpRing) {
1508 -      xfree(pI830->LpRing);
1509 -      pI830->LpRing = NULL;
1510 -   }
1511 -   if (IsPrimary(pScrn) && pI830->CursorMem) {
1512 -      xfree(pI830->CursorMem);
1513 -      pI830->CursorMem = NULL;
1514 -   }
1515 -   if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
1516 -      xfree(pI830->CursorMemARGB);
1517 -      pI830->CursorMemARGB = NULL;
1518 -   }
1519 -   if (IsPrimary(pScrn) && pI830->OverlayMem) {
1520 -      xfree(pI830->OverlayMem);
1521 -      pI830->OverlayMem = NULL;
1522 -   }
1523 -   if (IsPrimary(pScrn) && pI830->overlayOn) {
1524 -      xfree(pI830->overlayOn);
1525 -      pI830->overlayOn = NULL;
1526 -   }
1527 -   if (!IsPrimary(pScrn) && pI830->entityPrivate)
1528 -      pI830->entityPrivate->pScrn_2 = NULL;
1529 -   RestoreBIOSMemSize(pScrn);
1530 -   if (pI830->swfSaved) {
1531 -      OUTREG(SWF0, pI830->saveSWF0);
1532 -      OUTREG(SWF4, pI830->saveSWF4);
1533 -   }
1534 -   if (pI830->MMIOBase)
1535 -      I830UnmapMMIO(pScrn);
1536 -   I830BIOSFreeRec(pScrn);
1537 -}
1538 -
1539  static int
1540 -GetBIOSPipe(ScrnInfoPtr pScrn)
1541 +I830UseDDC(ScrnInfoPtr pScrn)
1542  {
1543 -   I830Ptr pI830 = I830PTR(pScrn);
1544 -   vbeInfoPtr pVbe = pI830->pVbe;
1545 -   int pipe;
1546 -
1547 -   DPRINTF(PFX, "GetBIOSPipe:\n");
1548 -
1549 -   /* single pipe machines should always return Pipe A */
1550 -   if (pI830->availablePipes == 1) return 0;
1551 -
1552 -   pVbe->pInt10->num = 0x10;
1553 -   pVbe->pInt10->ax = 0x5f1c;
1554 -   pVbe->pInt10->bx = 0x100;
1555 -
1556 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1557 -   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
1558 -      if (pI830->newPipeSwitch) {
1559 -         pipe = ((pVbe->pInt10->bx & 0x0001));
1560 -      } else {
1561 -         pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
1562 -      }
1563 -      return pipe;
1564 -   }
1565 -
1566 -   return -1;
1567 -}
1568 -
1569 -static Bool
1570 -SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
1571 -{
1572 -   I830Ptr pI830 = I830PTR(pScrn);
1573 -   vbeInfoPtr pVbe = pI830->pVbe;
1574 +   xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
1575 +   struct detailed_monitor_section* detMon;
1576 +   struct monitor_ranges *mon_range = NULL;
1577 +   int i;
1578  
1579 -   DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
1580 +   if (!DDC) return 0;
1581  
1582 -   /* single pipe machines should always return TRUE */
1583 -   if (pI830->availablePipes == 1) return TRUE;
1584 +   /* Now change the hsync/vrefresh values of the current monitor to
1585 +    * match those of DDC */
1586 +   for (i = 0; i < 4; i++) {
1587 +      detMon = &DDC->det_mon[i];
1588 +      if(detMon->type == DS_RANGES)
1589 +         mon_range = &detMon->section.ranges;
1590 +   }
1591 +
1592 +   if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
1593 +                    mon_range->min_v == 0 || mon_range->max_v == 0)
1594 +      return 0;        /* bad ddc */
1595 +
1596 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n");
1597 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n", 
1598 +               mon_range->min_h, mon_range->max_h);
1599 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tVertRefresh %d-%d\n", 
1600 +               mon_range->min_v, mon_range->max_v);
1601 +#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
1602 +   if (pScrn->monitor->nHsync > 0) {
1603 +      for (i = 0; i < pScrn->monitor->nHsync; i++) {
1604 +         if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
1605 +                               pScrn->monitor->hsync[i].lo ||
1606 +            (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
1607 +                               pScrn->monitor->hsync[i].hi) {
1608 +           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1609 +                         "config file hsync range %g-%gkHz not within DDC "
1610 +                         "hsync range %d-%dkHz\n",
1611 +                         pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
1612 +                         mon_range->min_h, mon_range->max_h);
1613 +         }
1614 +         pScrn->monitor->hsync[i].lo = mon_range->min_h;
1615 +        pScrn->monitor->hsync[i].hi = mon_range->max_h;
1616 +      }
1617 +   }
1618  
1619 -   pVbe->pInt10->num = 0x10;
1620 -   pVbe->pInt10->ax = 0x5f1c;
1621 -   if (pI830->newPipeSwitch) {
1622 -      pVbe->pInt10->bx = pipe;
1623 -      pVbe->pInt10->cx = 0;
1624 -   } else {
1625 -      pVbe->pInt10->bx = 0x0;
1626 -      pVbe->pInt10->cx = pipe << 8;
1627 +   if (pScrn->monitor->nVrefresh > 0) {
1628 +      for (i=0; i<pScrn->monitor->nVrefresh; i++) {
1629 +         if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
1630 +                               pScrn->monitor->vrefresh[i].lo ||
1631 +            (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
1632 +                               pScrn->monitor->vrefresh[i].hi) {
1633 +           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1634 +                         "config file vrefresh range %g-%gHz not within DDC "
1635 +                         "vrefresh range %d-%dHz\n",
1636 +                         pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
1637 +                         mon_range->min_v, mon_range->max_v);
1638 +         }
1639 +         pScrn->monitor->vrefresh[i].lo = mon_range->min_v;
1640 +         pScrn->monitor->vrefresh[i].hi = mon_range->max_v;
1641 +      }
1642     }
1643  
1644 -   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
1645 -   if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax))
1646 -      return TRUE;
1647 -       
1648 -   return FALSE;
1649 +   return mon_range->max_clock;
1650  }
1651  
1652 -static Bool
1653 -SetPipeAccess(ScrnInfoPtr pScrn)
1654 +static void
1655 +PreInitCleanup(ScrnInfoPtr pScrn)
1656  {
1657     I830Ptr pI830 = I830PTR(pScrn);
1658  
1659 -   /* Don't try messing with the pipe, unless we're dual head */
1660 -   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
1661 -      if (!SetBIOSPipe(pScrn, pI830->pipe))
1662 -         return FALSE;
1663 +   if (IsPrimary(pScrn))
1664 +      pI830->entityPrivate->pScrn_1 = NULL;
1665 +   if (IsPrimary(pScrn) && pI830->LpRing) {
1666 +      xfree(pI830->LpRing);
1667 +      pI830->LpRing = NULL;
1668     }
1669 -   
1670 -   return TRUE;
1671 +   if (IsPrimary(pScrn) && pI830->CursorMem) {
1672 +      xfree(pI830->CursorMem);
1673 +      pI830->CursorMem = NULL;
1674 +   }
1675 +   if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
1676 +      xfree(pI830->CursorMemARGB);
1677 +      pI830->CursorMemARGB = NULL;
1678 +   }
1679 +   if (IsPrimary(pScrn) && pI830->OverlayMem) {
1680 +      xfree(pI830->OverlayMem);
1681 +      pI830->OverlayMem = NULL;
1682 +   }
1683 +   if (IsPrimary(pScrn) && pI830->overlayOn) {
1684 +      xfree(pI830->overlayOn);
1685 +      pI830->overlayOn = NULL;
1686 +   }
1687 +   if (!IsPrimary(pScrn) && pI830->entityPrivate)
1688 +      pI830->entityPrivate->pScrn_2 = NULL;
1689 +   RestoreBIOSMemSize(pScrn);
1690 +   if (pI830->swfSaved) {
1691 +      OUTREG(SWF0, pI830->saveSWF0);
1692 +      OUTREG(SWF4, pI830->saveSWF4);
1693 +   }
1694 +   if (pI830->MMIOBase)
1695 +      I830UnmapMMIO(pScrn);
1696 +   I830BIOSFreeRec(pScrn);
1697  }
1698  
1699  static Bool
1700 @@ -1508,9 +1914,12 @@
1701     I830EntPtr pI830Ent = NULL;                                 
1702     int mem, memsize;
1703     int flags24;
1704 +   int defmon = 0;
1705     int i, n;
1706 +   int DDCclock = 0;
1707     char *s;
1708 -   pointer pDDCModule, pVBEModule;
1709 +   DisplayModePtr p, pMon;
1710 +   pointer pDDCModule = NULL, pVBEModule = NULL;
1711     Bool enable;
1712     const char *chipname;
1713     unsigned int ver;
1714 @@ -1660,6 +2069,15 @@
1715     case PCI_CHIP_I915_G:
1716        chipname = "915G";
1717        break;
1718 +   case PCI_CHIP_E7221_G:
1719 +      chipname = "E7221 (i915)";
1720 +      break;
1721 +   case PCI_CHIP_I915_GM:
1722 +      chipname = "915GM";
1723 +      break;
1724 +   case PCI_CHIP_I945_G:
1725 +      chipname = "945G";
1726 +      break;
1727     default:
1728        chipname = "unknown chipset";
1729        break;
1730 @@ -1697,7 +2115,7 @@
1731        pI830->LinearAddr = pI830->pEnt->device->MemBase;
1732        from = X_CONFIG;
1733     } else {
1734 -      if (IS_I915G(pI830)) {
1735 +      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
1736          pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000;
1737          from = X_PROBED;
1738        } else if (pI830->PciInfo->memBase[1] != 0) {
1739 @@ -1719,7 +2137,7 @@
1740        pI830->MMIOAddr = pI830->pEnt->device->IOBase;
1741        from = X_CONFIG;
1742     } else {
1743 -      if (IS_I915G(pI830)) {
1744 +      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
1745          pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000;
1746          from = X_PROBED;
1747        } else if (pI830->PciInfo->memBase[1]) {
1748 @@ -1764,11 +2182,14 @@
1749          pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */
1750        }
1751     } else {
1752 -      if (IS_I915G(pI830)) {
1753 +      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
1754          if (pI830->PciInfo->memBase[2] & 0x08000000)
1755             pI830->FbMapSize = 0x8000000;       /* 128MB aperture */
1756          else
1757             pI830->FbMapSize = 0x10000000;      /* 256MB aperture */
1758 +
1759 +        if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
1760 +           pI830->FbMapSize = 0x8000000;       /* 128MB aperture */
1761        } else
1762          /* 128MB aperture for later chips */
1763          pI830->FbMapSize = 0x8000000;
1764 @@ -1791,7 +2212,10 @@
1765        }
1766     }
1767  
1768 -   if (IS_MOBILE(pI830) || IS_I915G(pI830))
1769 +   if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
1770 +      pI830->availablePipes = 1;
1771 +   else
1772 +   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830))
1773        pI830->availablePipes = 2;
1774     else
1775        pI830->availablePipes = 1;
1776 @@ -1866,8 +2290,19 @@
1777     }
1778  #endif
1779  
1780 +   pI830->fixedPipe = -1;
1781 +   if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) &&
1782 +      IsPrimary(pScrn)) {
1783 +
1784 +      if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0"))
1785 +         pI830->fixedPipe = 0;
1786 +      else if (strstr(s, "B") || strstr(s, "b") || strstr(s, "1"))
1787 +         pI830->fixedPipe = 1;
1788 +   }
1789 +
1790     pI830->MonType1 = PIPE_NONE;
1791     pI830->MonType2 = PIPE_NONE;
1792 +   pI830->specifiedMonitor = FALSE;
1793  
1794     if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
1795        IsPrimary(pScrn)) {
1796 @@ -1947,6 +2382,8 @@
1797                     "Monitor 1 and 2 cannot be type NONE\n");
1798              return FALSE;
1799        }
1800 +
1801 +      pI830->specifiedMonitor = TRUE;
1802     }
1803  
1804     if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
1805 @@ -1963,21 +2400,24 @@
1806           return FALSE;
1807        }
1808        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n");
1809 -      pI830->CloneRefresh = 60; /* default to 60Hz */
1810 -      if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
1811 +      pI830->Clone = TRUE;
1812 +   }
1813 +
1814 +   pI830->CloneRefresh = 60; /* default to 60Hz */
1815 +   if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
1816                             &(pI830->CloneRefresh))) {
1817 -         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
1818 +      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
1819                  pI830->CloneRefresh);
1820 -      }
1821 -      if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 120) {
1822 -         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
1823 -         PreInitCleanup(pScrn);
1824 -         return FALSE;
1825 -      }
1826 -      pI830->Clone = TRUE;
1827     }
1828  
1829 -    if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
1830 +   /* See above i830refreshes on why 120Hz is commented out */
1831 +   if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 85 /* 120 */) {
1832 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
1833 +      PreInitCleanup(pScrn);
1834 +      return FALSE;
1835 +   }
1836 +
1837 +   if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
1838        if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
1839          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
1840                         "defined for use in a DualHead or Clone setup.\n");
1841 @@ -1993,26 +2433,57 @@
1842        }
1843      }
1844  
1845 +    xf86GetOptValBool(pI830->Options, OPTION_SHADOW_FB, &pI830->shadowFB);
1846 +    if (pI830->shadowFB) {
1847 +       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n");
1848 +    }
1849 +
1850 +    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
1851 +       if(!xf86NameCmp(s, "CW")) {
1852 +           /* accel is disabled below for shadowFB */
1853 +           pI830->shadowFB = TRUE;
1854 +           pI830->rotate = 1;
1855 +           xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1856 +               "Rotating screen clockwise - acceleration disabled\n");
1857 +       } else if(!xf86NameCmp(s, "CCW")) {
1858 +           pI830->shadowFB = TRUE;
1859 +           pI830->rotate = -1;
1860 +           xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
1861 +               "counter clockwise - acceleration disabled\n");
1862 +       } else {
1863 +           xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
1864 +               "value for Option \"Rotate\"\n", s);
1865 +           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1866 +               "Valid options are \"CW\" or \"CCW\"\n");
1867 +       }
1868 +    }
1869 +
1870 +   if (pI830->shadowFB && !pI830->noAccel) {
1871 +       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1872 +                  "HW acceleration not supported with \"shadowFB\".\n");
1873 +       pI830->noAccel = TRUE;
1874 +   }
1875 +
1876     /*
1877      * Let's setup the mobile systems to check the lid status
1878      */
1879     if (IS_MOBILE(pI830)) {
1880 -      pI830->checkLid = TRUE;
1881 +      pI830->checkDevices = TRUE;
1882  
1883 -      if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKLID, TRUE)) {
1884 -         pI830->checkLid = FALSE;
1885 -         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n");
1886 +      if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) {
1887 +         pI830->checkDevices = FALSE;
1888 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
1889        } else
1890        if (pI830->entityPrivate && !IsPrimary(pScrn) &&
1891 -          !I830PTR(pI830->entityPrivate->pScrn_1)->checkLid) {
1892 +          !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) {
1893           /* If checklid is off, on the primary head, then 
1894            * turn it off on the secondary*/
1895 -         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n");
1896 -         pI830->checkLid = FALSE;
1897 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
1898 +         pI830->checkDevices = FALSE;
1899        } else
1900 -         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status enabled\n");
1901 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays enabled\n");
1902     } else
1903 -      pI830->checkLid = FALSE;
1904 +      pI830->checkDevices = FALSE;
1905  
1906     /*
1907      * The "VideoRam" config file parameter specifies the total amount of
1908 @@ -2215,13 +2686,22 @@
1909  
1910     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version);
1911  
1912 -   /* BIOS build 3062 changed the pipe switching functionality */
1913 -   if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) {
1914 +   /* Great..
1915 +    * Intel changed the BIOS version codes and started at 1200.
1916 +    * We know that bios codes for 830M started around 2400.
1917 +    * So we test those conditions to make this judgement. Ugh.
1918 +    */
1919 +   if (pI830->availablePipes == 2 && pI830->bios_version < 2000)
1920        pI830->newPipeSwitch = TRUE;
1921 -      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
1922 -   } else
1923 +   else if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) 
1924 +      /* BIOS build 3062 changed the pipe switching functionality */
1925 +      pI830->newPipeSwitch = TRUE;
1926 +   else
1927        pI830->newPipeSwitch = FALSE;
1928  
1929 +   if (pI830->newPipeSwitch)
1930 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
1931 +
1932     pI830->devicePresence = FALSE;
1933     from = X_DEFAULT;
1934     if (xf86ReturnOptValBool(pI830->Options, OPTION_DEVICE_PRESENCE, FALSE)) {
1935 @@ -2250,18 +2730,29 @@
1936     pI830->savedDevices = GetDisplayDevices(pScrn);
1937  
1938     if (IsPrimary(pScrn)) {
1939 -      pI830->pipe = GetBIOSPipe(pScrn);
1940 -      
1941 -      if (xf86ReturnOptValBool(pI830->Options, OPTION_FLIP_PRIMARY, FALSE)) {
1942 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Primary flipping enabled\n");
1943 -         pI830->pipe = !pI830->pipe;
1944 -      }
1945 +      pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn);
1946  
1947 +      /* Override */
1948 +      if (pI830->fixedPipe != -1) {
1949 +         if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
1950 +            pI830->pipe = pI830->fixedPipe; 
1951 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1952 +               "Fixed Pipe setting primary to pipe %s.\n", 
1953 +                       pI830->fixedPipe ? "B" : "A");
1954 +         }
1955 +      }
1956 +      
1957        /* If the monitors aren't setup, read from the current config */
1958 -      if (pI830->MonType1 == PIPE_NONE)
1959 +      if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
1960           pI830->MonType1 = pI830->savedDevices & 0xff;
1961 -      if (pI830->MonType2 == PIPE_NONE)
1962           pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8;
1963 +      } else {
1964 +         /* Here, we've switched pipes from our primary */
1965 +         if (pI830->MonType1 == PIPE_NONE && pI830->pipe == 0)
1966 +            pI830->pipe = 1;
1967 +         if (pI830->MonType2 == PIPE_NONE && pI830->pipe == 1)
1968 +            pI830->pipe = 0;
1969 +      }
1970     
1971        pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
1972  
1973 @@ -2273,15 +2764,18 @@
1974              pI830->operatingDevices = pI830->MonType1;
1975           else
1976              pI830->operatingDevices = pI830->MonType2 << 8;
1977 -
1978 -         if (pI830->operatingDevices & 0xFF00)
1979 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1980 -                "Primary Pipe is %s, switching off second monitor (0x%x)\n",
1981 -                       pI830->pipe ? "B" : "A", pI830->operatingDevices);
1982        }
1983 +
1984 +      if (pI830->pipe != pI830->origPipe)
1985 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1986 +            "Primary Pipe has been switched from original pipe (%s to %s)\n",
1987 +             pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A");
1988     } else {
1989        I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
1990        pI830->operatingDevices = pI8301->operatingDevices;
1991 +      pI830->pipe = !pI8301->pipe;
1992 +      pI830->MonType1 = pI8301->MonType1;
1993 +      pI830->MonType2 = pI8301->MonType2;
1994     }
1995  
1996     /* Buggy BIOS 3066 is known to cause this, so turn this off */
1997 @@ -2309,26 +2803,25 @@
1998        return FALSE;
1999     }
2000  
2001 -   if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
2002 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2003 +   if (IsPrimary(pScrn)) {
2004 +      if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
2005 +         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2006                  "Failed to switch to monitor configuration (0x%x)\n",
2007                   pI830->operatingDevices);
2008 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2009 +         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2010                  "Please check the devices specified in your MonitorLayout\n");
2011 -      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2012 +         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2013                  "is configured correctly.\n");
2014 -      PreInitCleanup(pScrn);
2015 -      return FALSE;
2016 +         PreInitCleanup(pScrn);
2017 +         return FALSE;
2018 +      }
2019     }
2020  
2021     PrintDisplayDeviceInfo(pScrn);
2022  
2023     if (xf86IsEntityShared(pScrn->entityList[0])) {
2024        if (!IsPrimary(pScrn)) {
2025 -         I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
2026 -
2027           pI830Ent->pScrn_2 = pScrn;
2028 -         pI830->pipe = !pI8301->pipe;
2029  
2030          /* This could be made to work with a little more fiddling */
2031          pI830->directRenderingDisabled = TRUE;
2032 @@ -2367,14 +2860,13 @@
2033     }
2034  
2035     /* Check if the HW cursor needs physical address. */
2036 -   if (IS_MOBILE(pI830) || IS_I915G(pI830))
2037 +   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830))
2038        pI830->CursorNeedsPhysical = TRUE;
2039     else
2040        pI830->CursorNeedsPhysical = FALSE;
2041  
2042 -   /* Force ring buffer to be in low memory for the 845G and later. */
2043 -   if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830))
2044 -      pI830->NeedRingBufferLow = TRUE;
2045 +   /* Force ring buffer to be in low memory for all chipsets */
2046 +   pI830->NeedRingBufferLow = TRUE;
2047  
2048     /*
2049      * XXX If we knew the pre-initialised GTT format for certain, we could
2050 @@ -2413,14 +2905,17 @@
2051               "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
2052  
2053     SetPipeAccess(pScrn);
2054 -   if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
2055 -      PreInitCleanup(pScrn);
2056 -      return FALSE;
2057 -   }
2058  
2059 -   if ((pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) {
2060 -      xf86PrintEDID(pI830->vesa->monitor);
2061 -   }
2062 +   /* Check we have an LFP connected, before trying to
2063 +    * read PanelID information. */
2064 +   if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
2065 +        (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) )
2066 +       vbeDoPanelID(pI830->pVbe);
2067 +
2068 +   pDDCModule = xf86LoadSubModule(pScrn, "ddc");
2069 +
2070 +   pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
2071 +
2072     if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
2073        xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
2074     xf86UnloadSubModule(pDDCModule);
2075 @@ -2485,7 +2980,7 @@
2076        }
2077     }
2078  
2079 -   if (pI830->useExtendedRefresh) {
2080 +   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
2081        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2082                  "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n");
2083     }
2084 @@ -2501,13 +2996,38 @@
2085     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2086               "Maximum space available for video modes: %d kByte\n", memsize);
2087  
2088 +   /* By now, we should have had some monitor settings, but if not, we
2089 +    * need to setup some defaults. These are used in common/xf86Modes.c
2090 +    * so we'll use them here for GetModePool, and that's all. 
2091 +    * We unset them after the call, so we can report 'defaults' as being
2092 +    * used through the common layer.
2093 +    */
2094 +#define DEFAULT_HSYNC_LO 28
2095 +#define DEFAULT_HSYNC_HI 33
2096 +#define DEFAULT_VREFRESH_LO 43
2097 +#define DEFAULT_VREFRESH_HI 72
2098 +
2099 +   if (pScrn->monitor->nHsync == 0) {
2100 +      pScrn->monitor->hsync[0].lo = DEFAULT_HSYNC_LO;
2101 +      pScrn->monitor->hsync[0].hi = DEFAULT_HSYNC_HI;
2102 +      pScrn->monitor->nHsync = 1;
2103 +      defmon |= 1;
2104 +   }
2105 +
2106 +   if (pScrn->monitor->nVrefresh == 0) {
2107 +      pScrn->monitor->vrefresh[0].lo = DEFAULT_VREFRESH_LO;
2108 +      pScrn->monitor->vrefresh[0].hi = DEFAULT_VREFRESH_HI;
2109 +      pScrn->monitor->nVrefresh = 1;
2110 +      defmon |= 2;
2111 +   }
2112 +
2113 +   DDCclock = I830UseDDC(pScrn);
2114 +
2115     /*
2116      * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
2117 -    * functions.  For that reason it's important to set only
2118 -    * V_MODETYPE_VGA in the flags for VBEGetModePool().
2119 +    * functions. 
2120      */
2121 -   pScrn->modePool = VBEGetModePool(pScrn, pI830->pVbe, pI830->vbeInfo,
2122 -                                   V_MODETYPE_VGA);
2123 +   pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
2124  
2125     if (!pScrn->modePool) {
2126        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2127 @@ -2516,6 +3036,21 @@
2128        return FALSE;
2129     }
2130  
2131 +   /* This may look a little weird, but to notify that we're using the
2132 +    * default hsync/vrefresh we need to unset what we just set .....
2133 +    */
2134 +   if (defmon & 1) {
2135 +      pScrn->monitor->hsync[0].lo = 0;
2136 +      pScrn->monitor->hsync[0].hi = 0;
2137 +      pScrn->monitor->nHsync = 0;
2138 +   }
2139 +
2140 +   if (defmon & 2) {
2141 +      pScrn->monitor->vrefresh[0].lo = 0;
2142 +      pScrn->monitor->vrefresh[0].hi = 0;
2143 +      pScrn->monitor->nVrefresh = 0;
2144 +   }
2145 +
2146     SetPipeAccess(pScrn);
2147     VBESetModeNames(pScrn->modePool);
2148  
2149 @@ -2541,15 +3076,61 @@
2150        return FALSE;
2151     }
2152  
2153 -   xf86PruneDriverModes(pScrn);
2154 +   /* Only use this if we've got DDC available */
2155 +   if (DDCclock > 0) {
2156 +      p = pScrn->modes;
2157 +      if (p == NULL)
2158 +         return FALSE;
2159 +      do {
2160 +         int Clock = 100000000; /* incredible value */
2161  
2162 -   pScrn->currentMode = pScrn->modes;
2163 +         for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
2164 +            if ((pMon->HDisplay != p->HDisplay) ||
2165 +                (pMon->VDisplay != p->VDisplay) ||
2166 +                (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
2167 +               continue;
2168 +
2169 +            /* Find lowest supported Clock for this resolution */
2170 +            if (Clock > pMon->Clock)
2171 +               Clock = pMon->Clock;
2172 +         } 
2173 +
2174 +         if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
2175 +            ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
2176 +                  p->name, pScrn->monitor->id,
2177 +                  Clock/1000.0, DDCclock);
2178 +            p->status = MODE_BAD;
2179 +         } 
2180 +         p = p->next;
2181 +      } while (p != NULL && p != pScrn->modes);
2182 +   }
2183 +
2184 +   xf86PruneDriverModes(pScrn);
2185  
2186     if (pScrn->modes == NULL) {
2187        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
2188        PreInitCleanup(pScrn);
2189        return FALSE;
2190     }
2191 +
2192 +   /* Now we check the VESA BIOS's displayWidth and reset if necessary */
2193 +   p = pScrn->modes;
2194 +   do {
2195 +      VbeModeInfoData *data = (VbeModeInfoData *) p->Private;
2196 +      VbeModeInfoBlock *modeInfo;
2197 +
2198 +      /* Get BytesPerScanline so we can reset displayWidth */
2199 +      if ((modeInfo = VBEGetModeInfo(pI830->pVbe, data->mode))) {
2200 +         if (pScrn->displayWidth < modeInfo->BytesPerScanline / pI830->cpp) {
2201 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Correcting stride (%d -> %d)\n", pScrn->displayWidth, modeInfo->BytesPerScanline);
2202 +           pScrn->displayWidth = modeInfo->BytesPerScanline / pI830->cpp;
2203 +        }
2204 +      } 
2205 +      p = p->next;
2206 +   } while (p != NULL && p != pScrn->modes);
2207 +
2208 +   pScrn->currentMode = pScrn->modes;
2209 +
2210  #ifndef USE_PITCHES
2211  #define USE_PITCHES 1
2212  #endif
2213 @@ -2671,7 +3252,7 @@
2214  #endif
2215  
2216     SetPipeAccess(pScrn);
2217 -   VBEPrintModes(pScrn);
2218 +   I830PrintModes(pScrn);
2219  
2220     if (!pI830->vesa->useDefaultRefresh) {
2221        /*
2222 @@ -2682,7 +3263,7 @@
2223         * if there are no non-CRT devices attached.
2224         */
2225        SetPipeAccess(pScrn);
2226 -      VBESetModeParameters(pScrn, pI830->pVbe);
2227 +      I830SetModeParameters(pScrn, pI830->pVbe);
2228     }
2229  
2230     /* PreInit shouldn't leave any state changes, so restore this. */
2231 @@ -2721,11 +3302,6 @@
2232        xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
2233     }
2234  
2235 -   if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
2236 -      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2237 -                   "Failed to switch to saved display devices, continuing.\n");
2238 -   }
2239 -
2240     I830UnmapMMIO(pScrn);
2241  
2242     /*  We won't be using the VGA access after the probe. */
2243 @@ -2733,8 +3309,19 @@
2244     xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr);
2245     xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
2246  
2247 +   if (pI830->shadowFB) {
2248 +       if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2249 +          I830BIOSFreeRec(pScrn);
2250 +          vbeFree(pI830->pVbe);
2251 +          return FALSE;
2252 +       }
2253 +      xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
2254 +   }
2255 +
2256     VBEFreeVBEInfo(pI830->vbeInfo);
2257 +   pI830->vbeInfo = NULL;
2258     vbeFree(pI830->pVbe);
2259 +   pI830->pVbe = NULL;
2260  
2261     /* Use the VBE mode restore workaround by default. */
2262     pI830->vbeRestoreWorkaround = TRUE;
2263 @@ -2953,12 +3540,16 @@
2264  
2265     DPRINTF(PFX, "SaveHWState\n");
2266  
2267 -   SetPipeAccess(pScrn);
2268 +   if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
2269 +      SetBIOSPipe(pScrn, pI830->origPipe);
2270 +   else
2271 +      SetPipeAccess(pScrn);
2272  
2273     pVesa = pI830->vesa;
2274  
2275     /* Make sure we save at least this information in case of failure. */
2276     VBEGetVBEMode(pVbe, &pVesa->stateMode);
2277 +   pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
2278     modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
2279     pVesa->savedScanlinePitch = 0;
2280     if (modeInfo) {
2281 @@ -3024,6 +3615,11 @@
2282  
2283     DPRINTF(PFX, "RestoreHWState\n");
2284  
2285 +   if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
2286 +      SetBIOSPipe(pScrn, pI830->origPipe);
2287 +   else
2288 +      SetPipeAccess(pScrn);
2289 +
2290     pVesa = pI830->vesa;
2291  
2292     /*
2293 @@ -3031,26 +3627,8 @@
2294      * Temporarily program a 640x480 mode before switching back to
2295      * text mode.
2296      */
2297 -   if (pVesa->useDefaultRefresh) {
2298 -      int mode = 0;
2299 -
2300 -      switch (pScrn->depth) {
2301 -      case 8:
2302 -        mode = 0x30;
2303 -        break;
2304 -      case 15:
2305 -        mode = 0x40;
2306 -        break;
2307 -      case 16:
2308 -        mode = 0x41;
2309 -        break;
2310 -      case 24:
2311 -        mode = 0x50;
2312 -        break;
2313 -      }
2314 -      mode |= (1 << 15) | (1 << 14);
2315 -      I830VESASetVBEMode(pScrn, mode, NULL);
2316 -   }
2317 +   if (pVesa->useDefaultRefresh)
2318 +      I830Set640x480(pScrn);
2319  
2320     if (pVesa->state && pVesa->stateSize) {
2321        CARD16 imr = INREG16(IMR);
2322 @@ -3083,6 +3661,9 @@
2323                  "Setting the original video mode instead of restoring\n\t"
2324                  "the saved state\n");
2325        I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
2326 +      if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) {
2327 +         SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
2328 +      }
2329     }
2330     if (pVesa->savedScanlinePitch)
2331         VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
2332 @@ -3094,13 +3675,10 @@
2333  
2334     vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
2335     vgaHWLock(hwp);
2336 +
2337     return TRUE;
2338  }
2339  
2340 -#ifndef USE_VBE
2341 -#define USE_VBE 1
2342 -#endif
2343 -
2344  static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
2345  {
2346     I830Ptr pI830 = I830PTR(pScrn);
2347 @@ -3136,8 +3714,7 @@
2348  #endif
2349           if (clock)
2350              block->PixelClock = clock;
2351 -         block->RefreshRate = ((double)(block->PixelClock) /
2352 -                               (double)(p->HTotal * p->VTotal)) * 100;
2353 +         block->RefreshRate = RefreshRate;
2354           return;
2355        }
2356     }
2357 @@ -3147,62 +3724,138 @@
2358  I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
2359  {
2360     I830Ptr pI830 = I830PTR(pScrn);
2361 +   Bool ret = FALSE;
2362 +   int Mon;
2363  
2364     DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
2365  
2366 -   if (pI830->Clone && !pI830->preinit) {
2367 +   if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
2368 +       !pI830->preinit && !pI830->closing) {
2369        VbeCRTCInfoBlock newblock;
2370 -      int Mon;
2371 +      int newmode = mode;
2372  
2373 -      if (!pI830->pipe)
2374 -         Mon = pI830->MonType2;
2375 -      else
2376 +      if (pI830->pipe == 1)
2377           Mon = pI830->MonType1;
2378 +      else
2379 +         Mon = pI830->MonType2;
2380  
2381        SetBIOSPipe(pScrn, !pI830->pipe);
2382  
2383 -      /* The reason for this code is if we've not got a CRT on this pipe, then
2384 -       * make sure we're using a 60Hz refresh */
2385 -      if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
2386 -         (mode & (1 << 11)) && block) {
2387 -         /* we'll call 5F05 to set the refresh later.... */
2388 -         if (Mon != PIPE_CRT)
2389 -            VBESetVBEMode(pI830->pVbe, mode, NULL);
2390 -         else
2391 -            VBESetVBEMode(pI830->pVbe, mode, block);
2392 -      } else { 
2393 -         if (Mon != PIPE_CRT)
2394 -            /* Set clone head to 60Hz because we ain't got a CRT on it */
2395 -            I830SetCloneVBERefresh(pScrn, mode, &newblock, 6000);
2396 -         else
2397 -            /* Set clone head to specified clone refresh rate */
2398 -            I830SetCloneVBERefresh(pScrn, mode, &newblock, pI830->CloneRefresh * 100);
2399 -         if (newblock.RefreshRate == 0)
2400 +      /* Now recheck refresh operations we can use */
2401 +      pI830->useExtendedRefresh = FALSE;
2402 +      pI830->vesa->useDefaultRefresh = FALSE;
2403 +
2404 +      if (Mon != PIPE_CRT) {
2405 +        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2406 +                   "A non-CRT device is attached to Clone pipe %c.\n"
2407 +                   "\tNo refresh rate overrides will be attempted (0x%x).\n",
2408 +                   PIPE_NAME(!pI830->pipe), newmode);
2409 +        pI830->vesa->useDefaultRefresh = TRUE;
2410 +      }
2411 +      /*
2412 +       * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
2413 +       * would need to be set to FALSE for those cases.
2414 +       */
2415 +      if (!pI830->vesa->useDefaultRefresh) 
2416 +        pI830->useExtendedRefresh = TRUE;
2417 +
2418 +      newmode |= 1 << 11;
2419 +      if (pI830->vesa->useDefaultRefresh)
2420 +            newmode &= ~(1 << 11);
2421 +
2422 +      if (!SetRefreshRate(pScrn, newmode, 60)) {
2423 +        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2424 +                   "BIOS call 0x5f05 not supported on Clone Head, "
2425 +                   "setting refresh with VBE 3 method.\n");
2426 +        pI830->useExtendedRefresh = FALSE;
2427 +      }
2428 +
2429 +      if (!pI830->vesa->useDefaultRefresh) {
2430 +         I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
2431 +
2432 +         if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
2433 +            if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
2434 +               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2435 +                "Failed to set mode for Clone head.\n");
2436 +         } else {
2437 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2438 +                "Setting refresh on clone head with VBE 3 method.\n");
2439 +            pI830->useExtendedRefresh = FALSE;
2440 +         }
2441 +      } else {
2442 +         if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
2443 +            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2444 +                "Failed to set mode for Clone head.\n");
2445 +      }
2446 +
2447 +      if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
2448 +         if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
2449             xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2450 -              "Failed to setup clone head mode resolution and refresh.\n");
2451 +                   "Failed to set refresh rate to %dHz on Clone head.\n",
2452 +                   pI830->CloneRefresh);
2453           else
2454 -            VBESetVBEMode(pI830->pVbe, mode, &newblock);
2455 +           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2456 +                   "Set refresh rate to %dHz on Clone head.\n",
2457 +                   pI830->CloneRefresh);
2458        }
2459 +      SetPipeAccess(pScrn);
2460     }
2461  
2462 -   SetPipeAccess(pScrn);
2463 +   if (pI830->pipe == 0)
2464 +      Mon = pI830->MonType1;
2465 +   else
2466 +      Mon = pI830->MonType2;
2467  
2468 -#if USE_VBE
2469 -   return VBESetVBEMode(pI830->pVbe, mode, block);
2470 -#else
2471 -   {
2472 -      vbeInfoPtr pVbe = pI830->pVbe;
2473 -      pVbe->pInt10->num = 0x10;
2474 -      pVbe->pInt10->ax = 0x80 | (mode & 0x7f);
2475 -      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
2476 -      pVbe->pInt10->ax = 0x0f00;
2477 -      xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
2478 -      if ((pVbe->pInt10->ax & 0x7f) == (mode & 0x7f))
2479 -        return TRUE;
2480 -      else
2481 -        return FALSE;
2482 +   /* Now recheck refresh operations we can use */
2483 +   pI830->useExtendedRefresh = FALSE;
2484 +   pI830->vesa->useDefaultRefresh = FALSE;
2485 +
2486 +   if (Mon != PIPE_CRT)
2487 +      pI830->vesa->useDefaultRefresh = TRUE;
2488 +
2489 +   mode |= 1 << 11;
2490 +   if (pI830->vesa->useDefaultRefresh)
2491 +      mode &= ~(1 << 11);
2492 +   /*
2493 +    * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
2494 +    * would need to be set to FALSE for those cases.
2495 +    */
2496 +   if (!pI830->vesa->useDefaultRefresh) 
2497 +      pI830->useExtendedRefresh = TRUE;
2498 +
2499 +   if (!SetRefreshRate(pScrn, mode, 60)) {
2500 +      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2501 +                   "BIOS call 0x5f05 not supported, "
2502 +                   "setting refresh with VBE 3 method.\n");
2503 +      pI830->useExtendedRefresh = FALSE;
2504     }
2505 -#endif
2506 +
2507 +   if (!pI830->vesa->useDefaultRefresh && block) {
2508 +      ret = VBESetVBEMode(pI830->pVbe, mode, block);
2509 +      if (!ret)
2510 +         ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
2511 +      else {
2512 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2513 +                "Setting refresh with VBE 3 method.\n");
2514 +        pI830->useExtendedRefresh = FALSE;
2515 +      }
2516 +   } else {
2517 +      ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
2518 +   }
2519 +
2520 +   /* Might as well bail now if we've failed */
2521 +   if (!ret) return FALSE;
2522 +
2523 +   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
2524 +      if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
2525 +        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2526 +                   "Failed to set refresh rate to %dHz.\n",
2527 +                   block->RefreshRate / 100);
2528 +        pI830->useExtendedRefresh = FALSE;
2529 +      }
2530 +   }
2531 +
2532 +   return ret;
2533  }
2534  
2535  static Bool
2536 @@ -3231,21 +3884,6 @@
2537     }
2538  #endif
2539  
2540 -   /*
2541 -    * Do this early to find out if we can support it or not....
2542 -    * Test if the extendedRefresh BIOS function is supported.
2543 -    */
2544 -   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
2545 -       (mode & (1 << 11)) && data && data->data && data->block) {
2546 -      SetPipeAccess(pScrn);
2547 -      if (!SetRefreshRate(pScrn, mode, 60)) {
2548 -        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2549 -                   "BIOS call 0x5f05 not supported, "
2550 -                   "setting refresh with VBE 3 method.\n");
2551 -        pI830->useExtendedRefresh = FALSE;
2552 -      }
2553 -   }
2554 -
2555     if (pI830->Clone) {
2556        pI830->CloneHDisplay = pMode->HDisplay;
2557        pI830->CloneVDisplay = pMode->VDisplay;
2558 @@ -3258,25 +3896,11 @@
2559     ResetState(pScrn, TRUE);
2560  #endif
2561  
2562 -   /* XXX Add macros for the various mode parameter bits. */
2563 -
2564 -   if (pI830->vesa->useDefaultRefresh)
2565 -      mode &= ~(1 << 11);
2566 +   SetPipeAccess(pScrn);
2567  
2568     if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
2569 -      if ((data->block && (mode & (1 << 11))) &&
2570 -         I830VESASetVBEMode(pScrn, (mode & ~(1 << 11)), NULL) == TRUE) {
2571 -        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2572 -                   "Set VBE Mode rejected this modeline.\n\t"
2573 -                   "Trying standard mode instead!\n");
2574 -        DPRINTF(PFX, "OOPS!\n");
2575 -        xfree(data->block);
2576 -        data->block = NULL;
2577 -        data->mode &= ~(1 << 11);
2578 -      } else {
2579 -        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
2580 -        return FALSE;
2581 -      }
2582 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
2583 +      return FALSE;
2584     }
2585  
2586     /*
2587 @@ -3302,49 +3926,6 @@
2588        VBESetGetDACPaletteFormat(pVbe, 8);
2589     }
2590  
2591 -   /*
2592 -    * When it's OK to set better than default refresh rates, set them here.
2593 -    */
2594 -   if (pI830->Clone) {
2595 -      int Mon;
2596 -      if (!pI830->pipe)
2597 -         Mon = pI830->MonType2;
2598 -      else
2599 -         Mon = pI830->MonType1;
2600 -      SetBIOSPipe(pScrn, !pI830->pipe);
2601 -      if (pI830->CloneRefresh && (Mon == PIPE_CRT)) {
2602 -         if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
2603 -             (mode & (1 << 11)) && data && data->data && data->block) {
2604 -            refresh = SetRefreshRate(pScrn, mode, pI830->CloneRefresh);
2605 -            if (!refresh)
2606 -              xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2607 -                   "Failed to set refresh rate to %dHz on Clone head.\n",
2608 -                   pI830->CloneRefresh);
2609 -            else
2610 -              xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2611 -                   "Set refresh rate to %dHz on Clone head.\n",
2612 -                   pI830->CloneRefresh);
2613 -         } else
2614 -           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2615 -                   "Will use VBE3 method to set refresh on Clone head.\n");
2616 -      } else {
2617 -        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2618 -         "Not attempting to override default refresh on non-CRT clone head\n");
2619 -      }
2620 -   }
2621 -
2622 -   if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
2623 -       (mode & (1 << 11)) && data && data->data && data->block) {
2624 -      SetPipeAccess(pScrn);
2625 -      refresh = SetRefreshRate(pScrn, mode, data->block->RefreshRate / 100);
2626 -      if (!refresh) {
2627 -        refresh = 60;
2628 -        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2629 -                   "Failed to set refresh rate to %dHz.\n",
2630 -                   data->block->RefreshRate / 100);
2631 -      }
2632 -   }
2633 -
2634     /* XXX Fix plane A with pipe A, and plane B with pipe B. */
2635     planeA = INREG(DSPACNTR);
2636     planeB = INREG(DSPBCNTR);
2637 @@ -3360,36 +3941,18 @@
2638               pI830->planeEnabled[1] ? "enabled" : "disabled",
2639               planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
2640     
2641 -   if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
2642 +   if (pI830->operatingDevices & 0xff) {
2643        pI830->planeEnabled[0] = 1;
2644 -      pI830->pipeEnabled[0] = 1;
2645 -      pI830->planeEnabled[1] = 1;
2646 -      pI830->pipeEnabled[1] = 1;
2647 +   } else { 
2648 +      pI830->planeEnabled[0] = 0;
2649     }
2650  
2651 -   /*
2652 -    * Sometimes it seems that no display planes are enabled at this point.
2653 -    * For mobile platforms pick the plane(s) connected to enabled pipes.
2654 -    * For others choose plane A.
2655 -    */
2656 -   if (!pI830->planeEnabled[0] && !pI830->planeEnabled[1]) {
2657 -      if (pI830->availablePipes == 2) {
2658 -        if ((pI830->pipeEnabled[0] &&
2659 -             ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
2660 -            (pI830->pipeEnabled[1] &&
2661 -             ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
2662 -           pI830->planeEnabled[0] = TRUE;
2663 -        }
2664 -        if ((pI830->pipeEnabled[0] &&
2665 -             ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
2666 -            (pI830->pipeEnabled[1] &&
2667 -             ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
2668 -           pI830->planeEnabled[1] = TRUE;
2669 -        }
2670 -      } else {
2671 -        pI830->planeEnabled[0] = TRUE;
2672 -      }
2673 +   if (pI830->operatingDevices & 0xff00) {
2674 +      pI830->planeEnabled[1] = 1;
2675 +   } else {
2676 +      pI830->planeEnabled[1] = 0;
2677     }
2678 +   
2679     if (pI830->planeEnabled[0]) {
2680        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
2681        planeA |= DISPLAY_PLANE_ENABLE;
2682 @@ -3433,6 +3996,8 @@
2683        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
2684     }
2685  
2686 +
2687 +
2688     if (xf86IsEntityShared(pScrn->entityList[0])) {
2689        /* Clean this up !! */
2690        if (IsPrimary(pScrn)) {
2691 @@ -3611,6 +4176,7 @@
2692        }
2693     }
2694  
2695 +#if 0
2696     {
2697        int ret;
2698  
2699 @@ -3620,6 +4186,7 @@
2700                     "LFP compensation mode: 0x%x\n", ret);
2701        }
2702     }
2703 +#endif
2704  
2705  #if MODESWITCH_RESET_STATE
2706     ResetState(pScrn, TRUE);
2707 @@ -3876,6 +4443,8 @@
2708     VisualPtr visual;
2709     I830EntPtr pI830Ent = NULL;
2710     I830Ptr pI8301 = NULL;
2711 +   int width, height, displayWidth;
2712 +   unsigned char *fbbase;
2713  #ifdef XF86DRI
2714     Bool driDisabled;
2715  #endif
2716 @@ -3938,26 +4507,22 @@
2717      * If we're changing the BIOS's view of the video memory size, do that
2718      * first, then re-initialise the VBE information.
2719      */
2720 +   if (pI830->pVbe)
2721 +      vbeFree(pI830->pVbe);
2722     pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
2723     if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
2724         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
2725     if (!pI830->pVbe)
2726        return FALSE;
2727 +   if (pI830->vbeInfo)
2728 +      VBEFreeVBEInfo(pI830->vbeInfo);
2729     pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
2730  
2731     miClearVisualTypes();
2732 -   if (!xf86SetDefaultVisual(pScrn, -1))
2733 -      return FALSE;
2734 -   if (pScrn->bitsPerPixel > 8) {
2735 -      if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
2736 -                           pScrn->rgbBits, TrueColor))
2737 -        return FALSE;
2738 -   } else {
2739 -      if (!miSetVisualTypes(pScrn->depth,
2740 +   if (!miSetVisualTypes(pScrn->depth,
2741                             miGetDefaultVisualMask(pScrn->depth),
2742                             pScrn->rgbBits, pScrn->defaultVisual))
2743          return FALSE;
2744 -   }
2745     if (!miSetPixmapDepths())
2746        return FALSE;
2747  
2748 @@ -4036,7 +4601,7 @@
2749      */
2750  
2751     if (pI830->directRenderingEnabled) {
2752 -      if (pI830->noAccel || pI830->SWCursor || pI830->StolenOnly) {
2753 +      if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && IsPrimary(pScrn))) {
2754          xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
2755                     "needs HW cursor, 2D accel and AGPGART.\n");
2756          pI830->directRenderingEnabled = FALSE;
2757 @@ -4114,10 +4679,26 @@
2758        return FALSE;
2759  
2760     DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
2761 -   if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset,
2762 -                    pScrn->virtualX, pScrn->virtualY,
2763 +   if (pI830->rotate) {
2764 +       height = pScrn->virtualX;
2765 +       width = pScrn->virtualY;
2766 +   } else {
2767 +       width = pScrn->virtualX;
2768 +       height = pScrn->virtualY;
2769 +   }
2770 +   if (pI830->shadowFB) {
2771 +       pI830->shadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
2772 +       pI830->shadowPtr = xalloc(pI830->shadowPitch * height);
2773 +       displayWidth = pI830->shadowPitch / (pScrn->bitsPerPixel >> 3);
2774 +       fbbase = pI830->shadowPtr;
2775 +   } else {
2776 +       pI830->shadowPtr = NULL;
2777 +       fbbase = pI830->FbBase;
2778 +       displayWidth = pScrn->displayWidth;
2779 +   }
2780 +   if (!fbScreenInit(pScreen, fbbase + pScrn->fbOffset, width, height,
2781                      pScrn->xDpi, pScrn->yDpi,
2782 -                    pScrn->displayWidth, pScrn->bitsPerPixel))
2783 +                    displayWidth, pScrn->bitsPerPixel))
2784        return FALSE;
2785  
2786     if (pScrn->bitsPerPixel > 8) {
2787 @@ -4139,7 +4720,8 @@
2788  
2789     xf86SetBlackWhitePixels(pScreen);
2790  
2791 -   I830DGAInit(pScreen);
2792 +   if (!pI830->shadowFB)
2793 +       I830DGAInit(pScreen);
2794  
2795     DPRINTF(PFX,
2796            "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
2797 @@ -4177,13 +4759,39 @@
2798     } else
2799        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
2800  
2801 +   if (pI830->shadowFB) {
2802 +       RefreshAreaFuncPtr refreshArea = I830RefreshArea;
2803 +       if (pI830->rotate) {
2804 +          if (!pI830->PointerMoved) {
2805 +              pI830->PointerMoved = pScrn->PointerMoved;
2806 +              pScrn->PointerMoved = I830PointerMoved;
2807 +          }
2808 +          switch (pScrn->bitsPerPixel) {
2809 +          case 8:
2810 +              refreshArea = I830RefreshArea8;
2811 +              break;
2812 +          case 16:
2813 +              refreshArea = I830RefreshArea16;
2814 +              break;
2815 +          case 24:
2816 +              refreshArea = I830RefreshArea24;
2817 +              break;
2818 +          case 32:
2819 +              refreshArea = I830RefreshArea32;
2820 +              break;
2821 +          }
2822 +       }
2823 +       ShadowFBInit(pScreen, refreshArea);
2824 +   }
2825 +
2826     DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
2827     if (!miCreateDefColormap(pScreen))
2828        return FALSE;
2829  
2830     DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
2831     if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, 0,
2832 -                           CMAP_RELOAD_ON_MODE_SWITCH)) {
2833 +                           CMAP_RELOAD_ON_MODE_SWITCH |
2834 +                           CMAP_PALETTED_TRUECOLOR)) {
2835        return FALSE;
2836     }
2837  
2838 @@ -4221,9 +4829,6 @@
2839     pI830->CloseScreen = pScreen->CloseScreen;
2840     pScreen->CloseScreen = I830BIOSCloseScreen;
2841   
2842 -   if (pI830->checkLid)
2843 -      pI830->lidTimer = TimerSet(NULL, 0, 1000, I830LidTimer, pScrn);
2844 -
2845     if (serverGeneration == 1)
2846        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2847  
2848 @@ -4335,18 +4940,32 @@
2849  
2850     DPRINTF(PFX, "Leave VT\n");
2851  
2852 +   pI830->leaving = TRUE;
2853 +
2854 +   if (pI830->devicesTimer)
2855 +      TimerCancel(pI830->devicesTimer);
2856 +   pI830->devicesTimer = NULL;
2857 +
2858 +   if (pI830->Clone) {
2859 +      /* Ensure we don't try and setup modes on a clone head */
2860 +      pI830->CloneHDisplay = 0;
2861 +      pI830->CloneVDisplay = 0;
2862 +   }
2863 +
2864     if (!IsPrimary(pScrn)) {
2865         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
2866         if (!pI8301->GttBound) {
2867                 return;
2868         }
2869 -    }
2870 +   }
2871  
2872  #ifdef XF86DRI
2873     if (pI830->directRenderingOpen) {
2874        DPRINTF(PFX, "calling dri lock\n");
2875        DRILock(screenInfo.screens[scrnIndex], 0);
2876        pI830->LockHeld = 1;
2877 +      
2878 +      drmCtlUninstHandler(pI830->drmSubFD);
2879     }
2880  #endif
2881  
2882 @@ -4355,8 +4974,10 @@
2883        SaveHWOperatingState(pScrn);
2884  #endif
2885  
2886 +   if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
2887 +      pI830->CursorInfoRec->HideCursor(pScrn);
2888 +
2889     ResetState(pScrn, TRUE);
2890 -   RestoreHWState(pScrn);
2891  
2892     if (IsPrimary(pScrn)) {
2893        if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
2894 @@ -4369,13 +4990,195 @@
2895        }
2896     }
2897  
2898 +   RestoreHWState(pScrn);
2899     RestoreBIOSMemSize(pScrn);
2900     if (IsPrimary(pScrn))
2901        I830UnbindGARTMemory(pScrn);
2902     if (pI830->AccelInfoRec)
2903        pI830->AccelInfoRec->NeedToSync = FALSE;
2904 +
2905 +   /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
2906 +   if (IsPrimary(pScrn)) {
2907 +      if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
2908 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2909 +                "Failed to switch back to original display devices (0x%x) (2)\n",
2910 +                pI830->savedDevices);
2911 +      } else {
2912 +         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2913 +                "Successfully set original devices (2)\n");
2914 +      }
2915 +   }
2916 +}
2917 +
2918 +static Bool
2919 +I830DetectMonitorChange(ScrnInfoPtr pScrn)
2920 +{
2921 +   I830Ptr pI830 = I830PTR(pScrn);
2922 +   pointer pDDCModule = NULL;
2923 +   DisplayModePtr p, pMon;
2924 +   int memsize;
2925 +   int DDCclock = 0;
2926 +   int displayWidth = pScrn->displayWidth;
2927 +   int curHDisplay = pScrn->currentMode->HDisplay;
2928 +   int curVDisplay = pScrn->currentMode->VDisplay;
2929 +
2930 +   DPRINTF(PFX, "Detect Monitor Change\n");
2931 +   
2932 +   SetPipeAccess(pScrn);
2933 +
2934 +   /* Re-read EDID */
2935 +   pDDCModule = xf86LoadSubModule(pScrn, "ddc");
2936 +   if (pI830->vesa->monitor)
2937 +      xfree(pI830->vesa->monitor);
2938 +   pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
2939 +   xf86UnloadSubModule(pDDCModule);
2940 +   if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
2941 +      xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
2942 +   else 
2943 +      /* No DDC, so get out of here, and continue to use the current settings */
2944 +      return FALSE; 
2945 +
2946 +   if (!(DDCclock = I830UseDDC(pScrn)))
2947 +      return FALSE;
2948 +
2949 +   /* Revalidate the modes */
2950 +
2951 +   /*
2952 +    * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
2953 +    * functions.  
2954 +    */
2955 +   pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
2956 +
2957 +   if (!pScrn->modePool) {
2958 +      /* This is bad, which would cause the Xserver to exit, maybe
2959 +       * we should default to a 640x480 @ 60Hz mode here ??? */
2960 +      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2961 +                "No Video BIOS modes for chosen depth.\n");
2962 +      return FALSE;
2963 +   }
2964 +
2965 +   SetPipeAccess(pScrn);
2966 +   VBESetModeNames(pScrn->modePool);
2967 +
2968 +   if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
2969 +      memsize = pI830->vbeInfo->TotalMemory * 64;
2970 +   else
2971 +      memsize = pScrn->videoRam;
2972 +
2973 +   VBEValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, NULL,
2974 +                       NULL, 0, MAX_DISPLAY_PITCH, 1,
2975 +                       0, MAX_DISPLAY_HEIGHT,
2976 +                       pScrn->display->virtualX,
2977 +                       pScrn->display->virtualY,
2978 +                       memsize, LOOKUP_BEST_REFRESH);
2979 +
2980 +if (DDCclock > 0) {
2981 +   p = pScrn->modes;
2982 +   if (p == NULL)
2983 +      return FALSE;
2984 +   do {
2985 +      int Clock = 100000000; /* incredible value */
2986 +
2987 +      for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
2988 +         if ((pMon->HDisplay != p->HDisplay) ||
2989 +             (pMon->VDisplay != p->VDisplay) ||
2990 +             (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
2991 +            continue;
2992 +
2993 +         /* Find lowest supported Clock for this resolution */
2994 +         if (Clock > pMon->Clock)
2995 +            Clock = pMon->Clock;
2996 +      } 
2997 +
2998 +      if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
2999 +         ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
3000 +                  p->name, pScrn->monitor->id,
3001 +                  Clock/1000.0, DDCclock);
3002 +         p->status = MODE_BAD;
3003 +      } 
3004 +      p = p->next;
3005 +   } while (p != NULL && p != pScrn->modes);
3006 +}
3007 +
3008 +   pScrn->displayWidth = displayWidth; /* restore old displayWidth */
3009 +
3010 +   xf86PruneDriverModes(pScrn);
3011 +   I830PrintModes(pScrn);
3012 +
3013 +   if (!pI830->vesa->useDefaultRefresh)
3014 +      I830SetModeParameters(pScrn, pI830->pVbe);
3015 +
3016 +   /* Now check if the previously used mode is o.k. for the current monitor.
3017 +    * This allows VT switching to continue happily when not disconnecting
3018 +    * and reconnecting monitors */
3019 +
3020 +   pScrn->currentMode = pScrn->modes;
3021 +   p = pScrn->modes;
3022 +   if (p == NULL)
3023 +      return FALSE;
3024 +   do {
3025 +      if ((p->HDisplay == curHDisplay) &&
3026 +          (p->VDisplay == curVDisplay) &&
3027 +          (!(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))) {
3028 +               pScrn->currentMode = p; /* previous mode is o.k. */
3029 +       }
3030 +      p = p->next;
3031 +   } while (p != NULL && p != pScrn->modes);
3032 +
3033 +   /* Now readjust for panning if necessary */
3034 +   {
3035 +      pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2;
3036 +
3037 +      if (pScrn->frameX0 < 0)
3038 +         pScrn->frameX0 = 0;
3039 +
3040 +      pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
3041 +      if (pScrn->frameX1 >= pScrn->virtualX) {
3042 +         pScrn->frameX0 = pScrn->virtualX - pScrn->currentMode->HDisplay;
3043 +         pScrn->frameX1 = pScrn->virtualX - 1;
3044 +      }
3045 +
3046 +      pScrn->frameY0 = (pScrn->frameY0 + pScrn->frameY1 + 1 - pScrn->currentMode->VDisplay) / 2;
3047 +
3048 +      if (pScrn->frameY0 < 0)
3049 +         pScrn->frameY0 = 0;
3050 +
3051 +      pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
3052 +      if (pScrn->frameY1 >= pScrn->virtualY) {
3053 +        pScrn->frameY0 = pScrn->virtualY - pScrn->currentMode->VDisplay;
3054 +        pScrn->frameY1 = pScrn->virtualY - 1;
3055 +      }
3056 +   }
3057 +
3058 +   return TRUE;
3059  }
3060  
3061 +Bool
3062 +I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode)
3063 +{
3064 +   I830Ptr pI830 = I830PTR(pScrn);
3065 +   Bool ret = TRUE;
3066 +
3067 +   if (pI830->Clone) {
3068 +      if (pI830->pipeDisplaySize[0].x2 != 0) {
3069 +        if (x > pI830->pipeDisplaySize[0].x2 ||
3070 +             y > pI830->pipeDisplaySize[0].y2) {
3071 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
3072 +               return FALSE;
3073 +         }
3074 +      }
3075 +      if (pI830->pipeDisplaySize[1].x2 != 0) {
3076 +        if (x > pI830->pipeDisplaySize[1].x2 ||
3077 +             y > pI830->pipeDisplaySize[1].y2) {
3078 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
3079 +               return FALSE;
3080 +         }
3081 +      }
3082 +   }
3083 +
3084 +   return ret;
3085 +}
3086 +               
3087  /*
3088   * This gets called when gaining control of the VT, and from ScreenInit().
3089   */
3090 @@ -4387,15 +5190,56 @@
3091  
3092     DPRINTF(PFX, "Enter VT\n");
3093  
3094 +   /*
3095 +    * Only save state once per server generation since that's what most
3096 +    * drivers do.  Could change this to save state at each VT enter.
3097 +    */
3098 +   if (pI830->SaveGeneration != serverGeneration) {
3099 +      pI830->SaveGeneration = serverGeneration;
3100 +      SaveHWState(pScrn);
3101 +   }
3102 +
3103 +   pI830->leaving = FALSE;
3104 +
3105     if (IsPrimary(pScrn)) {
3106 +     /* 
3107 +      * This is needed for restoring from ACPI modes (especially S3)
3108 +      * so that we warmboot the Video BIOS. Some platforms have problems,
3109 +      * warm booting when we don't need to, so check that we can call
3110 +      * the Video BIOS with our saved devices, and only when that fails,
3111 +      * we'll warm boot it.
3112 +      */
3113 +     /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
3114 +      CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
3115 +      if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) {
3116 +         xf86Int10InfoPtr pInt;
3117 +
3118 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3119 +                               "Detected resume, re-POSTing.\n");
3120 +
3121 +         pInt = xf86InitInt10(pI830->pEnt->index);
3122 +
3123 +         /* Now perform our warm boot */
3124 +         if (pInt) {
3125 +            pInt->num = 0xe6;
3126 +            xf86ExecX86int10 (pInt);
3127 +            xf86FreeInt10 (pInt);
3128 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Re-POSTing via int10.\n");
3129 +         } else {
3130 +            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
3131 +               "Re-POSTing via int10 failed, trying to continue.\n");
3132 +         }
3133 +      }
3134 +     
3135 +      /* Finally, re-setup the display devices */
3136        if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
3137           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3138                  "Failed to switch to configured display devices\n");
3139 -        return FALSE;
3140 +         return FALSE;
3141        }
3142     }
3143  
3144 -   /* Setup for checking lid status */
3145 +   /* Setup for device monitoring status */
3146     pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF;
3147  
3148     if (IsPrimary(pScrn))
3149 @@ -4406,14 +5250,6 @@
3150     if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
3151         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
3152  
3153 -   /*
3154 -    * Only save state once per server generation since that's what most
3155 -    * drivers do.  Could change this to save state at each VT enter.
3156 -    */
3157 -   if (pI830->SaveGeneration != serverGeneration) {
3158 -      pI830->SaveGeneration = serverGeneration;
3159 -      SaveHWState(pScrn);
3160 -   }
3161     ResetState(pScrn, FALSE);
3162     SetHWOperatingState(pScrn);
3163  
3164 @@ -4423,8 +5259,13 @@
3165           pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
3166  #endif
3167  
3168 +   /* Detect monitor change and switch to suitable mode */
3169 +   if (!pI830->starting)
3170 +      I830DetectMonitorChange(pScrn);
3171 +           
3172     if (!I830VESASetMode(pScrn, pScrn->currentMode))
3173        return FALSE;
3174 +   
3175  #ifdef I830_XV
3176     I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
3177  #endif
3178 @@ -4441,6 +5282,8 @@
3179  #ifdef XF86DRI
3180     if (pI830->directRenderingEnabled) {
3181        if (!pI830->starting) {
3182 +        I830DRIResume(screenInfo.screens[scrnIndex]);
3183 +      
3184          I830EmitInvarientState(pScrn);
3185          I830RefreshRing(pScrn);
3186          I830Sync(pScrn);
3187 @@ -4453,6 +5296,9 @@
3188     }
3189  #endif
3190  
3191 +   if (pI830->checkDevices)
3192 +      pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
3193 +
3194     return TRUE;
3195  }
3196  
3197 @@ -4460,8 +5306,6 @@
3198  I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
3199  {
3200  
3201 -   int _head;
3202 -   int _tail;
3203     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3204     I830Ptr pI830 = I830PTR(pScrn);
3205     int ret = TRUE;
3206 @@ -4469,13 +5313,8 @@
3207     DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
3208  
3209     /* Stops head pointer freezes for 845G */
3210 -   if (!pI830->noAccel && (1 || IS_845G(pI830))) {
3211 -      do {
3212 -        _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
3213 -        _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK;
3214 -        DELAY(1000);
3215 -      } while (_head != _tail);
3216 -   }
3217 +   if (!pI830->noAccel)
3218 +      (*pI830->AccelInfoRec->Sync)(pScrn);
3219  
3220  #ifndef BINDUNBIND
3221  #define BINDUNBIND 0
3222 @@ -4509,30 +5348,27 @@
3223     I830Ptr pI830 = I830PTR(pScrn);
3224     Bool on = xf86IsUnblank(mode);
3225     CARD32 temp, ctrl, base;
3226 -   int i;
3227  
3228     DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
3229  
3230     if (pScrn->vtSema) {
3231 -      for (i = 0; i < pI830->availablePipes; i++) {
3232 -        if (i == 0) {
3233 -           ctrl = DSPACNTR;
3234 -           base = DSPABASE;
3235 -        } else {
3236 -           ctrl = DSPBCNTR;
3237 -           base = DSPBADDR;
3238 -        }
3239 -        if (pI830->planeEnabled[i]) {
3240 -           temp = INREG(ctrl);
3241 -           if (on)
3242 -              temp |= DISPLAY_PLANE_ENABLE;
3243 -           else
3244 -              temp &= ~DISPLAY_PLANE_ENABLE;
3245 -           OUTREG(ctrl, temp);
3246 -           /* Flush changes */
3247 -           temp = INREG(base);
3248 -           OUTREG(base, temp);
3249 -        }
3250 +      if (pI830->pipe == 0) {
3251 +        ctrl = DSPACNTR;
3252 +        base = DSPABASE;
3253 +      } else {
3254 +        ctrl = DSPBCNTR;
3255 +        base = DSPBADDR;
3256 +      }
3257 +      if (pI830->planeEnabled[pI830->pipe]) {
3258 +        temp = INREG(ctrl);
3259 +        if (on)
3260 +           temp |= DISPLAY_PLANE_ENABLE;
3261 +        else
3262 +           temp &= ~DISPLAY_PLANE_ENABLE;
3263 +        OUTREG(ctrl, temp);
3264 +        /* Flush changes */
3265 +        temp = INREG(base);
3266 +        OUTREG(base, temp);
3267        }
3268  
3269        if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
3270 @@ -4625,6 +5461,10 @@
3271        I830BIOSLeaveVT(scrnIndex, 0);
3272     }
3273  
3274 +   if (pI830->devicesTimer)
3275 +      TimerCancel(pI830->devicesTimer);
3276 +   pI830->devicesTimer = NULL;
3277 +
3278     DPRINTF(PFX, "\nUnmapping memory\n");
3279     I830UnmapMem(pScrn);
3280     vgaHWUnmapMem(pScrn);
3281 @@ -4661,9 +5501,6 @@
3282        pI830->overlayOn = NULL;
3283     }
3284  
3285 -   if (pI830->lidTimer)
3286 -      TimerCancel(pI830->lidTimer);
3287 -
3288     pScrn->vtSema = FALSE;
3289     pI830->closing = FALSE;
3290     pScreen->CloseScreen = pI830->CloseScreen;
3291 @@ -4743,58 +5580,232 @@
3292     return TRUE;
3293  }
3294  
3295 +static int CountBits(int a)
3296 +{
3297 +   int i;
3298 +   int b = 0;
3299 +
3300 +   for (i=0;i<8;i++) {
3301 +     if (a & (1<<i))
3302 +        b+=1;
3303 +   }
3304 +
3305 +   return b;
3306 +}
3307 +
3308  static CARD32
3309 -I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg)
3310 +I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
3311  {
3312     ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
3313     I830Ptr pI830 = I830PTR(pScrn);
3314 +   int cloned = 0;
3315  
3316     if (pScrn->vtSema) {
3317        /* Check for monitor lid being closed/opened and act accordingly */
3318 -      int temp = INREG(SWF0) & 0x0000FFFF;
3319 +      CARD32 adjust;
3320 +      CARD32 temp = INREG(SWF0) & 0x0000FFFF;
3321 +      int fixup = 0;
3322  
3323 +      /* this avoids a BIOS call if possible */
3324        if (pI830->monitorSwitch != temp) {
3325 -        int conf = pI830->operatingDevices;
3326 -         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
3327 -                       "Detected possible lid operation, fixing up.\n");
3328 -         if ((temp & 0x0808) == 0x0000) {
3329 -           /* LFP (PIPE A or B) GOING OFF - PROBABLE LID CLOSURE */
3330 -           conf = pI830->operatingDevices & 0xF7F7;
3331 -#if 0
3332 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being closed.\n");
3333 -#endif
3334 -         } else {
3335 -#if 0
3336 -            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being opened.\n");
3337 -#endif
3338 +         I830Ptr pI8301;
3339 +         I830Ptr pI8302 = NULL;
3340 +         unsigned int toggle = GetToggleList(pScrn, 1);
3341 +
3342 +         GetToggleList(pScrn, 2);
3343 +         GetToggleList(pScrn, 3);
3344 +         GetToggleList(pScrn, 4);
3345 +         
3346 +         if (IsPrimary(pScrn))
3347 +            pI8301 = pI830;
3348 +         else 
3349 +            pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
3350 +
3351 +         if (xf86IsEntityShared(pScrn->entityList[0]))
3352 +            pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
3353 +
3354 +         pI8301->lastDevice1 = pI8301->lastDevice2;
3355 +         pI8301->lastDevice2 = pI8301->monitorSwitch;
3356 +
3357 +         if (CountBits(temp & 0xff) > 1) {
3358 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3359 +                       "Detected cloned pipe mode (A).\n");
3360 +            if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
3361 +              temp = pI8301->MonType2 << 8 | pI8301->MonType1;
3362 +         } else
3363 +         if (CountBits((temp & 0xff00) >> 8) > 1) {
3364 +            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3365 +                       "Detected cloned pipe mode (B).\n");
3366 +            if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
3367 +              temp = pI8301->MonType2 << 8 | pI8301->MonType1;
3368 +         } else
3369 +         if (pI8301->lastDevice1 && pI8301->lastDevice2) {
3370 +            if ( ((pI8301->lastDevice1 & 0xFF00) == 0) && 
3371 +                 ((pI8301->lastDevice2 & 0x00FF) == 0) ) {
3372 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3373 +                       "Detected last devices (1).\n");
3374 +              cloned = 1;
3375 +            } else if ( ((pI8301->lastDevice2 & 0xFF00) == 0) && 
3376 +                 ((pI8301->lastDevice1 & 0x00FF) == 0) ) {
3377 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3378 +                       "Detected last devices (2).\n");
3379 +              cloned = 1;
3380 +            } else
3381 +               cloned = 0;
3382 +         }
3383 +
3384 +         if (cloned &&
3385 +             ((CountBits(pI830->lastDevice1 & 0xff) > 1) ||
3386 +             ((CountBits((pI830->lastDevice1 & 0xff00) >> 8) > 1))) ) {
3387 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3388 +                       "Detected duplicate (1).\n");
3389 +               cloned = 0;
3390 +         } else
3391 +         if (cloned &&
3392 +             ((CountBits(pI830->lastDevice2 & 0xff) > 1) ||
3393 +             ((CountBits((pI830->lastDevice2 & 0xff00) >> 8) > 1))) ) {
3394 +               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3395 +                       "Detected duplicate (2).\n");
3396 +               cloned = 0;
3397 +         } 
3398 +
3399 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3400 +                       "Requested display devices 0x%lx.\n", temp);
3401 +
3402 +
3403 +         /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake
3404 +          * it here as it seems some just flip between CRT and LFP. Ugh!
3405 +          *
3406 +          * So this pushes them onto Pipe B and clones the displays, which
3407 +          * is what most BIOS' should be doing.
3408 +          *
3409 +          * Cloned pipe mode should only be done when running single head.
3410 +          */
3411 +         if (xf86IsEntityShared(pScrn->entityList[0]))
3412 +            cloned = 0;
3413 +
3414 +         if (cloned) { 
3415 +            if (pI830->Clone)
3416 +               temp = pI8301->MonType2 << 8 | pI8301->MonType1;
3417 +           else if (pI8301->lastDevice1 & 0xFF)
3418 +              temp = pI8301->lastDevice1 << 8 | pI8301->lastDevice2;
3419 +            else
3420 +              temp = pI8301->lastDevice2 << 8 | pI8301->lastDevice1;
3421 +         } 
3422 +
3423 +         /* Jump to our next mode if we detect we've been here before */
3424 +         if (temp == pI830->lastDevice1 || temp == pI830->lastDevice2) {
3425 +             temp = toggle;
3426 +             xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3427 +                       "Detected duplicate devices. Toggling (0x%lx)\n", temp);
3428           }
3429  
3430 -         /* If we've defined our own monitors, then get them and set them
3431 -          * up when switching in single head mode, no effect in dual heads
3432 -          * NOTE: This assumes that the LCD is always on Pipe B..... */
3433 -         conf |= pI830->MonType1;
3434 -        if (IsPrimary(pScrn)) {
3435 -            if (!SetDisplayDevices(pScrn, conf)) 
3436 -               xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
3437 -                   "to configured display devices during lid operation.\n");
3438 +         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
3439 +               "Detected display change operation (0x%x, 0x%x, 0x%lx).\n", 
3440 +                pI8301->lastDevice1, pI8301->lastDevice2, temp);
3441 +
3442 +         /* So that if we close on the wrong config, we restore correctly */
3443 +         pI830->specifiedMonitor = TRUE;
3444 +
3445 +         /* double check the display devices are what's configured and try
3446 +          * not to do it twice because of dual heads with the code above */
3447 +         if (!SetDisplayDevices(pScrn, temp)) {
3448 +            if ( cloned &&
3449 +                    ((CountBits(temp & 0xff) > 1) ||
3450 +                     (CountBits((temp & 0xff00) >> 8) > 1)) ) {
3451 +              temp = pI8301->lastDevice2 | pI8301->lastDevice1;
3452 +               xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, "
3453 +                    "trying dual pipe clone mode (0x%lx)\n", temp);
3454 +               if (!SetDisplayDevices(pScrn, temp))
3455 +                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
3456 +                   "to configured display devices (0x%lx).\n", temp);
3457 +               else
3458 +                 pI830->Clone = TRUE;
3459 +            }
3460           }
3461 -         pI830->monitorSwitch = conf;
3462 -   
3463 +         pI8301->monitorSwitch = temp;
3464 +        pI8301->operatingDevices = temp;
3465 +         if (xf86IsEntityShared(pScrn->entityList[0])) {
3466 +           pI8302->operatingDevices = temp;
3467 +            pI8302->monitorSwitch = temp;
3468 +         }
3469 +
3470 +         fixup = 1;
3471 +      } else {
3472 +         int offset = pScrn->fbOffset + ((pScrn->frameY0 * pScrn->displayWidth + pScrn->frameX0) * pI830->cpp);
3473 +
3474 +         if (pI830->pipe == 0)
3475 +            adjust = INREG(DSPABASE);
3476 +         else 
3477 +            adjust = INREG(DSPBBASE);
3478 +
3479 +         if (adjust != offset) {
3480 +            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3481 +                                              "Fixing display offsets.\n");
3482 +
3483 +            I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
3484 +         }
3485 +      }
3486 +
3487 +      if (fixup) {
3488 +         ScreenPtr   pCursorScreen;
3489 +         int x = 0, y = 0;
3490 +
3491 +         pCursorScreen = miPointerCurrentScreen();
3492 +         if (pScrn->pScreen == pCursorScreen)
3493 +            miPointerPosition(&x, &y);
3494 +
3495           /* Now, when we're single head, make sure we switch pipes */
3496 -         if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)) {
3497 -            if ((temp & 0xFF00) == 0x0000)
3498 -               pI830->pipe = 0;
3499 -            if ((temp & 0x00FF) == 0x0000)
3500 +         if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) || cloned) {
3501 +            if (temp & 0xFF00)
3502                 pI830->pipe = 1;
3503 -         }
3504 +            else 
3505 +               pI830->pipe = 0;
3506 +              xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3507 +                        "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A");
3508 +         } 
3509 +
3510           I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
3511           I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
3512
3513 -         /* Everything should be o.k. now, so make sure the HW cursor is
3514 -          * on the correct pipe */
3515 -         if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
3516 -            pI830->CursorInfoRec->ShowCursor(pScrn);
3517 -            pI830->cursorOn = TRUE;
3518 +         if (xf86IsEntityShared(pScrn->entityList[0])) {
3519 +           ScrnInfoPtr pScrn2;
3520 +            I830Ptr pI8302;
3521 +
3522 +            if (IsPrimary(pScrn)) {
3523 +              pScrn2 = pI830->entityPrivate->pScrn_2;
3524 +               pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
3525 +            } else {
3526 +              pScrn2 = pI830->entityPrivate->pScrn_1;
3527 +               pI8302 = I830PTR(pI830->entityPrivate->pScrn_1);
3528 +            }
3529 +
3530 +            I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
3531 +            I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
3532 +            if (pScrn2->pScreen == pCursorScreen) {
3533 +               int sigstate = xf86BlockSIGIO ();
3534 +               miPointerWarpCursor(pScrn2->pScreen,x,y);
3535 +
3536 +               /* xf86Info.currentScreen = pScrn->pScreen; */
3537 +               xf86UnblockSIGIO (sigstate);
3538 +               if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) {
3539 +                  pI8302->CursorInfoRec->HideCursor(pScrn);
3540 +                  pI8302->CursorInfoRec->ShowCursor(pScrn);
3541 +                  pI8302->cursorOn = TRUE;
3542 +               }
3543 +            }
3544 +        }
3545 +
3546 +         if (pScrn->pScreen == pCursorScreen) {
3547 +            int sigstate = xf86BlockSIGIO ();
3548 +            miPointerWarpCursor(pScrn->pScreen,x,y);
3549 +
3550 +            /* xf86Info.currentScreen = pScrn->pScreen; */
3551 +            xf86UnblockSIGIO (sigstate);
3552 +            if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
3553 +               pI830->CursorInfoRec->HideCursor(pScrn);
3554 +               pI830->CursorInfoRec->ShowCursor(pScrn);
3555 +               pI830->cursorOn = TRUE;
3556 +            }
3557           }
3558        }
3559     }
3560 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c.i945      2005-08-18 19:40:12.000000000 -0400
3561 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c   2005-08-18 19:40:24.000000000 -0400
3562 @@ -2,7 +2,7 @@
3563  /**************************************************************************
3564  
3565  Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3566 -Copyright © 2002 by David Dawes.
3567 +Copyright © 2002 by David Dawes.
3568  
3569  All Rights Reserved.
3570  
3571 @@ -90,7 +90,7 @@
3572             end = pool->Free.End;
3573  
3574          start = ROUND_DOWN_TO(end - size, alignment);
3575 -        needed = pool->Free.End - start;
3576 +        needed = end - start;
3577        }
3578     }
3579     if (needed > pool->Free.Size) {
3580 @@ -123,10 +123,9 @@
3581        pool->Free.Start += needed;
3582        result->End = pool->Free.Start;
3583     } else {
3584 -      result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment) -
3585 -                       pool->Total.End;
3586 -      result->End = pool->Free.End - pool->Total.End;
3587 +      result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment);
3588        pool->Free.End -= needed;
3589 +      result->End = result->Start + needed;
3590     }
3591     pool->Free.Size = pool->Free.End - pool->Free.Start;
3592     result->Size = result->End - result->Start;
3593 @@ -1236,7 +1235,7 @@
3594  
3595     i830Reg->Fence[nr] = 0;
3596  
3597 -   if (IS_I915G(pI830))
3598 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
3599         fence_mask = ~I915G_FENCE_START_MASK;
3600     else
3601         fence_mask = ~I830_FENCE_START_MASK;
3602 @@ -1244,7 +1243,7 @@
3603     if (start & fence_mask) {
3604        xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
3605                  "SetFence: %d: start (0x%08x) is not %s aligned\n",
3606 -                nr, start, (IS_I915G(pI830)) ? "1MB" : "512k");
3607 +                nr, start, (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) ? "1MB" : "512k");
3608        return;
3609     }
3610  
3611 @@ -1264,7 +1263,7 @@
3612  
3613     val = (start | FENCE_X_MAJOR | FENCE_VALID);
3614  
3615 -   if (IS_I915G(pI830)) {
3616 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
3617         switch (size) {
3618            case MB(1):
3619                 val |= I915G_FENCE_SIZE_1M;
3620 @@ -1325,7 +1324,7 @@
3621         }
3622     }
3623  
3624 -   if (IS_I915G(pI830))
3625 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
3626         fence_pitch = pitch / 512;
3627     else
3628         fence_pitch = pitch / 128;
3629 --- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c.i945       2005-08-18 19:40:12.000000000 -0400
3630 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c    2005-08-18 19:40:24.000000000 -0400
3631 @@ -42,7 +42,7 @@
3632  /*
3633   * i830_video.c: i830/i845 Xv driver. 
3634   *
3635 - * Copyright © 2002 by Alan Hourihane and David Dawes
3636 + * Copyright © 2002 by Alan Hourihane and David Dawes
3637   *
3638   * Authors: 
3639   *     Alan Hourihane <alanh@tungstengraphics.com>
3640 @@ -72,7 +72,7 @@
3641  
3642  #include "i830.h"
3643  #include "xf86xv.h"
3644 -#include "Xv.h"
3645 +#include <X11/extensions/Xv.h>
3646  #include "xaa.h"
3647  #include "xaalocal.h"
3648  #include "dixstruct.h"
3649 @@ -110,7 +110,7 @@
3650  
3651  #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
3652  
3653 -static Atom xvBrightness, xvContrast, xvColorKey;
3654 +static Atom xvBrightness, xvContrast, xvColorKey, xvPipe;
3655  static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
3656  
3657  #define IMAGE_MAX_WIDTH                1440
3658 @@ -251,12 +251,20 @@
3659     {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
3660  };
3661  
3662 -#define NUM_ATTRIBUTES 9
3663 +#define CLONE_ATTRIBUTES 1
3664 +static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
3665 +   {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
3666 +};
3667  
3668 +#define NUM_ATTRIBUTES 3
3669  static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
3670     {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
3671     {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
3672 -   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
3673 +   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
3674 +};
3675 +
3676 +#define GAMMA_ATTRIBUTES 6
3677 +static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = {
3678     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
3679     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
3680     {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
3681 @@ -342,6 +350,7 @@
3682  
3683     int brightness;
3684     int contrast;
3685 +   int pipe;
3686  
3687     RegionRec clip;
3688     CARD32 colorKey;
3689 @@ -503,7 +512,7 @@
3690      * Select which pipe the overlay is enabled on.
3691      */
3692     overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
3693 -   if (pI830->pipe == 0)
3694 +   if (pPriv->pipe == 0)
3695        overlay->OCONFIG |= OVERLAY_PIPE_A;
3696     else 
3697        overlay->OCONFIG |= OVERLAY_PIPE_B;
3698 @@ -580,6 +589,7 @@
3699     I830Ptr pI830 = I830PTR(pScrn);
3700     XF86VideoAdaptorPtr adapt;
3701     I830PortPrivPtr pPriv;
3702 +   XF86AttributePtr att;
3703  
3704     DPRINTF(PFX, "I830SetupImageVideo\n");
3705  
3706 @@ -589,7 +599,7 @@
3707  
3708     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
3709     adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
3710 -   adapt->name = "Intel(R) 830M/845G/852GM/855GM/865G/915G Video Overlay";
3711 +   adapt->name = "Intel(R) Video Overlay";
3712     adapt->nEncodings = 1;
3713     adapt->pEncodings = DummyEncoding;
3714     adapt->nFormats = NUM_FORMATS;
3715 @@ -600,12 +610,25 @@
3716     pPriv = (I830PortPrivPtr) (&adapt->pPortPrivates[1]);
3717  
3718     adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
3719 -   adapt->pAttributes = Attributes;
3720 +   adapt->nAttributes = NUM_ATTRIBUTES;
3721 +   if (pI830->Clone)
3722 +      adapt->nAttributes += CLONE_ATTRIBUTES;
3723 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
3724 +      adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
3725 +   adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
3726 +   /* Now copy the attributes */
3727 +   att = adapt->pAttributes;
3728 +   memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
3729 +   att+=NUM_ATTRIBUTES;
3730 +   if (pI830->Clone) {
3731 +      memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
3732 +      att+=CLONE_ATTRIBUTES;
3733 +   }
3734 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
3735 +      memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
3736 +      att+=GAMMA_ATTRIBUTES;
3737 +   }
3738     adapt->nImages = NUM_IMAGES;
3739 -   if (IS_I915G(pI830))
3740 -      adapt->nAttributes = 9; /* has gamma */
3741 -   else
3742 -      adapt->nAttributes = 3;
3743     adapt->pImages = Images;
3744     adapt->PutVideo = NULL;
3745     adapt->PutStill = NULL;
3746 @@ -622,6 +645,7 @@
3747     pPriv->videoStatus = 0;
3748     pPriv->brightness = 0;
3749     pPriv->contrast = 64;
3750 +   pPriv->pipe = pI830->pipe; /* default to current pipe */
3751     pPriv->linear = NULL;
3752     pPriv->currentBuf = 0;
3753     pPriv->gamma5 = 0xc0c0c0;
3754 @@ -655,7 +679,12 @@
3755     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
3756     xvContrast = MAKE_ATOM("XV_CONTRAST");
3757     xvColorKey = MAKE_ATOM("XV_COLORKEY");
3758 -   if (IS_I915G(pI830)) {
3759 +
3760 +   /* Allow the pipe to be switched from pipe A to B when in clone mode */
3761 +   if (pI830->Clone)
3762 +     xvPipe = MAKE_ATOM("XV_PIPE");
3763 +
3764 +   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
3765       xvGamma0 = MAKE_ATOM("XV_GAMMA0");
3766       xvGamma1 = MAKE_ATOM("XV_GAMMA1");
3767       xvGamma2 = MAKE_ATOM("XV_GAMMA2");
3768 @@ -759,7 +788,21 @@
3769        overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
3770        if (pPriv->overlayOK)
3771           OVERLAY_UPDATE;
3772 -   } else if (attribute == xvGamma0 && (IS_I915G(pI830))) {
3773 +   } else if (pI830->Clone && attribute == xvPipe) {
3774 +      if ((value < 0) || (value > 1))
3775 +         return BadValue;
3776 +      pPriv->pipe = value;
3777 +      /*
3778 +       * Select which pipe the overlay is enabled on.
3779 +       */
3780 +      overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
3781 +      if (pPriv->pipe == 0)
3782 +         overlay->OCONFIG |= OVERLAY_PIPE_A;
3783 +      else 
3784 +         overlay->OCONFIG |= OVERLAY_PIPE_B;
3785 +      if (pPriv->overlayOK)
3786 +         OVERLAY_UPDATE;
3787 +   } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3788        /* Avoid video anomalies, so set gamma registers when overlay is off */
3789        /* We also clamp the values if they are outside the ranges */
3790        if (!*pI830->overlayOn) {
3791 @@ -768,35 +811,35 @@
3792            pPriv->gamma1 = pPriv->gamma0 + 0x7d;
3793        } else
3794           return BadRequest;
3795 -   } else if (attribute == xvGamma1 && (IS_I915G(pI830))) {
3796 +   } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3797        if (!*pI830->overlayOn) {
3798           pPriv->gamma1 = value;
3799           if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
3800             pPriv->gamma0 = pPriv->gamma1 - 0x7d;
3801        } else
3802           return BadRequest;
3803 -   } else if (attribute == xvGamma2 && (IS_I915G(pI830))) {
3804 +   } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3805        if (!*pI830->overlayOn) {
3806           pPriv->gamma2 = value;
3807           if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
3808              pPriv->gamma3 = pPriv->gamma2 + 0x7d;
3809        } else
3810           return BadRequest;
3811 -   } else if (attribute == xvGamma3 && (IS_I915G(pI830))) {
3812 +   } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3813        if (!*pI830->overlayOn) {
3814           pPriv->gamma3 = value;
3815           if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
3816              pPriv->gamma2 = pPriv->gamma3 - 0x7d;
3817        } else
3818           return BadRequest;
3819 -   } else if (attribute == xvGamma4 && (IS_I915G(pI830))) {
3820 +   } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3821        if (!*pI830->overlayOn) {
3822           pPriv->gamma4 = value;
3823           if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
3824              pPriv->gamma5 = pPriv->gamma4 + 0x7d;
3825        } else
3826           return BadRequest;
3827 -   } else if (attribute == xvGamma5 && (IS_I915G(pI830))) {
3828 +   } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3829        if (!*pI830->overlayOn) {
3830           pPriv->gamma5 = value;
3831           if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
3832 @@ -828,7 +871,7 @@
3833          attribute == xvGamma2 ||
3834          attribute == xvGamma3 ||
3835          attribute == xvGamma4 ||
3836 -        attribute == xvGamma5) && (IS_I915G(pI830))) {
3837 +        attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3838         I830UpdateGamma(pScrn);
3839     }
3840  
3841 @@ -846,17 +889,19 @@
3842        *value = pPriv->brightness;
3843     } else if (attribute == xvContrast) {
3844        *value = pPriv->contrast;
3845 -   } else if (attribute == xvGamma0 && (IS_I915G(pI830))) {
3846 +   } else if (pI830->Clone && attribute == xvPipe) {
3847 +      *value = pPriv->pipe;
3848 +   } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3849        *value = pPriv->gamma0;
3850 -   } else if (attribute == xvGamma1 && (IS_I915G(pI830))) {
3851 +   } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3852        *value = pPriv->gamma1;
3853 -   } else if (attribute == xvGamma2 && (IS_I915G(pI830))) {
3854 +   } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3855        *value = pPriv->gamma2;
3856 -   } else if (attribute == xvGamma3 && (IS_I915G(pI830))) {
3857 +   } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3858        *value = pPriv->gamma3;
3859 -   } else if (attribute == xvGamma4 && (IS_I915G(pI830))) {
3860 +   } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3861        *value = pPriv->gamma4;
3862 -   } else if (attribute == xvGamma5 && (IS_I915G(pI830))) {
3863 +   } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
3864        *value = pPriv->gamma5;
3865     } else if (attribute == xvColorKey) {
3866        *value = pPriv->colorKey;
3867 @@ -912,7 +957,7 @@
3868  
3869  static void
3870  I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch,
3871 -                  int dstPitch, int srcH, int top, int left,
3872 +                  int srcPitch2, int dstPitch, int srcH, int top, int left,
3873                    int h, int w, int id)
3874  {
3875     I830Ptr pI830 = I830PTR(pScrn);
3876 @@ -920,8 +965,8 @@
3877     int i;
3878     unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
3879  
3880 -   DPRINTF(PFX, "I830CopyPlanarData: srcPitch %d, dstPitch %d\n"
3881 -          "nlines %d, npixels %d, top %d, left %d\n", srcPitch, dstPitch,
3882 +   ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
3883 +          "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch,
3884            h, w, top, left);
3885  
3886     /* Copy Y data */
3887 @@ -957,12 +1002,12 @@
3888  
3889     for (i = 0; i < h / 2; i++) {
3890        memcpy(dst2, src2, w / 2);
3891 -      src2 += srcPitch >> 1;
3892 +      src2 += srcPitch2;
3893        dst2 += dstPitch;
3894     }
3895  
3896     /* Copy U data for YV12, or V data for I420 */
3897 -   src3 = buf + (srcH * srcPitch) + ((srcH * srcPitch) >> 2) +
3898 +   src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) +
3899          ((top * srcPitch) >> 2) + (left >> 1);
3900     ErrorF("src3 is %p, offset is %d\n", src3,
3901           (unsigned long)src3 - (unsigned long)buf);
3902 @@ -980,7 +1025,7 @@
3903  
3904     for (i = 0; i < h / 2; i++) {
3905        memcpy(dst3, src3, w / 2);
3906 -      src3 += srcPitch >> 1;
3907 +      src3 += srcPitch2;
3908        dst3 += dstPitch;
3909     }
3910  }
3911 @@ -1125,70 +1170,126 @@
3912     I830OverlayRegPtr overlay =
3913          (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
3914     unsigned int swidth;
3915 +   unsigned int mask, shift, offsety, offsetu;
3916  
3917 -   DPRINTF(PFX, "I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
3918 +   ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
3919            dstPitch);
3920  
3921     if (!pPriv->overlayOK)
3922        return;
3923  
3924 +   if (IS_I915G(pI830) || IS_I915GM(pI830)) {
3925 +      shift = 6;
3926 +      mask = 0x3f;
3927 +   } else {
3928 +      shift = 5;
3929 +      mask = 0x1f;
3930 +   }
3931 +
3932 +   if (pPriv->currentBuf == 0) {
3933 +      offsety = pPriv->YBuf0offset;
3934 +      offsetu = pPriv->UBuf0offset;
3935 +   } else {
3936 +      offsety = pPriv->YBuf1offset;
3937 +      offsetu = pPriv->UBuf1offset;
3938 +   }
3939 +
3940  #if VIDEO_DEBUG
3941     CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
3942  #endif
3943  
3944     /* When in dual head with different bpp setups we need to refresh the
3945      * color key, so let's reset the video parameters and refresh here */
3946 -   I830ResetVideo(pScrn);
3947 +#if 0
3948 +   if (pI830->entityPrivate)
3949 +#endif
3950 +      I830ResetVideo(pScrn);
3951  
3952     switch (id) {
3953     case FOURCC_YV12:
3954     case FOURCC_I420:
3955 -      swidth = (width + 1) & ~1 & 0xfff;
3956 +      swidth = width;
3957 +
3958        overlay->SWIDTH = swidth;
3959        swidth /= 2;
3960        overlay->SWIDTH |= (swidth & 0x7ff) << 16;
3961  
3962 -      swidth = ((pPriv->YBuf0offset + width + 0x1f) >> 5) -
3963 -           (pPriv->YBuf0offset >> 5) - 1;
3964 +      swidth = ((offsety + width + mask) >> shift) -
3965 +           (offsety >> shift);
3966 +
3967 +      if (IS_I915G(pI830) || IS_I915GM(pI830))
3968 +         swidth <<= 1;
3969  
3970 -      ErrorF("Y width is %d, swidthsw is %d\n", width, swidth);
3971 +      swidth -= 1;
3972 +
3973 +      ErrorF("Y width is %d, swidth is %d\n", width, swidth);
3974  
3975        overlay->SWIDTHSW = swidth << 2;
3976  
3977 -      swidth = ((pPriv->UBuf0offset + (width / 2) + 0x1f) >> 5) -
3978 -           (pPriv->UBuf0offset >> 5) - 1;
3979 +      swidth = ((offsetu + (width / 2) + mask) >> shift) -
3980 +           (offsetu >> shift);
3981 +
3982 +      if (IS_I915G(pI830) || IS_I915GM(pI830))
3983 +         swidth <<= 1;
3984 +
3985 +      swidth -= 1;
3986 +
3987        ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth);
3988  
3989        overlay->SWIDTHSW |= swidth << 18;
3990 +
3991 +      ErrorF("HEIGHT is %d\n",height);
3992 +
3993 +      overlay->SHEIGHT = height | ((height / 2) << 16);
3994        break;
3995     case FOURCC_UYVY:
3996     case FOURCC_YUY2:
3997     default:
3998 -      /* XXX Check for i845 */
3999 -
4000 -      swidth = ((width + 31) & ~31) << 1;
4001 +      swidth = width;
4002        overlay->SWIDTH = swidth;
4003 -      overlay->SWIDTHSW = swidth >> 3;
4004 +
4005 +      ErrorF("Y width is %d\n", swidth);
4006 +
4007 +      swidth = ((offsety + (width << 1) + mask) >> shift) -
4008 +           (offsety >> shift);
4009 +
4010 +      if (IS_I915G(pI830) || IS_I915GM(pI830))
4011 +         swidth <<= 1;
4012 +
4013 +      swidth -= 1;
4014 +
4015 +      ErrorF("swidthsw is %d\n", swidth);
4016 +
4017 +      overlay->SWIDTHSW = swidth << 2;
4018 +
4019 +      ErrorF("HEIGHT is %d\n",height);
4020 +
4021 +      overlay->SHEIGHT = height;
4022        break;
4023     }
4024  
4025 -   overlay->SHEIGHT = height | ((height / 2) << 16);
4026 -
4027     if (pPriv->oneLineMode) {
4028        /* change the coordinates with panel fitting active */
4029        dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
4030        dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
4031 -
4032
4033        /* Now, alter the height, so we scale to the correct size */
4034 -      drw_h = dstBox->y2 - dstBox->y1;
4035 -      if (drw_h < height) drw_h = height;
4036 +      drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
4037 +
4038 +      /* Keep the engine happy */
4039 +      if (dstBox->y1 < 0) dstBox->y1 = 0;
4040 +      if (dstBox->y2 < 0) dstBox->y2 = 0;
4041     }
4042  
4043 +
4044     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
4045  
4046     overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
4047          (dstBox->x2 - dstBox->x1);
4048  
4049 +   ErrorF("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", dstBox->x1, dstBox->y1,
4050 +                       dstBox->x2, dstBox->y2);
4051 +
4052     /* buffer locations */
4053     overlay->OBUF_0Y = pPriv->YBuf0offset;
4054     overlay->OBUF_0U = pPriv->UBuf0offset;
4055 @@ -1252,8 +1353,8 @@
4056        /*
4057         * Y down-scale factor as a multiple of 4096.
4058         */
4059 -      xscaleFract = (src_w << 12) / drw_w;
4060 -      yscaleFract = (src_h << 12) / drw_h;
4061 +      xscaleFract = ((src_w - 1) << 12) / drw_w;
4062 +      yscaleFract = ((src_h - 1) << 12) / drw_h;
4063  
4064        /* Calculate the UV scaling factor. */
4065        xscaleFractUV = xscaleFract / uvratio;
4066 @@ -1273,9 +1374,9 @@
4067        xscaleIntUV = xscaleFractUV >> 12;
4068        yscaleIntUV = yscaleFractUV >> 12;
4069  
4070 -      ErrorF("xscale: 0x%x.%03x, yscale: 0x%x.%03x\n", xscaleInt,
4071 +      ErrorF("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt,
4072              xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
4073 -      ErrorF("UV xscale: 0x%x.%03x, UV yscale: 0x%x.%03x\n", xscaleIntUV,
4074 +      ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
4075              xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
4076  
4077        newval = (xscaleInt << 16) |
4078 @@ -1385,13 +1486,9 @@
4079  {
4080     ScreenPtr pScreen;
4081     FBLinearPtr new_linear;
4082 -   int bytespp = pScrn->bitsPerPixel >> 3;
4083  
4084     DPRINTF(PFX, "I830AllocateMemory\n");
4085  
4086 -   /* convert size in bytes into number of pixels */
4087 -   size = (size + bytespp - 1) / bytespp;
4088 -
4089     if (linear) {
4090        if (linear->size >= size)
4091          return linear;
4092 @@ -1438,7 +1535,7 @@
4093     I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
4094     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
4095     INT32 x1, x2, y1, y2;
4096 -   int srcPitch, dstPitch;
4097 +   int srcPitch, srcPitch2 = 0, dstPitch;
4098     int top, left, npixels, nlines, size, loops;
4099     BoxRec dstBox;
4100  
4101 @@ -1448,7 +1545,7 @@
4102  
4103     if (pI830->entityPrivate) {
4104          if (pI830->entityPrivate->XvInUse != -1 &&
4105 -            pI830->entityPrivate->XvInUse != pI830->pipe) {
4106 +            pI830->entityPrivate->XvInUse != pPriv->pipe) {
4107  #ifdef PANORAMIX
4108                 if (!noPanoramiXExtension) {
4109                         return Success; /* faked for trying to share it */
4110 @@ -1459,9 +1556,16 @@
4111                 }
4112          }
4113  
4114 -      pI830->entityPrivate->XvInUse = pI830->pipe;
4115 +      pI830->entityPrivate->XvInUse = pPriv->pipe;
4116     }
4117  
4118 +   /* overlay limits */
4119 +   if(src_w > (drw_w * 7))
4120 +      drw_w = src_w * 7;
4121 +
4122 +   if(src_h > (drw_h * 7))
4123 +      drw_h = src_h * 7;
4124 +
4125     /* Clip */
4126     x1 = src_x;
4127     x2 = src_x + src_w;
4128 @@ -1486,21 +1590,22 @@
4129     case FOURCC_YV12:
4130     case FOURCC_I420:
4131        srcPitch = (width + 3) & ~3;
4132 -      dstPitch = ((width / 2) + 255) & ~255;   /* of chroma */
4133 +      srcPitch2 = ((width >> 1) + 3) & ~3;
4134 +      dstPitch = ((width / 2) + 63) & ~63;     /* of chroma */
4135        size = dstPitch * height * 3;
4136        break;
4137     case FOURCC_UYVY:
4138     case FOURCC_YUY2:
4139     default:
4140 -      srcPitch = (width << 1);
4141 -      dstPitch = (srcPitch + 255) & ~255;
4142 +      srcPitch = width << 1;
4143 +      dstPitch = (srcPitch + 63) & ~63;        /* of chroma */
4144        size = dstPitch * height;
4145        break;
4146     }
4147     ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
4148  
4149 -   if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear,
4150 -                                           size * 2 / pI830->cpp)))
4151 +   /* size is multiplied by 2 because we have two buffers that are flipping */
4152 +   if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, size * 2 / pI830->cpp)))
4153        return BadAlloc;
4154  
4155     /* fixup pointers */
4156 @@ -1549,7 +1654,7 @@
4157     case FOURCC_I420:
4158        top &= ~1;
4159        nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
4160 -      I830CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left,
4161 +      I830CopyPlanarData(pScrn, buf, srcPitch, srcPitch2, dstPitch, height, top, left,
4162                          nlines, npixels, id);
4163        break;
4164     case FOURCC_UYVY:
4165 @@ -1605,21 +1710,13 @@
4166     case FOURCC_YV12:
4167     case FOURCC_I420:
4168        *h = (*h + 1) & ~1;
4169 -#if 1
4170        size = (*w + 3) & ~3;
4171 -#else
4172 -      size = (*w + 255) & ~255;
4173 -#endif
4174        if (pitches)
4175          pitches[0] = size;
4176        size *= *h;
4177        if (offsets)
4178          offsets[1] = size;
4179 -#if 1
4180        tmp = ((*w >> 1) + 3) & ~3;
4181 -#else
4182 -      tmp = ((*w >> 1) + 255) & ~255;
4183 -#endif
4184        if (pitches)
4185          pitches[1] = pitches[2] = tmp;
4186        tmp *= (*h >> 1);
4187 @@ -1836,7 +1933,7 @@
4188  
4189     if (pI830->entityPrivate) {
4190          if (pI830->entityPrivate->XvInUse != -1 &&
4191 -            pI830->entityPrivate->XvInUse != pI830->pipe) {
4192 +            pI830->entityPrivate->XvInUse != pI830Priv->pipe) {
4193  #ifdef PANORAMIX
4194                 if (!noPanoramiXExtension) {
4195                         return Success; /* faked for trying to share it */
4196 @@ -1847,7 +1944,7 @@
4197                 }
4198          }
4199  
4200 -      pI830->entityPrivate->XvInUse = pI830->pipe;
4201 +      pI830->entityPrivate->XvInUse = pI830Priv->pipe;
4202     }
4203  
4204     x1 = src_x;
4205 @@ -1978,7 +2075,7 @@
4206     if (!pPriv)
4207        return;
4208  
4209 -   if (pI830->pipe == 0) {
4210 +   if (pPriv->pipe == 0) {
4211        if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) {
4212           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
4213            "Disabling XVideo output because Pipe A is in double-wide mode.\n");
4214 @@ -1990,7 +2087,7 @@
4215        }
4216     }
4217  
4218 -   if (pI830->pipe == 1) {
4219 +   if (pPriv->pipe == 1) {
4220        if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) {
4221           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
4222            "Disabling XVideo output because Pipe B is in double-wide mode.\n");
4223 @@ -2002,12 +2099,13 @@
4224        }
4225     }
4226  
4227 -   /* Check we are on pipe B and have an LFP connected */
4228 -   if ((pI830->pipe == 1) && (pI830->operatingDevices & (PIPE_LFP << 8))) {
4229 -      size = INREG(PIPEBSRC);
4230 +   /* Check we have an LFP connected */
4231 +   if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
4232 +       (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
4233 +      size = pI830->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
4234        hsize = (size >> 16) & 0x7FF;
4235        vsize = size & 0x7FF;
4236 -      active = INREG(VTOTAL_B) & 0x7FF;
4237 +      active = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
4238  
4239        if (vsize < active && hsize > 1024)
4240           I830SetOneLineModeRatio(pScrn);
4241 --- /dev/null   2004-06-24 14:04:38.000000000 -0400
4242 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_modes.c    2005-08-18 19:40:24.000000000 -0400
4243 @@ -0,0 +1,769 @@
4244 +#define DEBUG_VERB 2
4245 +/*
4246 + * Copyright © 2002 David Dawes
4247 + *
4248 + * Permission is hereby granted, free of charge, to any person obtaining a
4249 + * copy of this software and associated documentation files (the "Software"),
4250 + * to deal in the Software without restriction, including without limitation
4251 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4252 + * and/or sell copies of the Software, and to permit persons to whom the
4253 + * Software is furnished to do so, subject to the following conditions:
4254 + *
4255 + * The above copyright notice and this permission notice shall be included in
4256 + * all copies or substantial portions of the Software.
4257 + *
4258 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4259 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4260 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
4261 + * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
4262 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
4263 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4264 + * SOFTWARE.
4265 + *
4266 + * Except as contained in this notice, the name of the author(s) shall
4267 + * not be used in advertising or otherwise to promote the sale, use or other
4268 + * dealings in this Software without prior written authorization from
4269 + * the author(s).
4270 + *
4271 + * Authors: David Dawes <dawes@xfree86.org>
4272 + *
4273 + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
4274 + */
4275 +/*
4276 + * Modified by Alan Hourihane <alanh@tungstengraphics.com>
4277 + * to support extended BIOS modes for the Intel chipsets
4278 + */
4279 +
4280 +#include "xf86.h"
4281 +#include "xf86_ansic.h"
4282 +#include "vbe.h"
4283 +#include "vbeModes.h"
4284 +#include "i830.h"
4285 +
4286 +#include <math.h>
4287 +
4288 +#define rint(x) floor(x)
4289 +
4290 +#define MARGIN_PERCENT    1.8   /* % of active vertical image                */
4291 +#define CELL_GRAN         8.0   /* assumed character cell granularity        */
4292 +#define MIN_PORCH         1     /* minimum front porch                       */
4293 +#define V_SYNC_RQD        3     /* width of vsync in lines                   */
4294 +#define H_SYNC_PERCENT    8.0   /* width of hsync as % of total line         */
4295 +#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
4296 +#define M                 600.0 /* blanking formula gradient                 */
4297 +#define C                 40.0  /* blanking formula offset                   */
4298 +#define K                 128.0 /* blanking formula scaling factor           */
4299 +#define J                 20.0  /* blanking formula scaling factor           */
4300 +
4301 +/* C' and M' are part of the Blanking Duty Cycle computation */
4302 +
4303 +#define C_PRIME           (((C - J) * K/256.0) + J)
4304 +#define M_PRIME           (K/256.0 * M)
4305 +
4306 +extern const int i830refreshes[];
4307 +
4308 +static DisplayModePtr
4309 +I830GetGTF (int h_pixels, int v_lines, float freq,
4310 +                    int interlaced, int margins)
4311 +{
4312 +    float h_pixels_rnd;
4313 +    float v_lines_rnd;
4314 +    float v_field_rate_rqd;
4315 +    float top_margin;
4316 +    float bottom_margin;
4317 +    float interlace;
4318 +    float h_period_est;
4319 +    float vsync_plus_bp;
4320 +    float v_back_porch;
4321 +    float total_v_lines;
4322 +    float v_field_rate_est;
4323 +    float h_period;
4324 +    float v_field_rate;
4325 +    float v_frame_rate;
4326 +    float left_margin;
4327 +    float right_margin;
4328 +    float total_active_pixels;
4329 +    float ideal_duty_cycle;
4330 +    float h_blank;
4331 +    float total_pixels;
4332 +    float pixel_freq;
4333 +    float h_freq;
4334 +
4335 +    float h_sync;
4336 +    float h_front_porch;
4337 +    float v_odd_front_porch_lines;
4338 +    char modename[20];
4339 +    DisplayModePtr m;
4340 +
4341 +    m = xnfcalloc(sizeof(DisplayModeRec), 1);
4342 +    
4343 +    
4344 +    /*  1. In order to give correct results, the number of horizontal
4345 +     *  pixels requested is first processed to ensure that it is divisible
4346 +     *  by the character size, by rounding it to the nearest character
4347 +     *  cell boundary:
4348 +     *
4349 +     *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
4350 +     */
4351 +    
4352 +    h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
4353 +    
4354 +    
4355 +    /*  2. If interlace is requested, the number of vertical lines assumed
4356 +     *  by the calculation must be halved, as the computation calculates
4357 +     *  the number of vertical lines per field. In either case, the
4358 +     *  number of lines is rounded to the nearest integer.
4359 +     *   
4360 +     *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
4361 +     *                                     ROUND([V LINES],0))
4362 +     */
4363 +
4364 +    v_lines_rnd = interlaced ?
4365 +            rint((float) v_lines) / 2.0 :
4366 +            rint((float) v_lines);
4367 +    
4368 +    /*  3. Find the frame rate required:
4369 +     *
4370 +     *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
4371 +     *                                          [I/P FREQ RQD])
4372 +     */
4373 +
4374 +    v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
4375 +
4376 +    /*  4. Find number of lines in Top margin:
4377 +     *
4378 +     *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
4379 +     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
4380 +     *          0)
4381 +     */
4382 +
4383 +    top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
4384 +
4385 +    /*  5. Find number of lines in Bottom margin:
4386 +     *
4387 +     *  [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
4388 +     *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
4389 +     *          0)
4390 +     */
4391 +
4392 +    bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
4393 +
4394 +    /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
4395 +     *   
4396 +     *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
4397 +     */
4398 +
4399 +    interlace = interlaced ? 0.5 : 0.0;
4400 +
4401 +    /*  7. Estimate the Horizontal period
4402 +     *
4403 +     *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
4404 +     *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
4405 +     *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
4406 +     */
4407 +
4408 +    h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
4409 +                    / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
4410 +                    * 1000000.0);
4411 +
4412 +    /*  8. Find the number of lines in V sync + back porch:
4413 +     *
4414 +     *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
4415 +     */
4416 +
4417 +    vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
4418 +
4419 +    /*  9. Find the number of lines in V back porch alone:
4420 +     *
4421 +     *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
4422 +     *
4423 +     *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
4424 +     */
4425 +    
4426 +    v_back_porch = vsync_plus_bp - V_SYNC_RQD;
4427 +    
4428 +    /*  10. Find the total number of lines in Vertical field period:
4429 +     *
4430 +     *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
4431 +     *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
4432 +     *                    [MIN PORCH RND]
4433 +     */
4434 +
4435 +    total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
4436 +        interlace + MIN_PORCH;
4437 +    
4438 +    /*  11. Estimate the Vertical field frequency:
4439 +     *
4440 +     *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
4441 +     */
4442 +
4443 +    v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
4444 +    
4445 +    /*  12. Find the actual horizontal period:
4446 +     *
4447 +     *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
4448 +     */
4449 +
4450 +    h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
4451 +    
4452 +    /*  13. Find the actual Vertical field frequency:
4453 +     *
4454 +     *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
4455 +     */
4456 +
4457 +    v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
4458 +
4459 +    /*  14. Find the Vertical frame frequency:
4460 +     *
4461 +     *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
4462 +     */
4463 +
4464 +    v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
4465 +
4466 +    /*  15. Find number of pixels in left margin:
4467 +     *
4468 +     *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
4469 +     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
4470 +     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
4471 +     *          0))
4472 +     */
4473 +
4474 +    left_margin = margins ?
4475 +        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
4476 +        0.0;
4477 +    
4478 +    /*  16. Find number of pixels in right margin:
4479 +     *
4480 +     *  [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
4481 +     *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
4482 +     *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
4483 +     *          0))
4484 +     */
4485 +    
4486 +    right_margin = margins ?
4487 +        rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
4488 +        0.0;
4489 +    
4490 +    /*  17. Find total number of active pixels in image and left and right
4491 +     *  margins:
4492 +     *
4493 +     *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
4494 +     *                          [RIGHT MARGIN (PIXELS)]
4495 +     */
4496 +
4497 +    total_active_pixels = h_pixels_rnd + left_margin + right_margin;
4498 +    
4499 +    /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
4500 +     *  equation:
4501 +     *
4502 +     *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
4503 +     */
4504 +
4505 +    ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
4506 +    
4507 +    /*  19. Find the number of pixels in the blanking time to the nearest
4508 +     *  double character cell:
4509 +     *
4510 +     *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
4511 +     *                               [IDEAL DUTY CYCLE] /
4512 +     *                               (100-[IDEAL DUTY CYCLE]) /
4513 +     *                               (2*[CELL GRAN RND])), 0))
4514 +     *                       * (2*[CELL GRAN RND])
4515 +     */
4516 +
4517 +    h_blank = rint(total_active_pixels *
4518 +                   ideal_duty_cycle /
4519 +                   (100.0 - ideal_duty_cycle) /
4520 +                   (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
4521 +    
4522 +    /*  20. Find total number of pixels:
4523 +     *
4524 +     *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
4525 +     */
4526 +
4527 +    total_pixels = total_active_pixels + h_blank;
4528 +    
4529 +    /*  21. Find pixel clock frequency:
4530 +     *
4531 +     *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
4532 +     */
4533 +    
4534 +    pixel_freq = total_pixels / h_period;
4535 +    
4536 +    /*  22. Find horizontal frequency:
4537 +     *
4538 +     *  [H FREQ] = 1000 / [H PERIOD]
4539 +     */
4540 +
4541 +    h_freq = 1000.0 / h_period;
4542 +    
4543 +
4544 +    /* Stage 1 computations are now complete; I should really pass
4545 +       the results to another function and do the Stage 2
4546 +       computations, but I only need a few more values so I'll just
4547 +       append the computations here for now */
4548 +
4549 +    
4550 +
4551 +    /*  17. Find the number of pixels in the horizontal sync period:
4552 +     *
4553 +     *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
4554 +     *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
4555 +     */
4556 +
4557 +    h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
4558 +
4559 +    /*  18. Find the number of pixels in the horizontal front porch period:
4560 +     *
4561 +     *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
4562 +     */
4563 +
4564 +    h_front_porch = (h_blank / 2.0) - h_sync;
4565 +
4566 +    /*  36. Find the number of lines in the odd front porch period:
4567 +     *
4568 +     *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
4569 +     */
4570 +    
4571 +    v_odd_front_porch_lines = MIN_PORCH + interlace;
4572 +    
4573 +    /* finally, pack the results in the DisplayMode struct */
4574 +    
4575 +    m->HDisplay  = (int) (h_pixels_rnd);
4576 +    m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
4577 +    m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
4578 +    m->HTotal = (int) (total_pixels);
4579 +
4580 +    m->VDisplay  = (int) (v_lines_rnd);
4581 +    m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
4582 +    m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
4583 +    m->VTotal = (int) (total_v_lines);
4584 +
4585 +    m->Clock   = (int)(pixel_freq * 1000);
4586 +    m->SynthClock   = m->Clock;
4587 +    m->HSync = h_freq;
4588 +    m->VRefresh = freq;
4589 +
4590 +    snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
4591 +    m->name = xnfstrdup(modename);
4592 +
4593 +    return (m);
4594 +}
4595 +
4596 +static DisplayModePtr
4597 +CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id,
4598 +         int flags)
4599 +{
4600 +    CARD16 major, minor;
4601 +    VbeModeInfoBlock *mode;
4602 +    DisplayModePtr p = NULL, pMode = NULL;
4603 +    VbeModeInfoData *data;
4604 +    Bool modeOK = FALSE;
4605 +    ModeStatus status = MODE_OK;
4606 +
4607 +    major = (unsigned)(vbe->VESAVersion >> 8);
4608 +    minor = vbe->VESAVersion & 0xff;
4609 +
4610 +    if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
4611 +       return NULL;
4612 +
4613 +    /* Does the mode match the depth/bpp? */
4614 +    /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */
4615 +    if (VBE_MODE_USABLE(mode, flags) &&
4616 +       ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
4617 +        (mode->BitsPerPixel > 8 &&
4618 +         (mode->RedMaskSize + mode->GreenMaskSize +
4619 +          mode->BlueMaskSize) == pScrn->depth &&
4620 +         mode->BitsPerPixel == pScrn->bitsPerPixel) ||
4621 +        (mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
4622 +        (mode->BitsPerPixel <= 8 &&
4623 +         mode->BitsPerPixel == pScrn->bitsPerPixel))) {
4624 +       modeOK = TRUE;
4625 +       xf86ErrorFVerb(DEBUG_VERB, "*");
4626 +    }
4627 +
4628 +    if (mode->XResolution && mode->YResolution &&
4629 +       !I830CheckModeSupport(pScrn, mode->XResolution, mode->YResolution, id)) 
4630 +       modeOK = FALSE;
4631 +
4632 +
4633 +    /*
4634 +     * Check if there's a valid monitor mode that this one can be matched
4635 +     * up with from the 'specified' modes list.
4636 +     */
4637 +    if (modeOK) {
4638 +       for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
4639 +           if ((p->type != 0) ||
4640 +               (p->HDisplay != mode->XResolution) ||
4641 +               (p->VDisplay != mode->YResolution) ||
4642 +               (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
4643 +               continue;
4644 +           status = xf86CheckModeForMonitor(p, pScrn->monitor);
4645 +           if (status == MODE_OK) {
4646 +               modeOK = TRUE;
4647 +               break;
4648 +           }
4649 +       }
4650 +       if (p) {
4651 +               pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
4652 +               memcpy((char*)pMode,(char*)p,sizeof(DisplayModeRec));
4653 +               pMode->name = xnfstrdup(p->name);
4654 +       }
4655 +    } 
4656 +
4657 +    /*
4658 +     * Now, check if there's a valid monitor mode that this one can be matched
4659 +     * up with from the default modes list. i.e. VESA modes in xf86DefModes.c
4660 +     */
4661 +    if (modeOK && !pMode) {
4662 +       int refresh = 0, calcrefresh = 0;
4663 +       DisplayModePtr newMode = NULL;
4664 +
4665 +       for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
4666 +           calcrefresh = (int)(((double)(p->Clock * 1000) /
4667 +                       (double)(p->HTotal * p->VTotal)) * 100);
4668 +           if ((p->type != M_T_DEFAULT) ||
4669 +               (p->HDisplay != mode->XResolution) ||
4670 +               (p->VDisplay != mode->YResolution) ||
4671 +               (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
4672 +               continue;
4673 +           status = xf86CheckModeForMonitor(p, pScrn->monitor);
4674 +           if (status == MODE_OK) {
4675 +               if (calcrefresh > refresh) {
4676 +                       refresh = calcrefresh;
4677 +                       newMode = p;
4678 +               }
4679 +               modeOK = TRUE;
4680 +           }
4681 +       }
4682 +       if (newMode) {
4683 +               pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
4684 +               memcpy((char*)pMode,(char*)newMode,sizeof(DisplayModeRec));
4685 +               pMode->name = xnfstrdup(newMode->name);
4686 +       }
4687 +    } 
4688 +
4689 +    /*
4690 +     * Check if there's a valid monitor mode that this one can be matched
4691 +     * up with.  The actual matching is done later.
4692 +     */
4693 +    if (modeOK && !pMode) {
4694 +       float vrefresh = 0.0f;
4695 +       int i;
4696 +
4697 +       for (i=0;i<pScrn->monitor->nVrefresh;i++) {
4698 +
4699 +           for (vrefresh = pScrn->monitor->vrefresh[i].hi; 
4700 +                vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) {
4701 +
4702 +               if (vrefresh != (float)0.0f) {
4703 +                    float best_vrefresh;
4704 +                    int int_vrefresh;
4705
4706 +                    /* Find the best refresh for the Intel chipsets */
4707 +                    int_vrefresh = I830GetBestRefresh(pScrn, (int)vrefresh);
4708 +                   best_vrefresh = (float)i830refreshes[int_vrefresh];
4709 +
4710 +                    /* Now, grab the best mode from the available refresh */
4711 +                   pMode = I830GetGTF(mode->XResolution, mode->YResolution, 
4712 +                                                       best_vrefresh, 0, 0);
4713 +
4714 +                   pMode->type = M_T_BUILTIN;
4715 +
4716 +                   status = xf86CheckModeForMonitor(pMode, pScrn->monitor);
4717 +                   if (status == MODE_OK) {
4718 +                       if (major >= 3) {
4719 +                           if (pMode->Clock * 1000 <= mode->MaxPixelClock)
4720 +                               modeOK = TRUE;
4721 +                           else
4722 +                               modeOK = FALSE;
4723 +                       } else
4724 +                           modeOK = TRUE;
4725 +                   } else
4726 +                       modeOK = FALSE;
4727 +                   pMode->status = status;
4728 +               } else { 
4729 +                   modeOK = FALSE;
4730 +               }
4731 +               if (modeOK) break;
4732 +            }
4733 +           if (modeOK) break;
4734 +        }
4735 +    }
4736 +
4737 +    xf86ErrorFVerb(DEBUG_VERB,
4738 +           "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
4739 +    xf86ErrorFVerb(DEBUG_VERB,
4740 +           "   ModeAttributes: 0x%x\n", mode->ModeAttributes);
4741 +    xf86ErrorFVerb(DEBUG_VERB,
4742 +           "   WinAAttributes: 0x%x\n", mode->WinAAttributes);
4743 +    xf86ErrorFVerb(DEBUG_VERB,
4744 +           "   WinBAttributes: 0x%x\n", mode->WinBAttributes);
4745 +    xf86ErrorFVerb(DEBUG_VERB,
4746 +           "   WinGranularity: %d\n", mode->WinGranularity);
4747 +    xf86ErrorFVerb(DEBUG_VERB,
4748 +           "   WinSize: %d\n", mode->WinSize);
4749 +    xf86ErrorFVerb(DEBUG_VERB,
4750 +           "   WinASegment: 0x%x\n", mode->WinASegment);
4751 +    xf86ErrorFVerb(DEBUG_VERB,
4752 +           "   WinBSegment: 0x%x\n", mode->WinBSegment);
4753 +    xf86ErrorFVerb(DEBUG_VERB,
4754 +           "   WinFuncPtr: 0x%lx\n", mode->WinFuncPtr);
4755 +    xf86ErrorFVerb(DEBUG_VERB,
4756 +           "   BytesPerScanline: %d\n", mode->BytesPerScanline);
4757 +    xf86ErrorFVerb(DEBUG_VERB,
4758 +           "   XResolution: %d\n", mode->XResolution);
4759 +    xf86ErrorFVerb(DEBUG_VERB,
4760 +           "   YResolution: %d\n", mode->YResolution);
4761 +    xf86ErrorFVerb(DEBUG_VERB,
4762 +           "   XCharSize: %d\n", mode->XCharSize);
4763 +    xf86ErrorFVerb(DEBUG_VERB,
4764 +           "   YCharSize: %d\n", mode->YCharSize);
4765 +    xf86ErrorFVerb(DEBUG_VERB,
4766 +           "   NumberOfPlanes: %d\n", mode->NumberOfPlanes);
4767 +    xf86ErrorFVerb(DEBUG_VERB,
4768 +           "   BitsPerPixel: %d\n", mode->BitsPerPixel);
4769 +    xf86ErrorFVerb(DEBUG_VERB,
4770 +           "   NumberOfBanks: %d\n", mode->NumberOfBanks);
4771 +    xf86ErrorFVerb(DEBUG_VERB,
4772 +           "   MemoryModel: %d\n", mode->MemoryModel);
4773 +    xf86ErrorFVerb(DEBUG_VERB,
4774 +           "   BankSize: %d\n", mode->BankSize);
4775 +    xf86ErrorFVerb(DEBUG_VERB,
4776 +           "   NumberOfImages: %d\n", mode->NumberOfImages);
4777 +    xf86ErrorFVerb(DEBUG_VERB,
4778 +           "   RedMaskSize: %d\n", mode->RedMaskSize);
4779 +    xf86ErrorFVerb(DEBUG_VERB,
4780 +           "   RedFieldPosition: %d\n", mode->RedFieldPosition);
4781 +    xf86ErrorFVerb(DEBUG_VERB,
4782 +           "   GreenMaskSize: %d\n", mode->GreenMaskSize);
4783 +    xf86ErrorFVerb(DEBUG_VERB,
4784 +           "   GreenFieldPosition: %d\n", mode->GreenFieldPosition);
4785 +    xf86ErrorFVerb(DEBUG_VERB,
4786 +           "   BlueMaskSize: %d\n", mode->BlueMaskSize);
4787 +    xf86ErrorFVerb(DEBUG_VERB,
4788 +           "   BlueFieldPosition: %d\n", mode->BlueFieldPosition);
4789 +    xf86ErrorFVerb(DEBUG_VERB,
4790 +           "   RsvdMaskSize: %d\n", mode->RsvdMaskSize);
4791 +    xf86ErrorFVerb(DEBUG_VERB,
4792 +           "   RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
4793 +    xf86ErrorFVerb(DEBUG_VERB,
4794 +           "   DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
4795 +    if (major >= 2) {
4796 +       xf86ErrorFVerb(DEBUG_VERB,
4797 +               "       PhysBasePtr: 0x%lx\n", mode->PhysBasePtr);
4798 +       if (major >= 3) {
4799 +           xf86ErrorFVerb(DEBUG_VERB,
4800 +                   "   LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
4801 +           xf86ErrorFVerb(DEBUG_VERB,
4802 +                   "   BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages);
4803 +           xf86ErrorFVerb(DEBUG_VERB,
4804 +                   "   LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages);
4805 +           xf86ErrorFVerb(DEBUG_VERB,
4806 +                   "   LinRedMaskSize: %d\n", mode->LinRedMaskSize);
4807 +           xf86ErrorFVerb(DEBUG_VERB,
4808 +                   "   LinRedFieldPosition: %d\n", mode->LinRedFieldPosition);
4809 +           xf86ErrorFVerb(DEBUG_VERB,
4810 +                   "   LinGreenMaskSize: %d\n", mode->LinGreenMaskSize);
4811 +           xf86ErrorFVerb(DEBUG_VERB,
4812 +                   "   LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition);
4813 +           xf86ErrorFVerb(DEBUG_VERB,
4814 +                   "   LinBlueMaskSize: %d\n", mode->LinBlueMaskSize);
4815 +           xf86ErrorFVerb(DEBUG_VERB,
4816 +                   "   LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition);
4817 +           xf86ErrorFVerb(DEBUG_VERB,
4818 +                   "   LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize);
4819 +           xf86ErrorFVerb(DEBUG_VERB,
4820 +                   "   LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
4821 +           xf86ErrorFVerb(DEBUG_VERB,
4822 +                   "   MaxPixelClock: %ld\n", mode->MaxPixelClock);
4823 +       }
4824 +    }
4825 +
4826 +    if (!modeOK) {
4827 +       VBEFreeModeInfo(mode);
4828 +       if (pMode)
4829 +           xfree(pMode);
4830 +       return NULL;
4831 +    }
4832 +
4833 +    pMode->status = MODE_OK;
4834 +    pMode->type = M_T_BUILTIN;
4835 +
4836 +    /* for adjust frame */
4837 +    pMode->HDisplay = mode->XResolution;
4838 +    pMode->VDisplay = mode->YResolution;
4839 +
4840 +    data = xnfcalloc(sizeof(VbeModeInfoData), 1);
4841 +    data->mode = id;
4842 +    data->data = mode;
4843 +    pMode->PrivSize = sizeof(VbeModeInfoData);
4844 +    pMode->Private = (INT32*)data;
4845 +    pMode->next = NULL;
4846 +    return pMode;
4847 +}
4848 +
4849 +/*
4850 + * Check the available BIOS modes, and extract those that match the
4851 + * requirements into the modePool.  Note: modePool is a NULL-terminated
4852 + * list.
4853 + */
4854 +
4855 +DisplayModePtr
4856 +I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe)
4857 +{
4858 +   DisplayModePtr pMode, p = NULL, modePool = NULL;
4859 +   int i = 0;
4860 +
4861 +   for (i = 0; i < 0x7F; i++) {
4862 +      if ((pMode = CheckMode(pScrn, pVbe, vbe, i, V_MODETYPE_VGA)) != NULL) {
4863 +         ModeStatus status = MODE_OK;
4864 +
4865 +               /* Check the mode against a specified virtual size (if any) */
4866 +               if (pScrn->display->virtualX > 0 &&
4867 +                   pMode->HDisplay > pScrn->display->virtualX) {
4868 +                   status = MODE_VIRTUAL_X;
4869 +               }
4870 +               if (pScrn->display->virtualY > 0 &&
4871 +                   pMode->VDisplay > pScrn->display->virtualY) {
4872 +                   status = MODE_VIRTUAL_Y;
4873 +               }
4874 +               if (status != MODE_OK) {
4875 +                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4876 +                               "Not using mode \"%dx%d\" (%s)\n",
4877 +                               pMode->HDisplay, pMode->VDisplay,
4878 +                               xf86ModeStatusToString(status));
4879 +               } else {
4880 +                   if (p == NULL) {
4881 +                       modePool = pMode;
4882 +                   } else {
4883 +                       p->next = pMode;
4884 +                   }
4885 +                   pMode->prev = NULL;
4886 +                   p = pMode;
4887 +               }
4888 +           }
4889 +       }
4890 +    return modePool;
4891 +}
4892 +
4893 +/*
4894 + * Go through the monitor modes and selecting the best set of
4895 + * parameters for each BIOS mode.  Note: This is only supported in
4896 + * VBE version 3.0 or later.
4897 + */
4898 +void
4899 +I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
4900 +{
4901 +    DisplayModePtr pMode;
4902 +    VbeModeInfoData *data;
4903 +
4904 +    pMode = pScrn->modes;
4905 +    do {
4906 +       int clock;
4907 +
4908 +       data = (VbeModeInfoData*)pMode->Private;
4909 +       data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
4910 +       data->block->HorizontalTotal = pMode->HTotal;
4911 +       data->block->HorizontalSyncStart = pMode->HSyncStart;
4912 +       data->block->HorizontalSyncEnd = pMode->HSyncEnd;
4913 +       data->block->VerticalTotal = pMode->VTotal;
4914 +       data->block->VerticalSyncStart = pMode->VSyncStart;
4915 +       data->block->VerticalSyncEnd = pMode->VSyncEnd;
4916 +       data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
4917 +                                ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
4918 +       data->block->PixelClock = pMode->Clock * 1000;
4919 +       /* XXX May not have this. */
4920 +       clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
4921 +       if (clock)
4922 +           data->block->PixelClock = clock;
4923 +#ifdef DEBUG
4924 +       ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
4925 +               (double)data->block->PixelClock / 1000000.0, 
4926 +               (double)clock / 1000000.0);
4927 +#endif
4928 +       data->mode |= (1 << 11);
4929 +       if (pMode->VRefresh != 0) {
4930 +           data->block->RefreshRate = pMode->VRefresh * 100;
4931 +       } else {
4932 +           data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/
4933 +                       (double)(pMode->HTotal * pMode->VTotal)) * 100);
4934 +       }
4935 +       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4936 +                      "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n",
4937 +                      (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode);
4938 +#ifdef DEBUG
4939 +       ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - "
4940 +              "  %i %i %i %i %.2f MHz Refresh: %.2f Hz\n",
4941 +              data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart,
4942 +              pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay,
4943 +              pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal,
4944 +              (double)data->block->PixelClock/1000000.0,
4945 +              (double)data->block->RefreshRate/100);
4946 +#endif
4947 +       pMode = pMode->next;
4948 +    } while (pMode != pScrn->modes);
4949 +}
4950 +
4951 +void
4952 +I830PrintModes(ScrnInfoPtr scrp)
4953 +{
4954 +    DisplayModePtr p;
4955 +    float hsync, refresh = 0;
4956 +    char *desc, *desc2, *prefix, *uprefix;
4957 +
4958 +    if (scrp == NULL)
4959 +       return;
4960 +
4961 +    xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d "
4962 +              "(pitch %d)\n", scrp->virtualX, scrp->virtualY,
4963 +              scrp->displayWidth);
4964 +    
4965 +    p = scrp->modes;
4966 +    if (p == NULL)
4967 +       return;
4968 +
4969 +    do {
4970 +       desc = desc2 = "";
4971 +       if (p->HSync > 0.0)
4972 +           hsync = p->HSync;
4973 +       else if (p->HTotal > 0)
4974 +           hsync = (float)p->Clock / (float)p->HTotal;
4975 +       else
4976 +           hsync = 0.0;
4977 +       if (p->VTotal > 0)
4978 +           refresh = hsync * 1000.0 / p->VTotal;
4979 +       if (p->Flags & V_INTERLACE) {
4980 +           refresh *= 2.0;
4981 +           desc = " (I)";
4982 +       }
4983 +       if (p->Flags & V_DBLSCAN) {
4984 +           refresh /= 2.0;
4985 +           desc = " (D)";
4986 +       }
4987 +       if (p->VScan > 1) {
4988 +           refresh /= p->VScan;
4989 +           desc2 = " (VScan)";
4990 +       }
4991 +       if (p->VRefresh > 0.0)
4992 +           refresh = p->VRefresh;
4993 +       if (p->type & M_T_BUILTIN)
4994 +           prefix = "Built-in mode";
4995 +       else if (p->type & M_T_DEFAULT)
4996 +           prefix = "Default mode";
4997 +       else
4998 +           prefix = "Mode";
4999 +       if (p->type & M_T_USERDEF)
5000 +           uprefix = "*";
5001 +       else
5002 +           uprefix = " ";
5003 +       if (p->name)
5004 +           xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
5005 +                          "%s%s \"%s\"\n", uprefix, prefix, p->name);
5006 +       else
5007 +           xf86DrvMsg(scrp->scrnIndex, X_PROBED,
5008 +                          "%s%s %dx%d (unnamed)\n",
5009 +                          uprefix, prefix, p->HDisplay, p->VDisplay);
5010 +       p = p->next;
5011 +    } while (p != NULL && p != scrp->modes);
5012 +}
5013 --- /dev/null   2004-06-24 14:04:38.000000000 -0400
5014 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_shadow.c   2005-08-18 19:40:24.000000000 -0400
5015 @@ -0,0 +1,249 @@
5016 +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_shadow.c,v 1.3 2000/03/31 20:13:33 dawes Exp $ */
5017 +
5018 +/*
5019 +   Copyright (c) 1999,2000  The XFree86 Project Inc. 
5020 +   based on code written by Mark Vojkovich <markv@valinux.com>
5021 +*/
5022 +
5023 +/*
5024 + * Ported from the savage driver to the I830 by
5025 + * Helmar Spangenberg <hspangenberg@frey.de> and Dima Dorfman
5026 + */
5027 +
5028 +#include "xf86.h"
5029 +#include "i830.h"
5030 +#include "shadowfb.h"
5031 +#include "servermd.h"
5032 +
5033 +
5034 +void
5035 +I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
5036 +{
5037 +    I830Ptr pI830 = I830PTR(pScrn);
5038 +    int width, height, Bpp, FBPitch;
5039 +    unsigned char *src, *dst;
5040 +   
5041 +    Bpp = pScrn->bitsPerPixel >> 3;
5042 +    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
5043 +
5044 +    while(num--) {
5045 +       width = (pbox->x2 - pbox->x1) * Bpp;
5046 +       height = pbox->y2 - pbox->y1;
5047 +       src = pI830->shadowPtr + (pbox->y1 * pI830->shadowPitch) + 
5048 +                                               (pbox->x1 * Bpp);
5049 +       dst = pI830->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
5050 +
5051 +       while(height--) {
5052 +           memcpy(dst, src, width);
5053 +           dst += FBPitch;
5054 +           src += pI830->shadowPitch;
5055 +       }
5056 +       
5057 +       pbox++;
5058 +    }
5059 +} 
5060 +
5061 +
5062 +void
5063 +I830PointerMoved(int index, int x, int y)
5064 +{
5065 +    ScrnInfoPtr pScrn = xf86Screens[index];
5066 +    I830Ptr pI830 = I830PTR(pScrn);
5067 +    int newX, newY;
5068 +
5069 +    if(pI830->rotate == 1) {
5070 +       newX = pScrn->pScreen->height - y - 1;
5071 +       newY = x;
5072 +    } else {
5073 +       newX = y;
5074 +       newY = pScrn->pScreen->width - x - 1;
5075 +    }
5076 +
5077 +    (*pI830->PointerMoved)(index, newX, newY);
5078 +}
5079 +
5080 +void
5081 +I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
5082 +{
5083 +    I830Ptr pI830 = I830PTR(pScrn);
5084 +    int count, width, height, y1, y2, dstPitch, srcPitch;
5085 +    CARD8 *dstPtr, *srcPtr, *src;
5086 +    CARD32 *dst;
5087 +
5088 +    dstPitch = pScrn->displayWidth;
5089 +    srcPitch = -pI830->rotate * pI830->shadowPitch;
5090 +
5091 +    while(num--) {
5092 +       width = pbox->x2 - pbox->x1;
5093 +       y1 = pbox->y1 & ~3;
5094 +       y2 = (pbox->y2 + 3) & ~3;
5095 +       height = (y2 - y1) >> 2;  /* in dwords */
5096 +
5097 +       if(pI830->rotate == 1) {
5098 +           dstPtr = pI830->FbBase + 
5099 +                       (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
5100 +           srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
5101 +       } else {
5102 +           dstPtr = pI830->FbBase + 
5103 +                       ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
5104 +           srcPtr = pI830->shadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
5105 +       }
5106 +
5107 +       while(width--) {
5108 +           src = srcPtr;
5109 +           dst = (CARD32*)dstPtr;
5110 +           count = height;
5111 +           while(count--) {
5112 +               *(dst++) = src[0] | (src[srcPitch] << 8) | 
5113 +                                       (src[srcPitch * 2] << 16) | 
5114 +                                       (src[srcPitch * 3] << 24);
5115 +               src += srcPitch * 4;
5116 +           }
5117 +           srcPtr += pI830->rotate;
5118 +           dstPtr += dstPitch;
5119 +       }
5120 +
5121 +       pbox++;
5122 +    }
5123 +} 
5124 +
5125 +
5126 +void
5127 +I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
5128 +{
5129 +    I830Ptr pI830 = I830PTR(pScrn);
5130 +    int count, width, height, y1, y2, dstPitch, srcPitch;
5131 +    CARD16 *dstPtr, *srcPtr, *src;
5132 +    CARD32 *dst;
5133 +
5134 +    dstPitch = pScrn->displayWidth;
5135 +    srcPitch = -pI830->rotate * pI830->shadowPitch >> 1;
5136 +
5137 +    while(num--) {
5138 +       width = pbox->x2 - pbox->x1;
5139 +       y1 = pbox->y1 & ~1;
5140 +       y2 = (pbox->y2 + 1) & ~1;
5141 +       height = (y2 - y1) >> 1;  /* in dwords */
5142 +
5143 +       if(pI830->rotate == 1) {
5144 +           dstPtr = (CARD16*)pI830->FbBase + 
5145 +                       (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
5146 +           srcPtr = (CARD16*)pI830->shadowPtr + 
5147 +                       ((1 - y2) * srcPitch) + pbox->x1;
5148 +       } else {
5149 +           dstPtr = (CARD16*)pI830->FbBase + 
5150 +                       ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
5151 +           srcPtr = (CARD16*)pI830->shadowPtr + 
5152 +                       (y1 * srcPitch) + pbox->x2 - 1;
5153 +       }
5154 +
5155 +       while(width--) {
5156 +           src = srcPtr;
5157 +           dst = (CARD32*)dstPtr;
5158 +           count = height;
5159 +           while(count--) {
5160 +               *(dst++) = src[0] | (src[srcPitch] << 16);
5161 +               src += srcPitch * 2;
5162 +           }
5163 +           srcPtr += pI830->rotate;
5164 +           dstPtr += dstPitch;
5165 +       }
5166 +
5167 +       pbox++;
5168 +    }
5169 +}
5170 +
5171 +
5172 +/* this one could be faster */
5173 +void
5174 +I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
5175 +{
5176 +    I830Ptr pI830 = I830PTR(pScrn);
5177 +    int count, width, height, y1, y2, dstPitch, srcPitch;
5178 +    CARD8 *dstPtr, *srcPtr, *src;
5179 +    CARD32 *dst;
5180 +
5181 +    dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
5182 +    srcPitch = -pI830->rotate * pI830->shadowPitch;
5183 +
5184 +    while(num--) {
5185 +        width = pbox->x2 - pbox->x1;
5186 +        y1 = pbox->y1 & ~3;
5187 +        y2 = (pbox->y2 + 3) & ~3;
5188 +        height = (y2 - y1) >> 2;  /* blocks of 3 dwords */
5189 +
5190 +       if(pI830->rotate == 1) {
5191 +           dstPtr = pI830->FbBase + 
5192 +                       (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
5193 +           srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
5194 +       } else {
5195 +           dstPtr = pI830->FbBase + 
5196 +                       ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
5197 +           srcPtr = pI830->shadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
5198 +       }
5199 +
5200 +       while(width--) {
5201 +           src = srcPtr;
5202 +           dst = (CARD32*)dstPtr;
5203 +           count = height;
5204 +           while(count--) {
5205 +               dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
5206 +                               (src[srcPitch] << 24);          
5207 +               dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
5208 +                               (src[srcPitch * 2] << 16) |
5209 +                               (src[(srcPitch * 2) + 1] << 24);                
5210 +               dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
5211 +                               (src[(srcPitch * 3) + 1] << 16) |
5212 +                               (src[(srcPitch * 3) + 2] << 24);        
5213 +               dst += 3;
5214 +               src += srcPitch * 4;
5215 +           }
5216 +           srcPtr += pI830->rotate * 3;
5217 +           dstPtr += dstPitch; 
5218 +       }
5219 +
5220 +       pbox++;
5221 +    }
5222 +}
5223 +
5224 +void
5225 +I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
5226 +{
5227 +    I830Ptr pI830 = I830PTR(pScrn);
5228 +    int count, width, height, dstPitch, srcPitch;
5229 +    CARD32 *dstPtr, *srcPtr, *src, *dst;
5230 +
5231 +    dstPitch = pScrn->displayWidth;
5232 +    srcPitch = -pI830->rotate * pI830->shadowPitch >> 2;
5233 +
5234 +    while(num--) {
5235 +       width = pbox->x2 - pbox->x1;
5236 +       height = pbox->y2 - pbox->y1;
5237 +
5238 +       if(pI830->rotate == 1) {
5239 +           dstPtr = (CARD32*)pI830->FbBase + 
5240 +                       (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
5241 +           srcPtr = (CARD32*)pI830->shadowPtr + 
5242 +                       ((1 - pbox->y2) * srcPitch) + pbox->x1;
5243 +       } else {
5244 +           dstPtr = (CARD32*)pI830->FbBase + 
5245 +                       ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
5246 +           srcPtr = (CARD32*)pI830->shadowPtr + 
5247 +                       (pbox->y1 * srcPitch) + pbox->x2 - 1;
5248 +       }
5249 +
5250 +       while(width--) {
5251 +           src = srcPtr;
5252 +           dst = dstPtr;
5253 +           count = height;
5254 +           while(count--) {
5255 +               *(dst++) = *src;
5256 +               src += srcPitch;
5257 +           }
5258 +           srcPtr += pI830->rotate;
5259 +           dstPtr += dstPitch;
5260 +       }
5261 +
5262 +       pbox++;
5263 +    }
5264 +}
This page took 0.777945 seconds and 3 git commands to generate.