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