Initial code release
[adaptation/xorg-x11-drv-intel.git] / src / intel_driver.c
1 /**************************************************************************
2
3 Copyright 2001 VA Linux Systems Inc., Fremont, California.
4 Copyright © 2002 by David Dawes
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30  * Authors: Jeff Hartmann <jhartmann@valinux.com>
31  *          Abraham van der Merwe <abraham@2d3d.co.za>
32  *          David Dawes <dawes@xfree86.org>
33  *          Alan Hourihane <alanh@tungstengraphics.com>
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <assert.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <errno.h>
47
48 #include "xf86.h"
49 #include "xf86_OSproc.h"
50 #include "xf86Priv.h"
51 #include "xf86cmap.h"
52 #include "compiler.h"
53 #include "mibstore.h"
54 #include "vgaHW.h"
55 #include "mipointer.h"
56 #include "micmap.h"
57 #include "shadowfb.h"
58 #include <X11/extensions/randr.h>
59 #include "fb.h"
60 #include "miscstruct.h"
61 #include "dixstruct.h"
62 #include "xf86xv.h"
63 #include <X11/extensions/Xv.h>
64 #include "shadow.h"
65 #include "intel.h"
66 #include "intel_video.h"
67
68 #ifdef INTEL_XVMC
69 #define _INTEL_XVMC_SERVER_
70 #include "intel_hwmc.h"
71 #endif
72
73 #include "legacy/legacy.h"
74
75 #include <sys/ioctl.h>
76 #include "i915_drm.h"
77 #include <xf86drmMode.h>
78
79 /* *INDENT-OFF* */
80 /*
81  * Note: "ColorKey" is provided for compatibility with the i810 driver.
82  * However, the correct option name is "VideoKey".  "ColorKey" usually
83  * refers to the tranparency key for 8+24 overlays, not for video overlays.
84  */
85
86 typedef enum {
87    OPTION_ACCELMETHOD,
88    OPTION_DRI,
89    OPTION_VIDEO_KEY,
90    OPTION_COLOR_KEY,
91    OPTION_FALLBACKDEBUG,
92    OPTION_TILING_FB,
93    OPTION_TILING_2D,
94    OPTION_SHADOW,
95    OPTION_SWAPBUFFERS_WAIT,
96 #ifdef INTEL_XVMC
97    OPTION_XVMC,
98 #endif
99    OPTION_PREFER_OVERLAY,
100    OPTION_DEBUG_FLUSH_BATCHES,
101    OPTION_DEBUG_FLUSH_CACHES,
102    OPTION_DEBUG_WAIT,
103    OPTION_HOTPLUG,
104    OPTION_RELAXED_FENCING,
105 } I830Opts;
106
107 static OptionInfoRec I830Options[] = {
108    {OPTION_ACCELMETHOD, "AccelMethod",  OPTV_ANYSTR,    {0},    FALSE},
109    {OPTION_DRI,         "DRI",          OPTV_BOOLEAN,   {0},    TRUE},
110    {OPTION_COLOR_KEY,   "ColorKey",     OPTV_INTEGER,   {0},    FALSE},
111    {OPTION_VIDEO_KEY,   "VideoKey",     OPTV_INTEGER,   {0},    FALSE},
112    {OPTION_FALLBACKDEBUG, "FallbackDebug", OPTV_BOOLEAN, {0},   FALSE},
113    {OPTION_TILING_2D,   "Tiling",       OPTV_BOOLEAN,   {0},    TRUE},
114    {OPTION_TILING_FB,   "LinearFramebuffer",    OPTV_BOOLEAN,   {0},    FALSE},
115    {OPTION_SHADOW,      "Shadow",       OPTV_BOOLEAN,   {0},    FALSE},
116    {OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN,   {0},    TRUE},
117 #ifdef INTEL_XVMC
118    {OPTION_XVMC,        "XvMC",         OPTV_BOOLEAN,   {0},    TRUE},
119 #endif
120    {OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, FALSE},
121    {OPTION_DEBUG_FLUSH_BATCHES, "DebugFlushBatches", OPTV_BOOLEAN, {0}, FALSE},
122    {OPTION_DEBUG_FLUSH_CACHES, "DebugFlushCaches", OPTV_BOOLEAN, {0}, FALSE},
123    {OPTION_DEBUG_WAIT, "DebugWait", OPTV_BOOLEAN, {0}, FALSE},
124    {OPTION_HOTPLUG,     "HotPlug",      OPTV_BOOLEAN,   {0},    TRUE},
125    {OPTION_RELAXED_FENCING,     "RelaxedFencing",       OPTV_BOOLEAN,   {0},    TRUE},
126    {-1,                 NULL,           OPTV_NONE,      {0},    FALSE}
127 };
128 /* *INDENT-ON* */
129
130 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags);
131 static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen);
132 static Bool I830EnterVT(int scrnIndex, int flags);
133
134 /* temporary */
135 extern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y);
136
137 #ifdef I830DEBUG
138 void
139 I830DPRINTF(const char *filename, int line, const char *function,
140             const char *fmt, ...)
141 {
142         va_list ap;
143
144         ErrorF("\n##############################################\n"
145                "*** In function %s, on line %d, in file %s ***\n",
146                function, line, filename);
147         va_start(ap, fmt);
148         VErrorF(fmt, ap);
149         va_end(ap);
150         ErrorF("##############################################\n\n");
151 }
152 #endif /* #ifdef I830DEBUG */
153
154 /* Export I830 options to i830 driver where necessary */
155 const OptionInfoRec *intel_uxa_available_options(int chipid, int busid)
156 {
157         return I830Options;
158 }
159
160 static void
161 I830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices,
162                 LOCO * colors, VisualPtr pVisual)
163 {
164         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
165         int i, j, index;
166         int p;
167         uint16_t lut_r[256], lut_g[256], lut_b[256];
168
169         DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
170
171         for (p = 0; p < xf86_config->num_crtc; p++) {
172                 xf86CrtcPtr crtc = xf86_config->crtc[p];
173
174                 switch (scrn->depth) {
175                 case 15:
176                         for (i = 0; i < numColors; i++) {
177                                 index = indices[i];
178                                 for (j = 0; j < 8; j++) {
179                                         lut_r[index * 8 + j] =
180                                             colors[index].red << 8;
181                                         lut_g[index * 8 + j] =
182                                             colors[index].green << 8;
183                                         lut_b[index * 8 + j] =
184                                             colors[index].blue << 8;
185                                 }
186                         }
187                         break;
188                 case 16:
189                         for (i = 0; i < numColors; i++) {
190                                 index = indices[i];
191
192                                 if (index <= 31) {
193                                         for (j = 0; j < 8; j++) {
194                                                 lut_r[index * 8 + j] =
195                                                     colors[index].red << 8;
196                                                 lut_b[index * 8 + j] =
197                                                     colors[index].blue << 8;
198                                         }
199                                 }
200
201                                 for (j = 0; j < 4; j++) {
202                                         lut_g[index * 4 + j] =
203                                             colors[index].green << 8;
204                                 }
205                         }
206                         break;
207                 default:
208                         for (i = 0; i < numColors; i++) {
209                                 index = indices[i];
210                                 lut_r[index] = colors[index].red << 8;
211                                 lut_g[index] = colors[index].green << 8;
212                                 lut_b[index] = colors[index].blue << 8;
213                         }
214                         break;
215                 }
216
217                 /* Make the change through RandR */
218 #ifdef RANDR_12_INTERFACE
219                 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
220 #else
221                 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
222 #endif
223         }
224 }
225
226 /**
227  * Adjust the screen pixmap for the current location of the front buffer.
228  * This is done at EnterVT when buffers are bound as long as the resources
229  * have already been created, but the first EnterVT happens before
230  * CreateScreenResources.
231  */
232 static Bool i830CreateScreenResources(ScreenPtr screen)
233 {
234         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
235         intel_screen_private *intel = intel_get_screen_private(scrn);
236
237         screen->CreateScreenResources = intel->CreateScreenResources;
238         if (!(*screen->CreateScreenResources) (screen))
239                 return FALSE;
240
241         return intel_uxa_create_screen_resources(screen);
242 }
243
244 static void PreInitCleanup(ScrnInfoPtr scrn)
245 {
246         if (!scrn || !scrn->driverPrivate)
247                 return;
248
249         free(scrn->driverPrivate);
250         scrn->driverPrivate = NULL;
251 }
252
253 static void intel_check_chipset_option(ScrnInfoPtr scrn)
254 {
255         intel_screen_private *intel = intel_get_screen_private(scrn);
256         MessageType from = X_PROBED;
257
258         intel_detect_chipset(scrn,
259                              intel->PciInfo,
260                              &intel->chipset);
261
262         /* Set the Chipset and ChipRev, allowing config file entries to override. */
263         if (intel->pEnt->device->chipset && *intel->pEnt->device->chipset) {
264                 scrn->chipset = intel->pEnt->device->chipset;
265                 from = X_CONFIG;
266         } else if (intel->pEnt->device->chipID >= 0) {
267                 scrn->chipset = (char *)xf86TokenToString(intel_chipsets,
268                                                            intel->pEnt->device->chipID);
269                 from = X_CONFIG;
270                 xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
271                            "ChipID override: 0x%04X\n",
272                            intel->pEnt->device->chipID);
273                 DEVICE_ID(intel->PciInfo) = intel->pEnt->device->chipID;
274         } else {
275                 from = X_PROBED;
276                 scrn->chipset = (char *)xf86TokenToString(intel_chipsets,
277                                                            DEVICE_ID(intel->PciInfo));
278         }
279
280         if (intel->pEnt->device->chipRev >= 0) {
281                 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
282                            intel->pEnt->device->chipRev);
283         }
284
285         xf86DrvMsg(scrn->scrnIndex, from, "Chipset: \"%s\"\n",
286                    (scrn->chipset != NULL) ? scrn->chipset : "Unknown i8xx");
287 }
288
289 static Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
290 {
291         intel_screen_private *intel = intel_get_screen_private(scrn);
292
293         /* Process the options */
294         xf86CollectOptions(scrn, NULL);
295         if (!(intel->Options = malloc(sizeof(I830Options))))
296                 return FALSE;
297         memcpy(intel->Options, I830Options, sizeof(I830Options));
298         xf86ProcessOptions(scrn->scrnIndex, scrn->options, intel->Options);
299
300         intel->fallback_debug = xf86ReturnOptValBool(intel->Options,
301                                                      OPTION_FALLBACKDEBUG,
302                                                      FALSE);
303
304         intel->debug_flush = 0;
305
306         if (xf86ReturnOptValBool(intel->Options,
307                                  OPTION_DEBUG_FLUSH_BATCHES,
308                                  FALSE))
309                 intel->debug_flush |= DEBUG_FLUSH_BATCHES;
310
311         if (xf86ReturnOptValBool(intel->Options,
312                                  OPTION_DEBUG_FLUSH_CACHES,
313                                  FALSE))
314                 intel->debug_flush |= DEBUG_FLUSH_CACHES;
315
316         if (xf86ReturnOptValBool(intel->Options,
317                                  OPTION_DEBUG_WAIT,
318                                  FALSE))
319                 intel->debug_flush |= DEBUG_FLUSH_WAIT;
320
321         return TRUE;
322 }
323
324 static void intel_check_dri_option(ScrnInfoPtr scrn)
325 {
326         intel_screen_private *intel = intel_get_screen_private(scrn);
327         intel->directRenderingType = DRI_NONE;
328         if (!xf86ReturnOptValBool(intel->Options, OPTION_DRI, TRUE))
329                 intel->directRenderingType = DRI_DISABLED;
330
331         if (scrn->depth != 16 && scrn->depth != 24) {
332                 xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
333                            "DRI is disabled because it "
334                            "runs only at depths 16 and 24.\n");
335                 intel->directRenderingType = DRI_DISABLED;
336         }
337 }
338
339 static Bool intel_open_drm_master(ScrnInfoPtr scrn)
340 {
341         intel_screen_private *intel = intel_get_screen_private(scrn);
342         struct pci_device *dev = intel->PciInfo;
343         drmSetVersion sv;
344         struct drm_i915_getparam gp;
345         int err, has_gem;
346         char busid[20];
347
348         snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
349                  dev->domain, dev->bus, dev->dev, dev->func);
350
351         intel->drmSubFD = drmOpen("i915", busid);
352         if (intel->drmSubFD == -1) {
353                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
354                            "[drm] Failed to open DRM device for %s: %s\n",
355                            busid, strerror(errno));
356                 return FALSE;
357         }
358
359         /* Check that what we opened was a master or a master-capable FD,
360          * by setting the version of the interface we'll use to talk to it.
361          * (see DRIOpenDRMMaster() in DRI1)
362          */
363         sv.drm_di_major = 1;
364         sv.drm_di_minor = 1;
365         sv.drm_dd_major = -1;
366         sv.drm_dd_minor = -1;
367         err = drmSetInterfaceVersion(intel->drmSubFD, &sv);
368         if (err != 0) {
369                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
370                            "[drm] failed to set drm interface version.\n");
371                 drmClose(intel->drmSubFD);
372                 intel->drmSubFD = -1;
373                 return FALSE;
374         }
375
376         has_gem = FALSE;
377         gp.param = I915_PARAM_HAS_GEM;
378         gp.value = &has_gem;
379         (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM,
380                                   &gp, sizeof(gp));
381         if (!has_gem) {
382                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
383                            "[drm] Failed to detect GEM.  Kernel 2.6.28 required.\n");
384                 drmClose(intel->drmSubFD);
385                 intel->drmSubFD = -1;
386                 return FALSE;
387         }
388
389         return TRUE;
390 }
391
392 static void intel_close_drm_master(intel_screen_private *intel)
393 {
394         if (intel && intel->drmSubFD > 0) {
395                 drmClose(intel->drmSubFD);
396                 intel->drmSubFD = -1;
397         }
398 }
399
400 static int intel_init_bufmgr(intel_screen_private *intel)
401 {
402         int batch_size;
403
404         batch_size = 4096 * 4;
405         if (IS_I865G(intel))
406                 /* The 865 has issues with larger-than-page-sized batch buffers. */
407                 batch_size = 4096;
408
409         intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
410         if (!intel->bufmgr)
411                 return FALSE;
412
413         drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
414         drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
415
416         list_init(&intel->batch_pixmaps);
417         list_init(&intel->flush_pixmaps);
418         list_init(&intel->in_flight);
419
420         return TRUE;
421 }
422
423 static void intel_bufmgr_fini(intel_screen_private *intel)
424 {
425         drm_intel_bufmgr_destroy(intel->bufmgr);
426 }
427
428 static void I830XvInit(ScrnInfoPtr scrn)
429 {
430         intel_screen_private *intel = intel_get_screen_private(scrn);
431         MessageType from = X_PROBED;
432
433         intel->XvPreferOverlay =
434             xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE);
435
436         if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY,
437                                  &(intel->colorKey))) {
438                 from = X_CONFIG;
439         } else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY,
440                                         &(intel->colorKey))) {
441                 from = X_CONFIG;
442         } else {
443                 intel->colorKey =
444                     (1 << scrn->offset.red) | (1 << scrn->offset.green) |
445                     (((scrn->mask.blue >> scrn->offset.blue) - 1) <<
446                      scrn->offset.blue);
447                 from = X_DEFAULT;
448         }
449         xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n",
450                    intel->colorKey);
451 }
452
453 static Bool drm_has_boolean_param(struct intel_screen_private *intel,
454                                   int param)
455 {
456         drm_i915_getparam_t gp;
457         int value;
458
459         gp.value = &value;
460         gp.param = param;
461         if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
462                 return FALSE;
463
464         return value;
465 }
466
467 static Bool has_kernel_flush(struct intel_screen_private *intel)
468 {
469         /* The BLT ring was introduced at the same time as the
470          * automatic flush for the busy-ioctl.
471          */
472         return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT);
473 }
474
475 static Bool has_relaxed_fencing(struct intel_screen_private *intel)
476 {
477         return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
478 }
479
480 static Bool can_accelerate_blt(struct intel_screen_private *intel)
481 {
482         if (0 && (IS_I830(intel) || IS_845G(intel))) {
483                 /* These pair of i8xx chipsets have a crippling erratum
484                  * that prevents the use of a PTE entry by the BLT
485                  * engine immediately following updating that
486                  * entry in the GATT.
487                  *
488                  * As the BLT is fundamental to our 2D acceleration,
489                  * and the workaround is lost in the midst of time,
490                  * fallback.
491                  *
492                  * XXX disabled for release as causes regressions in GL.
493                  */
494                 return FALSE;
495         }
496
497         if (INTEL_INFO(intel)->gen >= 60) {
498                 drm_i915_getparam_t gp;
499                 int value;
500
501                 /* On Sandybridge we need the BLT in order to do anything since
502                  * it so frequently used in the acceleration code paths.
503                  */
504                 gp.value = &value;
505                 gp.param = I915_PARAM_HAS_BLT;
506                 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
507                         return FALSE;
508         }
509
510         if (INTEL_INFO(intel)->gen == 60) {
511                 struct pci_device *const device = intel->PciInfo;
512
513                 /* Sandybridge rev07 locks up easily, even with the
514                  * BLT ring workaround in place.
515                  * Thus use shadowfb by default.
516                  */
517                 if (device->revision < 8)
518                     return FALSE;
519         }
520
521         return TRUE;
522 }
523
524 /**
525  * This is called before ScreenInit to do any require probing of screen
526  * configuration.
527  *
528  * This code generally covers probing, module loading, option handling
529  * card mapping, and RandR setup.
530  *
531  * Since xf86InitialConfiguration ends up requiring that we set video modes
532  * in order to detect configuration, we end up having to do a lot of driver
533  * setup (talking to the DRM, mapping the device, etc.) in this function.
534  * As a result, we want to set up that server initialization once rather
535  * that doing it per generation.
536  */
537 static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
538 {
539         intel_screen_private *intel;
540         rgb defaultWeight = { 0, 0, 0 };
541         EntityInfoPtr pEnt;
542         int flags24;
543         Gamma zeros = { 0.0, 0.0, 0.0 };
544
545         if (scrn->numEntities != 1)
546                 return FALSE;
547
548         pEnt = xf86GetEntityInfo(scrn->entityList[0]);
549
550         if (flags & PROBE_DETECT)
551                 return TRUE;
552
553         intel = intel_get_screen_private(scrn);
554         if (intel == NULL) {
555                 intel = xnfcalloc(sizeof(intel_screen_private), 1);
556                 if (intel == NULL)
557                         return FALSE;
558
559                 scrn->driverPrivate = intel;
560         }
561         intel->scrn = scrn;
562         intel->pEnt = pEnt;
563
564         scrn->displayWidth = 640;       /* default it */
565
566         if (intel->pEnt->location.type != BUS_PCI)
567                 return FALSE;
568
569         intel->PciInfo = xf86GetPciInfoForEntity(intel->pEnt->index);
570
571         if (!intel_open_drm_master(scrn))
572                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
573                            "Failed to become DRM master.\n");
574
575         scrn->monitor = scrn->confScreen->monitor;
576         scrn->progClock = TRUE;
577         scrn->rgbBits = 8;
578
579         flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
580
581         if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24))
582                 return FALSE;
583
584         switch (scrn->depth) {
585         case 8:
586         case 15:
587         case 16:
588         case 24:
589                 break;
590         default:
591                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
592                            "Given depth (%d) is not supported by I830 driver\n",
593                            scrn->depth);
594                 return FALSE;
595         }
596         xf86PrintDepthBpp(scrn);
597
598         if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
599                 return FALSE;
600         if (!xf86SetDefaultVisual(scrn, -1))
601                 return FALSE;
602
603         intel->cpp = scrn->bitsPerPixel / 8;
604
605         if (!I830GetEarlyOptions(scrn))
606                 return FALSE;
607
608         intel_check_chipset_option(scrn);
609         intel_check_dri_option(scrn);
610
611         if (!intel_init_bufmgr(intel)) {
612                 PreInitCleanup(scrn);
613                 return FALSE;
614         }
615
616         intel->force_fallback =
617                 drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0;
618
619         /* Enable tiling by default */
620         intel->tiling = INTEL_TILING_ALL;
621
622         /* Allow user override if they set a value */
623         if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE))
624                 intel->tiling &= ~INTEL_TILING_2D;
625         if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE))
626                 intel->tiling &= ~INTEL_TILING_FB;
627
628         intel->can_blt = can_accelerate_blt(intel);
629         intel->has_kernel_flush = has_kernel_flush(intel);
630         intel->use_shadow = !intel->can_blt;
631
632         if (xf86IsOptionSet(intel->Options, OPTION_SHADOW)) {
633                 intel->use_shadow =
634                         xf86ReturnOptValBool(intel->Options,
635                                              OPTION_SHADOW,
636                                              FALSE);
637         }
638
639         if (intel->use_shadow) {
640                 xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
641                            "Shadow buffer enabled,"
642                            " 2D GPU acceleration disabled.\n");
643         }
644
645         intel->has_relaxed_fencing =
646                 xf86ReturnOptValBool(intel->Options,
647                                      OPTION_RELAXED_FENCING,
648                                      INTEL_INFO(intel)->gen >= 33);
649         /* And override the user if there is no kernel support */
650         if (intel->has_relaxed_fencing)
651                 intel->has_relaxed_fencing = has_relaxed_fencing(intel);
652
653         xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
654                    "Relaxed fencing %s\n",
655                    intel->has_relaxed_fencing ? "enabled" : "disabled");
656
657         /* SwapBuffers delays to avoid tearing */
658         intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options,
659                                                        OPTION_SWAPBUFFERS_WAIT,
660                                                        TRUE);
661         if (IS_GEN6(intel))
662                 intel->swapbuffers_wait = FALSE;
663
664         xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n",
665                    intel->tiling & INTEL_TILING_FB ? "tiled" : "linear");
666         xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n",
667                    intel->tiling & INTEL_TILING_2D ? "tiled" : "linear");
668         xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n",
669                    intel->tiling & INTEL_TILING_3D ? "tiled" : "linear");
670         xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n",
671                    intel->swapbuffers_wait ? "en" : "dis");
672
673         I830XvInit(scrn);
674
675         if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
676                 PreInitCleanup(scrn);
677                 return FALSE;
678         }
679
680         if (!xf86SetGamma(scrn, zeros)) {
681                 PreInitCleanup(scrn);
682                 return FALSE;
683         }
684
685         if (scrn->modes == NULL) {
686                 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n");
687                 PreInitCleanup(scrn);
688                 return FALSE;
689         }
690         scrn->currentMode = scrn->modes;
691
692         /* Set display resolution */
693         xf86SetDpi(scrn, 0, 0);
694
695         /* Load the required sub modules */
696         if (!xf86LoadSubModule(scrn, "fb")) {
697                 PreInitCleanup(scrn);
698                 return FALSE;
699         }
700
701         /* Load the dri2 module if requested. */
702         if (intel->directRenderingType != DRI_DISABLED)
703                 xf86LoadSubModule(scrn, "dri2");
704
705         return TRUE;
706 }
707
708 /**
709  * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
710  *
711  * Some state caching is performed to avoid redundant state emits.  This
712  * function is also responsible for marking the state as clobbered for DRI
713  * clients.
714  */
715 void IntelEmitInvarientState(ScrnInfoPtr scrn)
716 {
717         intel_screen_private *intel = intel_get_screen_private(scrn);
718
719         /* If we've emitted our state since the last clobber by another client,
720          * skip it.
721          */
722         if (intel->last_3d != LAST_3D_OTHER)
723                 return;
724
725         if (IS_GEN2(intel))
726                 I830EmitInvarientState(scrn);
727         else if IS_GEN3(intel)
728                 I915EmitInvarientState(scrn);
729 }
730
731 static void
732 I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
733 {
734         ScreenPtr screen = screenInfo.screens[i];
735         ScrnInfoPtr scrn = xf86Screens[i];
736         intel_screen_private *intel = intel_get_screen_private(scrn);
737
738         screen->BlockHandler = intel->BlockHandler;
739
740         (*screen->BlockHandler) (i, blockData, pTimeout, pReadmask);
741
742         intel->BlockHandler = screen->BlockHandler;
743         screen->BlockHandler = I830BlockHandler;
744
745         intel_uxa_block_handler(intel);
746         intel_video_block_handler(intel);
747 }
748
749 static Bool
750 intel_init_initial_framebuffer(ScrnInfoPtr scrn)
751 {
752         intel_screen_private *intel = intel_get_screen_private(scrn);
753         int width = scrn->virtualX;
754         int height = scrn->virtualY;
755         unsigned long pitch;
756         uint32_t tiling;
757
758         intel->front_buffer = intel_allocate_framebuffer(scrn,
759                                                          width, height,
760                                                          intel->cpp,
761                                                          &pitch,
762                                                          &tiling);
763
764         if (!intel->front_buffer) {
765                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
766                            "Couldn't allocate initial framebuffer.\n");
767                 return FALSE;
768         }
769
770         intel->front_pitch = pitch;
771         intel->front_tiling = tiling;
772         scrn->displayWidth = pitch / intel->cpp;
773
774         return TRUE;
775 }
776
777 Bool intel_crtc_on(xf86CrtcPtr crtc)
778 {
779         ScrnInfoPtr scrn = crtc->scrn;
780         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
781         int i;
782
783         if (!crtc->enabled)
784                 return FALSE;
785
786         /* Kernel manages CRTC status based out output config */
787         for (i = 0; i < xf86_config->num_output; i++) {
788                 xf86OutputPtr output = xf86_config->output[i];
789                 if (output->crtc == crtc &&
790                     intel_output_dpms_status(output) == DPMSModeOn)
791                         return TRUE;
792         }
793
794         return FALSE;
795 }
796
797 static void
798 intel_flush_callback(CallbackListPtr *list,
799                      pointer user_data, pointer call_data)
800 {
801         ScrnInfoPtr scrn = user_data;
802         if (scrn->vtSema)
803                 intel_batch_submit(scrn);
804 }
805
806 #if HAVE_UDEV
807 static void
808 I830HandleUEvents(int fd, void *closure)
809 {
810         ScrnInfoPtr scrn = closure;
811         intel_screen_private *intel = intel_get_screen_private(scrn);
812         struct udev_device *dev;
813         const char *hotplug;
814         struct stat s;
815         dev_t udev_devnum;
816
817         dev = udev_monitor_receive_device(intel->uevent_monitor);
818         if (!dev)
819                 return;
820
821         udev_devnum = udev_device_get_devnum(dev);
822         fstat(intel->drmSubFD, &s);
823         /*
824          * Check to make sure this event is directed at our
825          * device (by comparing dev_t values), then make
826          * sure it's a hotplug event (HOTPLUG=1)
827          */
828
829         hotplug = udev_device_get_property_value(dev, "HOTPLUG");
830
831         if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
832                         hotplug && atoi(hotplug) == 1)
833                 RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
834
835         udev_device_unref(dev);
836 }
837
838 static void
839 I830UeventInit(ScrnInfoPtr scrn)
840 {
841         intel_screen_private *intel = intel_get_screen_private(scrn);
842         struct udev *u;
843         struct udev_monitor *mon;
844         Bool hotplug;
845         MessageType from = X_CONFIG;
846
847         if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
848                 from = X_DEFAULT;
849                 hotplug = TRUE;
850         }
851
852         xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
853                         hotplug ? "enabled" : "disabled");
854         if (!hotplug)
855                 return;
856
857         u = udev_new();
858         if (!u)
859                 return;
860
861         mon = udev_monitor_new_from_netlink(u, "udev");
862
863         if (!mon) {
864                 udev_unref(u);
865                 return;
866         }
867
868         if (udev_monitor_filter_add_match_subsystem_devtype(mon,
869                                 "drm",
870                                 "drm_minor") < 0 ||
871                         udev_monitor_enable_receiving(mon) < 0)
872         {
873                 udev_monitor_unref(mon);
874                 udev_unref(u);
875                 return;
876         }
877
878         intel->uevent_handler =
879                 xf86AddGeneralHandler(udev_monitor_get_fd(mon),
880                                 I830HandleUEvents,
881                                 scrn);
882         if (!intel->uevent_handler) {
883                 udev_monitor_unref(mon);
884                 udev_unref(u);
885                 return;
886         }
887
888         intel->uevent_monitor = mon;
889 }
890
891 static void
892 I830UeventFini(ScrnInfoPtr scrn)
893 {
894         intel_screen_private *intel = intel_get_screen_private(scrn);
895
896         if (intel->uevent_handler) {
897                 struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
898
899                 xf86RemoveGeneralHandler(intel->uevent_handler);
900
901                 udev_monitor_unref(intel->uevent_monitor);
902                 udev_unref(u);
903                 intel->uevent_handler = NULL;
904                 intel->uevent_monitor = NULL;
905         }
906 }
907 #endif /* HAVE_UDEV */
908
909 static Bool
910 I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
911 {
912         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
913         intel_screen_private *intel = intel_get_screen_private(scrn);
914         VisualPtr visual;
915 #ifdef INTEL_XVMC
916         MessageType from;
917 #endif
918         struct pci_device *const device = intel->PciInfo;
919         int fb_bar = IS_GEN2(intel) ? 0 : 2;
920
921         scrn->videoRam = device->regions[fb_bar].size / 1024;
922
923         intel->last_3d = LAST_3D_OTHER;
924         intel->overlayOn = FALSE;
925
926         /*
927          * Set this so that the overlay allocation is factored in when
928          * appropriate.
929          */
930         intel->XvEnabled = TRUE;
931
932 #ifdef DRI2
933         if (intel->directRenderingType == DRI_NONE
934             && I830DRI2ScreenInit(screen))
935                 intel->directRenderingType = DRI_DRI2;
936 #endif
937
938         if (!intel_init_initial_framebuffer(scrn))
939                 return FALSE;
940
941         intel_batch_init(scrn);
942
943         if (INTEL_INFO(intel)->gen >= 40)
944                 gen4_render_state_init(scrn);
945
946         miClearVisualTypes();
947         if (!miSetVisualTypes(scrn->depth,
948                               miGetDefaultVisualMask(scrn->depth),
949                               scrn->rgbBits, scrn->defaultVisual))
950                 return FALSE;
951         if (!miSetPixmapDepths())
952                 return FALSE;
953
954         DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
955
956         DPRINTF(PFX, "assert( if(!fbScreenInit(screen, ...) )\n");
957         if (!fbScreenInit(screen, NULL,
958                           scrn->virtualX, scrn->virtualY,
959                           scrn->xDpi, scrn->yDpi,
960                           scrn->displayWidth, scrn->bitsPerPixel))
961                 return FALSE;
962
963         if (scrn->bitsPerPixel > 8) {
964                 /* Fixup RGB ordering */
965                 visual = screen->visuals + screen->numVisuals;
966                 while (--visual >= screen->visuals) {
967                         if ((visual->class | DynamicClass) == DirectColor) {
968                                 visual->offsetRed = scrn->offset.red;
969                                 visual->offsetGreen = scrn->offset.green;
970                                 visual->offsetBlue = scrn->offset.blue;
971                                 visual->redMask = scrn->mask.red;
972                                 visual->greenMask = scrn->mask.green;
973                                 visual->blueMask = scrn->mask.blue;
974                         }
975                 }
976         }
977
978         fbPictureInit(screen, NULL, 0);
979
980         xf86SetBlackWhitePixels(screen);
981
982         if (!intel_uxa_init(screen)) {
983                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
984                            "Hardware acceleration initialization failed\n");
985                 return FALSE;
986         }
987
988         miInitializeBackingStore(screen);
989         xf86SetBackingStore(screen);
990         xf86SetSilkenMouse(screen);
991         miDCInitialize(screen, xf86GetPointerScreenFuncs());
992
993         xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
994         if (!xf86_cursors_init(screen, I810_CURSOR_X, I810_CURSOR_Y,
995                                (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
996                                 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
997                                 HARDWARE_CURSOR_INVERT_MASK |
998                                 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
999                                 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1000                                 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
1001                                 HARDWARE_CURSOR_UPDATE_UNHIDDEN |
1002                                 HARDWARE_CURSOR_ARGB))) {
1003                 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1004                            "Hardware cursor initialization failed\n");
1005         }
1006
1007         /* Must force it before EnterVT, so we are in control of VT and
1008          * later memory should be bound when allocating, e.g rotate_mem */
1009         scrn->vtSema = TRUE;
1010
1011         if (!I830EnterVT(scrnIndex, 0))
1012                 return FALSE;
1013
1014         intel->BlockHandler = screen->BlockHandler;
1015         screen->BlockHandler = I830BlockHandler;
1016
1017         if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
1018                 return FALSE;
1019
1020         screen->SaveScreen = xf86SaveScreen;
1021         intel->CloseScreen = screen->CloseScreen;
1022         screen->CloseScreen = I830CloseScreen;
1023         intel->CreateScreenResources = screen->CreateScreenResources;
1024         screen->CreateScreenResources = i830CreateScreenResources;
1025
1026         if (!xf86CrtcScreenInit(screen))
1027                 return FALSE;
1028
1029         DPRINTF(PFX, "assert( if(!miCreateDefColormap(screen)) )\n");
1030         if (!miCreateDefColormap(screen))
1031                 return FALSE;
1032
1033         DPRINTF(PFX, "assert( if(!xf86HandleColormaps(screen, ...)) )\n");
1034         if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL,
1035                                  CMAP_RELOAD_ON_MODE_SWITCH |
1036                                  CMAP_PALETTED_TRUECOLOR)) {
1037                 return FALSE;
1038         }
1039
1040         xf86DPMSInit(screen, xf86DPMSSet, 0);
1041
1042 #ifdef INTEL_XVMC
1043         if (INTEL_INFO(intel)->gen >= 40)
1044                 intel->XvMCEnabled = TRUE;
1045         from = ((intel->directRenderingType == DRI_DRI2) &&
1046                 xf86GetOptValBool(intel->Options, OPTION_XVMC,
1047                                   &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
1048         xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
1049                    intel->XvMCEnabled ? "en" : "dis");
1050 #endif
1051         /* Init video */
1052         if (intel->XvEnabled)
1053                 I830InitVideo(screen);
1054
1055 #if defined(DRI2)
1056         switch (intel->directRenderingType) {
1057         case DRI_DRI2:
1058                 intel->directRenderingOpen = TRUE;
1059                 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1060                            "direct rendering: DRI2 Enabled\n");
1061                 break;
1062         case DRI_DISABLED:
1063                 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1064                            "direct rendering: Disabled\n");
1065                 break;
1066         case DRI_NONE:
1067                 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1068                            "direct rendering: Failed\n");
1069                 break;
1070         }
1071 #else
1072         xf86DrvMsg(scrn->scrnIndex, X_INFO,
1073                    "direct rendering: Not available\n");
1074 #endif
1075
1076         if (serverGeneration == 1)
1077                 xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1078
1079         intel_mode_init(intel);
1080
1081         intel->suspended = FALSE;
1082
1083 #if HAVE_UDEV
1084         I830UeventInit(scrn);
1085 #endif
1086
1087         return TRUE;
1088 }
1089
1090 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags)
1091 {
1092 }
1093
1094 static void I830FreeScreen(int scrnIndex, int flags)
1095 {
1096         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1097         intel_screen_private *intel = intel_get_screen_private(scrn);
1098
1099         if (intel) {
1100                 intel_mode_fini(intel);
1101                 intel_close_drm_master(intel);
1102                 intel_bufmgr_fini(intel);
1103
1104                 free(intel);
1105                 scrn->driverPrivate = NULL;
1106         }
1107
1108         if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1109                 vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1110 }
1111
1112 static void I830LeaveVT(int scrnIndex, int flags)
1113 {
1114         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1115         intel_screen_private *intel = intel_get_screen_private(scrn);
1116         int ret;
1117
1118         DPRINTF(PFX, "Leave VT\n");
1119
1120         xf86RotateFreeShadow(scrn);
1121
1122         xf86_hide_cursors(scrn);
1123
1124         ret = drmDropMaster(intel->drmSubFD);
1125         if (ret)
1126                 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1127                            "drmDropMaster failed: %s\n", strerror(errno));
1128 }
1129
1130 /*
1131  * This gets called when gaining control of the VT, and from ScreenInit().
1132  */
1133 static Bool I830EnterVT(int scrnIndex, int flags)
1134 {
1135         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1136         intel_screen_private *intel = intel_get_screen_private(scrn);
1137         int ret;
1138
1139         DPRINTF(PFX, "Enter VT\n");
1140
1141         ret = drmSetMaster(intel->drmSubFD);
1142         if (ret) {
1143                 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1144                            "drmSetMaster failed: %s\n",
1145                            strerror(errno));
1146         }
1147
1148         intel_set_gem_max_sizes(scrn);
1149
1150         if (!xf86SetDesiredModes(scrn))
1151                 return FALSE;
1152
1153         return TRUE;
1154 }
1155
1156 static Bool I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1157 {
1158         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1159
1160         return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
1161 }
1162
1163 static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
1164 {
1165         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1166         intel_screen_private *intel = intel_get_screen_private(scrn);
1167
1168 #if HAVE_UDEV
1169         I830UeventFini(scrn);
1170 #endif
1171
1172         if (scrn->vtSema == TRUE) {
1173                 I830LeaveVT(scrnIndex, 0);
1174         }
1175
1176         DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
1177
1178         if (intel->uxa_driver) {
1179                 uxa_driver_fini(screen);
1180                 free(intel->uxa_driver);
1181                 intel->uxa_driver = NULL;
1182         }
1183
1184         if (intel->front_buffer) {
1185                 if (!intel->use_shadow)
1186                         intel_set_pixmap_bo(screen->GetScreenPixmap(screen),
1187                                             NULL);
1188                 intel_mode_remove_fb(intel);
1189                 drm_intel_bo_unreference(intel->front_buffer);
1190                 intel->front_buffer = NULL;
1191         }
1192
1193         if (intel->shadow_buffer) {
1194                 free(intel->shadow_buffer);
1195                 intel->shadow_buffer = NULL;
1196         }
1197
1198         if (intel->shadow_damage) {
1199                 DamageUnregister(&screen->GetScreenPixmap(screen)->drawable,
1200                                  intel->shadow_damage);
1201                 DamageDestroy(intel->shadow_damage);
1202                 intel->shadow_damage = NULL;
1203         }
1204
1205         intel_batch_teardown(scrn);
1206
1207         if (INTEL_INFO(intel)->gen >= 40)
1208                 gen4_render_state_cleanup(scrn);
1209
1210         xf86_cursors_fini(screen);
1211
1212         i965_free_video(scrn);
1213
1214         screen->CloseScreen = intel->CloseScreen;
1215         (*screen->CloseScreen) (scrnIndex, screen);
1216
1217         if (intel->directRenderingOpen
1218             && intel->directRenderingType == DRI_DRI2) {
1219                 intel->directRenderingOpen = FALSE;
1220                 I830DRI2CloseScreen(screen);
1221         }
1222
1223         xf86GARTCloseScreen(scrnIndex);
1224
1225         scrn->vtSema = FALSE;
1226         return TRUE;
1227 }
1228
1229 static ModeStatus
1230 I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1231 {
1232         if (mode->Flags & V_INTERLACE) {
1233                 if (verbose) {
1234                         xf86DrvMsg(scrnIndex, X_PROBED,
1235                                    "Removing interlaced mode \"%s\"\n",
1236                                    mode->name);
1237                 }
1238                 return MODE_BAD;
1239         }
1240         return MODE_OK;
1241 }
1242
1243 #ifndef SUSPEND_SLEEP
1244 #define SUSPEND_SLEEP 0
1245 #endif
1246 #ifndef RESUME_SLEEP
1247 #define RESUME_SLEEP 0
1248 #endif
1249
1250 /*
1251  * This function is only required if we need to do anything differently from
1252  * DoApmEvent() in common/xf86PM.c, including if we want to see events other
1253  * than suspend/resume.
1254  */
1255 static Bool I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
1256 {
1257         ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1258         intel_screen_private *intel = intel_get_screen_private(scrn);
1259
1260         DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event,
1261                 BOOLTOSTRING(undo));
1262
1263         switch (event) {
1264         case XF86_APM_SYS_SUSPEND:
1265         case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */
1266         case XF86_APM_USER_SUSPEND:
1267         case XF86_APM_SYS_STANDBY:
1268         case XF86_APM_USER_STANDBY:
1269                 if (!undo && !intel->suspended) {
1270                         scrn->LeaveVT(scrnIndex, 0);
1271                         intel->suspended = TRUE;
1272                         sleep(SUSPEND_SLEEP);
1273                 } else if (undo && intel->suspended) {
1274                         sleep(RESUME_SLEEP);
1275                         scrn->EnterVT(scrnIndex, 0);
1276                         intel->suspended = FALSE;
1277                 }
1278                 break;
1279         case XF86_APM_STANDBY_RESUME:
1280         case XF86_APM_NORMAL_RESUME:
1281         case XF86_APM_CRITICAL_RESUME:
1282                 if (intel->suspended) {
1283                         sleep(RESUME_SLEEP);
1284                         scrn->EnterVT(scrnIndex, 0);
1285                         intel->suspended = FALSE;
1286                         /*
1287                          * Turn the screen saver off when resuming.  This seems to be
1288                          * needed to stop xscreensaver kicking in (when used).
1289                          *
1290                          * XXX DoApmEvent() should probably call this just like
1291                          * xf86VTSwitch() does.  Maybe do it here only in 4.2
1292                          * compatibility mode.
1293                          */
1294                         SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1295                 }
1296                 break;
1297                 /* This is currently used for ACPI */
1298         case XF86_APM_CAPABILITY_CHANGED:
1299                 ErrorF("I830PMEvent: Capability change\n");
1300
1301                 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1302
1303                 break;
1304         default:
1305                 ErrorF("I830PMEvent: received APM event %d\n", event);
1306         }
1307         return TRUE;
1308 }
1309
1310 void intel_init_scrn(ScrnInfoPtr scrn)
1311 {
1312         scrn->PreInit = I830PreInit;
1313         scrn->ScreenInit = I830ScreenInit;
1314         scrn->SwitchMode = I830SwitchMode;
1315         scrn->AdjustFrame = i830AdjustFrame;
1316         scrn->EnterVT = I830EnterVT;
1317         scrn->LeaveVT = I830LeaveVT;
1318         scrn->FreeScreen = I830FreeScreen;
1319         scrn->ValidMode = I830ValidMode;
1320         scrn->PMEvent = I830PMEvent;
1321 }