1 /**************************************************************************
3 Copyright 2001 VA Linux Systems Inc., Fremont, California.
4 Copyright © 2002 by David Dawes
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:
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
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.
27 **************************************************************************/
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>
49 #include "xf86_OSproc.h"
55 #include "mipointer.h"
58 #include <X11/extensions/randr.h>
60 #include "miscstruct.h"
61 #include "dixstruct.h"
63 #include <X11/extensions/Xv.h>
66 #include "intel_video.h"
69 #define _INTEL_XVMC_SERVER_
70 #include "intel_hwmc.h"
73 #include "legacy/legacy.h"
75 #include <sys/ioctl.h>
77 #include <xf86drmMode.h>
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.
95 OPTION_SWAPBUFFERS_WAIT,
99 OPTION_PREFER_OVERLAY,
100 OPTION_DEBUG_FLUSH_BATCHES,
101 OPTION_DEBUG_FLUSH_CACHES,
104 OPTION_RELAXED_FENCING,
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},
118 {OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, TRUE},
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}
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);
135 extern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y);
139 I830DPRINTF(const char *filename, int line, const char *function,
140 const char *fmt, ...)
144 ErrorF("\n##############################################\n"
145 "*** In function %s, on line %d, in file %s ***\n",
146 function, line, filename);
150 ErrorF("##############################################\n\n");
152 #endif /* #ifdef I830DEBUG */
154 /* Export I830 options to i830 driver where necessary */
155 const OptionInfoRec *intel_uxa_available_options(int chipid, int busid)
161 I830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices,
162 LOCO * colors, VisualPtr pVisual)
164 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
167 uint16_t lut_r[256], lut_g[256], lut_b[256];
169 DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
171 for (p = 0; p < xf86_config->num_crtc; p++) {
172 xf86CrtcPtr crtc = xf86_config->crtc[p];
174 switch (scrn->depth) {
176 for (i = 0; i < numColors; 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;
189 for (i = 0; i < numColors; i++) {
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;
201 for (j = 0; j < 4; j++) {
202 lut_g[index * 4 + j] =
203 colors[index].green << 8;
208 for (i = 0; i < numColors; 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;
217 /* Make the change through RandR */
218 #ifdef RANDR_12_INTERFACE
219 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
221 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
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.
232 static Bool i830CreateScreenResources(ScreenPtr screen)
234 ScrnInfoPtr scrn = xf86Screens[screen->myNum];
235 intel_screen_private *intel = intel_get_screen_private(scrn);
237 screen->CreateScreenResources = intel->CreateScreenResources;
238 if (!(*screen->CreateScreenResources) (screen))
241 return intel_uxa_create_screen_resources(screen);
244 static void PreInitCleanup(ScrnInfoPtr scrn)
246 if (!scrn || !scrn->driverPrivate)
249 free(scrn->driverPrivate);
250 scrn->driverPrivate = NULL;
253 static void intel_check_chipset_option(ScrnInfoPtr scrn)
255 intel_screen_private *intel = intel_get_screen_private(scrn);
256 MessageType from = X_PROBED;
258 intel_detect_chipset(scrn,
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;
266 } else if (intel->pEnt->device->chipID >= 0) {
267 scrn->chipset = (char *)xf86TokenToString(intel_chipsets,
268 intel->pEnt->device->chipID);
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;
276 scrn->chipset = (char *)xf86TokenToString(intel_chipsets,
277 DEVICE_ID(intel->PciInfo));
280 if (intel->pEnt->device->chipRev >= 0) {
281 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
282 intel->pEnt->device->chipRev);
285 xf86DrvMsg(scrn->scrnIndex, from, "Chipset: \"%s\"\n",
286 (scrn->chipset != NULL) ? scrn->chipset : "Unknown i8xx");
289 static Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
291 intel_screen_private *intel = intel_get_screen_private(scrn);
293 /* Process the options */
294 xf86CollectOptions(scrn, NULL);
295 if (!(intel->Options = malloc(sizeof(I830Options))))
297 memcpy(intel->Options, I830Options, sizeof(I830Options));
298 xf86ProcessOptions(scrn->scrnIndex, scrn->options, intel->Options);
300 intel->fallback_debug = xf86ReturnOptValBool(intel->Options,
301 OPTION_FALLBACKDEBUG,
304 intel->debug_flush = 0;
306 if (xf86ReturnOptValBool(intel->Options,
307 OPTION_DEBUG_FLUSH_BATCHES,
309 intel->debug_flush |= DEBUG_FLUSH_BATCHES;
311 if (xf86ReturnOptValBool(intel->Options,
312 OPTION_DEBUG_FLUSH_CACHES,
314 intel->debug_flush |= DEBUG_FLUSH_CACHES;
316 if (xf86ReturnOptValBool(intel->Options,
319 intel->debug_flush |= DEBUG_FLUSH_WAIT;
324 static void intel_check_dri_option(ScrnInfoPtr scrn)
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;
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;
339 static Bool intel_open_drm_master(ScrnInfoPtr scrn)
341 intel_screen_private *intel = intel_get_screen_private(scrn);
342 struct pci_device *dev = intel->PciInfo;
344 struct drm_i915_getparam gp;
348 snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
349 dev->domain, dev->bus, dev->dev, dev->func);
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));
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)
365 sv.drm_dd_major = -1;
366 sv.drm_dd_minor = -1;
367 err = drmSetInterfaceVersion(intel->drmSubFD, &sv);
369 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
370 "[drm] failed to set drm interface version.\n");
371 drmClose(intel->drmSubFD);
372 intel->drmSubFD = -1;
377 gp.param = I915_PARAM_HAS_GEM;
379 (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM,
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;
392 static void intel_close_drm_master(intel_screen_private *intel)
394 if (intel && intel->drmSubFD > 0) {
395 drmClose(intel->drmSubFD);
396 intel->drmSubFD = -1;
400 static int intel_init_bufmgr(intel_screen_private *intel)
404 batch_size = 4096 * 4;
406 /* The 865 has issues with larger-than-page-sized batch buffers. */
409 intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
413 drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
414 drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
416 list_init(&intel->batch_pixmaps);
417 list_init(&intel->flush_pixmaps);
418 list_init(&intel->in_flight);
423 static void intel_bufmgr_fini(intel_screen_private *intel)
425 drm_intel_bufmgr_destroy(intel->bufmgr);
428 static void I830XvInit(ScrnInfoPtr scrn)
430 intel_screen_private *intel = intel_get_screen_private(scrn);
431 MessageType from = X_PROBED;
433 intel->XvPreferOverlay =
434 xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE);
436 if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY,
437 &(intel->colorKey))) {
439 } else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY,
440 &(intel->colorKey))) {
444 (1 << scrn->offset.red) | (1 << scrn->offset.green) |
445 (((scrn->mask.blue >> scrn->offset.blue) - 1) <<
449 xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n",
453 static Bool drm_has_boolean_param(struct intel_screen_private *intel,
456 drm_i915_getparam_t gp;
461 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
467 static Bool has_kernel_flush(struct intel_screen_private *intel)
469 /* The BLT ring was introduced at the same time as the
470 * automatic flush for the busy-ioctl.
472 return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT);
475 static Bool has_relaxed_fencing(struct intel_screen_private *intel)
477 return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
480 static Bool can_accelerate_blt(struct intel_screen_private *intel)
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
488 * As the BLT is fundamental to our 2D acceleration,
489 * and the workaround is lost in the midst of time,
492 * XXX disabled for release as causes regressions in GL.
497 if (INTEL_INFO(intel)->gen >= 60) {
498 drm_i915_getparam_t gp;
501 /* On Sandybridge we need the BLT in order to do anything since
502 * it so frequently used in the acceleration code paths.
505 gp.param = I915_PARAM_HAS_BLT;
506 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
510 if (INTEL_INFO(intel)->gen == 60) {
511 struct pci_device *const device = intel->PciInfo;
513 /* Sandybridge rev07 locks up easily, even with the
514 * BLT ring workaround in place.
515 * Thus use shadowfb by default.
517 if (device->revision < 8)
525 * This is called before ScreenInit to do any require probing of screen
528 * This code generally covers probing, module loading, option handling
529 * card mapping, and RandR setup.
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.
537 static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
539 intel_screen_private *intel;
540 rgb defaultWeight = { 0, 0, 0 };
543 Gamma zeros = { 0.0, 0.0, 0.0 };
545 if (scrn->numEntities != 1)
548 pEnt = xf86GetEntityInfo(scrn->entityList[0]);
550 if (flags & PROBE_DETECT)
553 intel = intel_get_screen_private(scrn);
555 intel = xnfcalloc(sizeof(intel_screen_private), 1);
559 scrn->driverPrivate = intel;
564 scrn->displayWidth = 640; /* default it */
566 if (intel->pEnt->location.type != BUS_PCI)
569 intel->PciInfo = xf86GetPciInfoForEntity(intel->pEnt->index);
571 if (!intel_open_drm_master(scrn))
572 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
573 "Failed to become DRM master.\n");
575 scrn->monitor = scrn->confScreen->monitor;
576 scrn->progClock = TRUE;
579 flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
581 if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24))
584 switch (scrn->depth) {
591 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
592 "Given depth (%d) is not supported by I830 driver\n",
596 xf86PrintDepthBpp(scrn);
598 if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
600 if (!xf86SetDefaultVisual(scrn, -1))
603 intel->cpp = scrn->bitsPerPixel / 8;
605 if (!I830GetEarlyOptions(scrn))
608 intel_check_chipset_option(scrn);
609 intel_check_dri_option(scrn);
611 if (!intel_init_bufmgr(intel)) {
612 PreInitCleanup(scrn);
616 intel->force_fallback =
617 drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0;
619 /* Enable tiling by default */
620 intel->tiling = INTEL_TILING_ALL;
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;
628 intel->can_blt = can_accelerate_blt(intel);
629 intel->has_kernel_flush = has_kernel_flush(intel);
630 intel->use_shadow = !intel->can_blt;
632 if (xf86IsOptionSet(intel->Options, OPTION_SHADOW)) {
634 xf86ReturnOptValBool(intel->Options,
639 if (intel->use_shadow) {
640 xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
641 "Shadow buffer enabled,"
642 " 2D GPU acceleration disabled.\n");
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);
653 xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
654 "Relaxed fencing %s\n",
655 intel->has_relaxed_fencing ? "enabled" : "disabled");
657 /* SwapBuffers delays to avoid tearing */
658 intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options,
659 OPTION_SWAPBUFFERS_WAIT,
662 intel->swapbuffers_wait = FALSE;
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");
675 if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
676 PreInitCleanup(scrn);
680 if (!xf86SetGamma(scrn, zeros)) {
681 PreInitCleanup(scrn);
685 if (scrn->modes == NULL) {
686 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n");
687 PreInitCleanup(scrn);
690 scrn->currentMode = scrn->modes;
692 /* Set display resolution */
693 xf86SetDpi(scrn, 0, 0);
695 /* Load the required sub modules */
696 if (!xf86LoadSubModule(scrn, "fb")) {
697 PreInitCleanup(scrn);
701 /* Load the dri2 module if requested. */
702 if (intel->directRenderingType != DRI_DISABLED)
703 xf86LoadSubModule(scrn, "dri2");
709 * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
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
715 void IntelEmitInvarientState(ScrnInfoPtr scrn)
717 intel_screen_private *intel = intel_get_screen_private(scrn);
719 /* If we've emitted our state since the last clobber by another client,
722 if (intel->last_3d != LAST_3D_OTHER)
726 I830EmitInvarientState(scrn);
727 else if IS_GEN3(intel)
728 I915EmitInvarientState(scrn);
732 I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
734 ScreenPtr screen = screenInfo.screens[i];
735 ScrnInfoPtr scrn = xf86Screens[i];
736 intel_screen_private *intel = intel_get_screen_private(scrn);
738 screen->BlockHandler = intel->BlockHandler;
740 (*screen->BlockHandler) (i, blockData, pTimeout, pReadmask);
742 intel->BlockHandler = screen->BlockHandler;
743 screen->BlockHandler = I830BlockHandler;
745 intel_uxa_block_handler(intel);
746 intel_video_block_handler(intel);
750 intel_init_initial_framebuffer(ScrnInfoPtr scrn)
752 intel_screen_private *intel = intel_get_screen_private(scrn);
753 int width = scrn->virtualX;
754 int height = scrn->virtualY;
758 intel->front_buffer = intel_allocate_framebuffer(scrn,
764 if (!intel->front_buffer) {
765 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
766 "Couldn't allocate initial framebuffer.\n");
770 intel->front_pitch = pitch;
771 intel->front_tiling = tiling;
772 scrn->displayWidth = pitch / intel->cpp;
777 Bool intel_crtc_on(xf86CrtcPtr crtc)
779 ScrnInfoPtr scrn = crtc->scrn;
780 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
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)
798 intel_flush_callback(CallbackListPtr *list,
799 pointer user_data, pointer call_data)
801 ScrnInfoPtr scrn = user_data;
803 intel_batch_submit(scrn);
808 I830HandleUEvents(int fd, void *closure)
810 ScrnInfoPtr scrn = closure;
811 intel_screen_private *intel = intel_get_screen_private(scrn);
812 struct udev_device *dev;
817 dev = udev_monitor_receive_device(intel->uevent_monitor);
821 udev_devnum = udev_device_get_devnum(dev);
822 fstat(intel->drmSubFD, &s);
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)
829 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
831 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
832 hotplug && atoi(hotplug) == 1)
833 RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
835 udev_device_unref(dev);
839 I830UeventInit(ScrnInfoPtr scrn)
841 intel_screen_private *intel = intel_get_screen_private(scrn);
843 struct udev_monitor *mon;
845 MessageType from = X_CONFIG;
847 if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
852 xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
853 hotplug ? "enabled" : "disabled");
861 mon = udev_monitor_new_from_netlink(u, "udev");
868 if (udev_monitor_filter_add_match_subsystem_devtype(mon,
871 udev_monitor_enable_receiving(mon) < 0)
873 udev_monitor_unref(mon);
878 intel->uevent_handler =
879 xf86AddGeneralHandler(udev_monitor_get_fd(mon),
882 if (!intel->uevent_handler) {
883 udev_monitor_unref(mon);
888 intel->uevent_monitor = mon;
892 I830UeventFini(ScrnInfoPtr scrn)
894 intel_screen_private *intel = intel_get_screen_private(scrn);
896 if (intel->uevent_handler) {
897 struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
899 xf86RemoveGeneralHandler(intel->uevent_handler);
901 udev_monitor_unref(intel->uevent_monitor);
903 intel->uevent_handler = NULL;
904 intel->uevent_monitor = NULL;
907 #endif /* HAVE_UDEV */
910 I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
912 ScrnInfoPtr scrn = xf86Screens[screen->myNum];
913 intel_screen_private *intel = intel_get_screen_private(scrn);
918 struct pci_device *const device = intel->PciInfo;
919 int fb_bar = IS_GEN2(intel) ? 0 : 2;
921 scrn->videoRam = device->regions[fb_bar].size / 1024;
923 intel->last_3d = LAST_3D_OTHER;
924 intel->overlayOn = FALSE;
927 * Set this so that the overlay allocation is factored in when
930 intel->XvEnabled = TRUE;
933 if (intel->directRenderingType == DRI_NONE
934 && I830DRI2ScreenInit(screen))
935 intel->directRenderingType = DRI_DRI2;
938 if (!intel_init_initial_framebuffer(scrn))
941 intel_batch_init(scrn);
943 if (INTEL_INFO(intel)->gen >= 40)
944 gen4_render_state_init(scrn);
946 miClearVisualTypes();
947 if (!miSetVisualTypes(scrn->depth,
948 miGetDefaultVisualMask(scrn->depth),
949 scrn->rgbBits, scrn->defaultVisual))
951 if (!miSetPixmapDepths())
954 DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
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))
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;
978 fbPictureInit(screen, NULL, 0);
980 xf86SetBlackWhitePixels(screen);
982 if (!intel_uxa_init(screen)) {
983 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
984 "Hardware acceleration initialization failed\n");
988 miInitializeBackingStore(screen);
989 xf86SetBackingStore(screen);
990 xf86SetSilkenMouse(screen);
991 miDCInitialize(screen, xf86GetPointerScreenFuncs());
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");
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;
1011 if (!I830EnterVT(scrnIndex, 0))
1014 intel->BlockHandler = screen->BlockHandler;
1015 screen->BlockHandler = I830BlockHandler;
1017 if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
1020 screen->SaveScreen = xf86SaveScreen;
1021 intel->CloseScreen = screen->CloseScreen;
1022 screen->CloseScreen = I830CloseScreen;
1023 intel->CreateScreenResources = screen->CreateScreenResources;
1024 screen->CreateScreenResources = i830CreateScreenResources;
1026 if (!xf86CrtcScreenInit(screen))
1029 DPRINTF(PFX, "assert( if(!miCreateDefColormap(screen)) )\n");
1030 if (!miCreateDefColormap(screen))
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)) {
1040 xf86DPMSInit(screen, xf86DPMSSet, 0);
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");
1052 if (intel->XvEnabled)
1053 I830InitVideo(screen);
1056 switch (intel->directRenderingType) {
1058 intel->directRenderingOpen = TRUE;
1059 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1060 "direct rendering: DRI2 Enabled\n");
1063 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1064 "direct rendering: Disabled\n");
1067 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1068 "direct rendering: Failed\n");
1072 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1073 "direct rendering: Not available\n");
1076 if (serverGeneration == 1)
1077 xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1079 intel_mode_init(intel);
1081 intel->suspended = FALSE;
1084 I830UeventInit(scrn);
1090 static void i830AdjustFrame(int scrnIndex, int x, int y, int flags)
1094 static void I830FreeScreen(int scrnIndex, int flags)
1096 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1097 intel_screen_private *intel = intel_get_screen_private(scrn);
1100 intel_mode_fini(intel);
1101 intel_close_drm_master(intel);
1102 intel_bufmgr_fini(intel);
1105 scrn->driverPrivate = NULL;
1108 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1109 vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1112 static void I830LeaveVT(int scrnIndex, int flags)
1114 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1115 intel_screen_private *intel = intel_get_screen_private(scrn);
1118 DPRINTF(PFX, "Leave VT\n");
1120 xf86RotateFreeShadow(scrn);
1122 xf86_hide_cursors(scrn);
1124 ret = drmDropMaster(intel->drmSubFD);
1126 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1127 "drmDropMaster failed: %s\n", strerror(errno));
1131 * This gets called when gaining control of the VT, and from ScreenInit().
1133 static Bool I830EnterVT(int scrnIndex, int flags)
1135 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1136 intel_screen_private *intel = intel_get_screen_private(scrn);
1139 DPRINTF(PFX, "Enter VT\n");
1141 ret = drmSetMaster(intel->drmSubFD);
1143 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1144 "drmSetMaster failed: %s\n",
1148 intel_set_gem_max_sizes(scrn);
1150 if (!xf86SetDesiredModes(scrn))
1156 static Bool I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1158 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1160 return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
1163 static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
1165 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1166 intel_screen_private *intel = intel_get_screen_private(scrn);
1169 I830UeventFini(scrn);
1172 if (scrn->vtSema == TRUE) {
1173 I830LeaveVT(scrnIndex, 0);
1176 DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
1178 if (intel->uxa_driver) {
1179 uxa_driver_fini(screen);
1180 free(intel->uxa_driver);
1181 intel->uxa_driver = NULL;
1184 if (intel->front_buffer) {
1185 if (!intel->use_shadow)
1186 intel_set_pixmap_bo(screen->GetScreenPixmap(screen),
1188 intel_mode_remove_fb(intel);
1189 drm_intel_bo_unreference(intel->front_buffer);
1190 intel->front_buffer = NULL;
1193 if (intel->shadow_buffer) {
1194 free(intel->shadow_buffer);
1195 intel->shadow_buffer = NULL;
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;
1205 intel_batch_teardown(scrn);
1207 if (INTEL_INFO(intel)->gen >= 40)
1208 gen4_render_state_cleanup(scrn);
1210 xf86_cursors_fini(screen);
1212 i965_free_video(scrn);
1214 screen->CloseScreen = intel->CloseScreen;
1215 (*screen->CloseScreen) (scrnIndex, screen);
1217 if (intel->directRenderingOpen
1218 && intel->directRenderingType == DRI_DRI2) {
1219 intel->directRenderingOpen = FALSE;
1220 I830DRI2CloseScreen(screen);
1223 xf86GARTCloseScreen(scrnIndex);
1225 scrn->vtSema = FALSE;
1230 I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1232 if (mode->Flags & V_INTERLACE) {
1234 xf86DrvMsg(scrnIndex, X_PROBED,
1235 "Removing interlaced mode \"%s\"\n",
1243 #ifndef SUSPEND_SLEEP
1244 #define SUSPEND_SLEEP 0
1246 #ifndef RESUME_SLEEP
1247 #define RESUME_SLEEP 0
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.
1255 static Bool I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
1257 ScrnInfoPtr scrn = xf86Screens[scrnIndex];
1258 intel_screen_private *intel = intel_get_screen_private(scrn);
1260 DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event,
1261 BOOLTOSTRING(undo));
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;
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;
1287 * Turn the screen saver off when resuming. This seems to be
1288 * needed to stop xscreensaver kicking in (when used).
1290 * XXX DoApmEvent() should probably call this just like
1291 * xf86VTSwitch() does. Maybe do it here only in 4.2
1292 * compatibility mode.
1294 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1297 /* This is currently used for ACPI */
1298 case XF86_APM_CAPABILITY_CHANGED:
1299 ErrorF("I830PMEvent: Capability change\n");
1301 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1305 ErrorF("I830PMEvent: received APM event %d\n", event);
1310 void intel_init_scrn(ScrnInfoPtr scrn)
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;