intel_driver.c revision 13496ba1
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
626static void
627redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
628{
629	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
630	intel_screen_private *intel = intel_get_screen_private(scrn);
631	RegionRec pixregion;
632	int was_blocked;
633
634	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
635	RegionTranslate(&pixregion, dirty->x, dirty->y);
636	RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage));
637	RegionTranslate(&pixregion, -dirty->x, -dirty->y);
638	was_blocked = RegionNil(&pixregion);
639	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
640	RegionUninit(&pixregion);
641	if (was_blocked)
642		return;
643
644	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
645	PixmapSyncDirtyHelper(dirty, &pixregion);
646	RegionUninit(&pixregion);
647
648        intel_flush(intel);
649	if (!intel->has_prime_vmap_flush) {
650		drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap);
651		was_blocked = xf86BlockSIGIO();
652		drm_intel_bo_map(bo, FALSE);
653		drm_intel_bo_unmap(bo);
654		xf86UnblockSIGIO(was_blocked);
655	}
656
657	DamageRegionProcessPending(&dirty->slave_dst->drawable);
658	return;
659}
660
661static void
662intel_dirty_update(ScreenPtr screen)
663{
664	RegionPtr region;
665	PixmapDirtyUpdatePtr ent;
666
667	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
668	    return;
669
670	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
671		region = DamageRegion(ent->damage);
672		if (RegionNotEmpty(region)) {
673			redisplay_dirty(screen, ent);
674			DamageEmpty(ent->damage);
675		}
676	}
677}
678#endif
679
680static void
681I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
682{
683	SCREEN_PTR(arg);
684	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
685	intel_screen_private *intel = intel_get_screen_private(scrn);
686
687	screen->BlockHandler = intel->BlockHandler;
688
689	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);
690
691	intel->BlockHandler = screen->BlockHandler;
692	screen->BlockHandler = I830BlockHandler;
693
694	intel_uxa_block_handler(intel);
695	intel_video_block_handler(intel);
696#ifdef INTEL_PIXMAP_SHARING
697	intel_dirty_update(screen);
698#endif
699}
700
701static Bool
702intel_init_initial_framebuffer(ScrnInfoPtr scrn)
703{
704	intel_screen_private *intel = intel_get_screen_private(scrn);
705	int width = scrn->virtualX;
706	int height = scrn->virtualY;
707	int pitch;
708	uint32_t tiling;
709
710	intel->front_buffer = intel_allocate_framebuffer(scrn,
711							 width, height,
712							 intel->cpp,
713							 &pitch, &tiling);
714
715	if (!intel->front_buffer) {
716		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
717			   "Couldn't allocate initial framebuffer.\n");
718		return FALSE;
719	}
720
721	intel->front_pitch = pitch;
722	intel->front_tiling = tiling;
723	scrn->displayWidth = pitch / intel->cpp;
724
725	return TRUE;
726}
727
728static void
729intel_flush_callback(CallbackListPtr *list,
730		     pointer user_data, pointer call_data)
731{
732	ScrnInfoPtr scrn = user_data;
733	if (scrn->vtSema)
734                intel_flush(intel_get_screen_private(scrn));
735}
736
737#if HAVE_UDEV
738static void
739I830HandleUEvents(int fd, void *closure)
740{
741	ScrnInfoPtr scrn = closure;
742	intel_screen_private *intel = intel_get_screen_private(scrn);
743	struct udev_device *dev;
744	const char *hotplug;
745	struct stat s;
746	dev_t udev_devnum;
747
748	dev = udev_monitor_receive_device(intel->uevent_monitor);
749	if (!dev)
750		return;
751
752	udev_devnum = udev_device_get_devnum(dev);
753	if (fstat(intel->drmSubFD, &s)) {
754		udev_device_unref(dev);
755		return;
756	}
757	/*
758	 * Check to make sure this event is directed at our
759	 * device (by comparing dev_t values), then make
760	 * sure it's a hotplug event (HOTPLUG=1)
761	 */
762
763	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
764
765	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
766			hotplug && atoi(hotplug) == 1)
767	{
768		intel_mode_hotplug(intel);
769	}
770
771	udev_device_unref(dev);
772}
773
774static void
775I830UeventInit(ScrnInfoPtr scrn)
776{
777	intel_screen_private *intel = intel_get_screen_private(scrn);
778	struct udev *u;
779	struct udev_monitor *mon;
780	Bool hotplug;
781	MessageType from = X_CONFIG;
782
783	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
784		from = X_DEFAULT;
785		hotplug = TRUE;
786	}
787
788	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
789			hotplug ? "enabled" : "disabled");
790	if (!hotplug)
791		return;
792
793	u = udev_new();
794	if (!u)
795		return;
796
797	mon = udev_monitor_new_from_netlink(u, "udev");
798
799	if (!mon) {
800		udev_unref(u);
801		return;
802	}
803
804	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
805				"drm",
806				"drm_minor") < 0 ||
807			udev_monitor_enable_receiving(mon) < 0)
808	{
809		udev_monitor_unref(mon);
810		udev_unref(u);
811		return;
812	}
813
814	intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
815						      I830HandleUEvents, scrn);
816	if (!intel->uevent_handler) {
817		udev_monitor_unref(mon);
818		udev_unref(u);
819		return;
820	}
821
822	intel->uevent_monitor = mon;
823}
824
825static void
826I830UeventFini(ScrnInfoPtr scrn)
827{
828	intel_screen_private *intel = intel_get_screen_private(scrn);
829
830	if (intel->uevent_handler) {
831		struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
832
833		xf86RemoveGeneralHandler(intel->uevent_handler);
834
835		udev_monitor_unref(intel->uevent_monitor);
836		udev_unref(u);
837		intel->uevent_handler = NULL;
838		intel->uevent_monitor = NULL;
839	}
840}
841#endif /* HAVE_UDEV */
842
843static Bool
844I830ScreenInit(SCREEN_INIT_ARGS_DECL)
845{
846	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
847	intel_screen_private *intel = intel_get_screen_private(scrn);
848	VisualPtr visual;
849#ifdef INTEL_XVMC
850	MessageType from;
851#endif
852	struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
853	int fb_bar = IS_GEN2(intel) ? 0 : 2;
854
855	scrn->videoRam = device->regions[fb_bar].size / 1024;
856
857	intel->last_3d = LAST_3D_OTHER;
858	intel->overlayOn = FALSE;
859
860	/*
861	 * Set this so that the overlay allocation is factored in when
862	 * appropriate.
863	 */
864	intel->XvEnabled = TRUE;
865
866	if (!intel_init_initial_framebuffer(scrn))
867		return FALSE;
868
869	miClearVisualTypes();
870	if (!miSetVisualTypes(scrn->depth,
871			      miGetDefaultVisualMask(scrn->depth),
872			      scrn->rgbBits, scrn->defaultVisual))
873		return FALSE;
874	if (!miSetPixmapDepths())
875		return FALSE;
876
877	/* Must be first, before anything else installs screen callbacks. */
878	if (!fbScreenInit(screen, NULL,
879			  scrn->virtualX, scrn->virtualY,
880			  scrn->xDpi, scrn->yDpi,
881			  scrn->displayWidth, scrn->bitsPerPixel))
882		return FALSE;
883
884	if (scrn->bitsPerPixel > 8) {
885		/* Fixup RGB ordering */
886		visual = screen->visuals + screen->numVisuals;
887		while (--visual >= screen->visuals) {
888			if ((visual->class | DynamicClass) == DirectColor) {
889				visual->offsetRed = scrn->offset.red;
890				visual->offsetGreen = scrn->offset.green;
891				visual->offsetBlue = scrn->offset.blue;
892				visual->redMask = scrn->mask.red;
893				visual->greenMask = scrn->mask.green;
894				visual->blueMask = scrn->mask.blue;
895			}
896		}
897	}
898
899	fbPictureInit(screen, NULL, 0);
900
901	xf86SetBlackWhitePixels(screen);
902
903	if (!intel_uxa_init(screen)) {
904		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
905			   "Hardware acceleration initialization failed\n");
906		return FALSE;
907	}
908
909#if HAVE_DRI2
910	if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen))
911		intel->dri2 = DRI_ACTIVE;
912#endif
913
914#if HAVE_DRI3
915	if (!intel_sync_init(screen))
916		intel->dri3 = DRI_DISABLED;
917	if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen))
918		intel->dri3 = DRI_ACTIVE;
919#endif
920
921	if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE))
922		intel_present_screen_init(screen);
923
924	xf86SetBackingStore(screen);
925	xf86SetSilkenMouse(screen);
926	miDCInitialize(screen, xf86GetPointerScreenFuncs());
927
928	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
929	if (!xf86_cursors_init(screen, 64, 64,
930			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
931				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
932				HARDWARE_CURSOR_INVERT_MASK |
933				HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
934				HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
935				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
936				HARDWARE_CURSOR_UPDATE_UNHIDDEN |
937				HARDWARE_CURSOR_ARGB))) {
938		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
939			   "Hardware cursor initialization failed\n");
940	}
941
942	intel->BlockHandler = screen->BlockHandler;
943	screen->BlockHandler = I830BlockHandler;
944
945#ifdef INTEL_PIXMAP_SHARING
946	screen->StartPixmapTracking = PixmapStartDirtyTracking;
947	screen->StopPixmapTracking = PixmapStopDirtyTracking;
948#endif
949
950	if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
951		return FALSE;
952
953	screen->SaveScreen = xf86SaveScreen;
954	intel->CloseScreen = screen->CloseScreen;
955	screen->CloseScreen = I830CloseScreen;
956	intel->CreateScreenResources = screen->CreateScreenResources;
957	screen->CreateScreenResources = i830CreateScreenResources;
958
959	if (!xf86CrtcScreenInit(screen))
960		return FALSE;
961
962	if (!miCreateDefColormap(screen))
963		return FALSE;
964
965	if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL,
966				 CMAP_RELOAD_ON_MODE_SWITCH |
967				 CMAP_PALETTED_TRUECOLOR)) {
968		return FALSE;
969	}
970
971	xf86DPMSInit(screen, xf86DPMSSet, 0);
972
973#ifdef INTEL_XVMC
974	if (INTEL_INFO(intel)->gen >= 040)
975		intel->XvMCEnabled = TRUE;
976	from = (intel->dri2 == DRI_ACTIVE &&
977		xf86GetOptValBool(intel->Options, OPTION_XVMC,
978				  &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
979	xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
980		   intel->XvMCEnabled ? "en" : "dis");
981#endif
982	/* Init video */
983	if (intel->XvEnabled)
984		intel_video_init(screen);
985
986#if HAVE_DRI2
987	switch (intel->dri2) {
988	case DRI_ACTIVE:
989		xf86DrvMsg(scrn->scrnIndex, X_INFO,
990			   "DRI2: Enabled\n");
991		break;
992	case DRI_DISABLED:
993		xf86DrvMsg(scrn->scrnIndex, X_INFO,
994			   "DRI2: Disabled\n");
995		break;
996	case DRI_NONE:
997		xf86DrvMsg(scrn->scrnIndex, X_INFO,
998			   "DRI2: Failed\n");
999		break;
1000	}
1001#else
1002	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1003		   "DRI2: Not available\n");
1004#endif
1005
1006#if HAVE_DRI3
1007	switch (intel->dri3) {
1008	case DRI_ACTIVE:
1009		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1010			   "DRI3: Enabled\n");
1011		break;
1012	case DRI_DISABLED:
1013		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1014			   "DRI3: Disabled\n");
1015		break;
1016	case DRI_NONE:
1017		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1018			   "DRI3: Failed\n");
1019		break;
1020	}
1021#else
1022	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1023		   "DRI3: Not available\n");
1024#endif
1025
1026	if (serverGeneration == 1)
1027		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1028
1029	intel_mode_init(intel);
1030
1031	intel->suspended = FALSE;
1032
1033#if HAVE_UDEV
1034	I830UeventInit(scrn);
1035#endif
1036
1037	/* Must force it before EnterVT, so we are in control of VT and
1038	 * later memory should be bound when allocating, e.g rotate_mem */
1039	scrn->vtSema = TRUE;
1040
1041	return I830EnterVT(VT_FUNC_ARGS(0));
1042}
1043
1044static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL)
1045{
1046}
1047
1048static void I830FreeScreen(FREE_SCREEN_ARGS_DECL)
1049{
1050	SCRN_INFO_PTR(arg);
1051	intel_screen_private *intel = intel_get_screen_private(scrn);
1052
1053	if (intel && !((uintptr_t)intel & 3)) {
1054		intel_mode_fini(intel);
1055		intel_bufmgr_fini(intel);
1056		intel_put_device(intel->dev);
1057
1058		free(intel);
1059		scrn->driverPrivate = NULL;
1060	}
1061}
1062
1063static void I830LeaveVT(VT_FUNC_ARGS_DECL)
1064{
1065	SCRN_INFO_PTR(arg);
1066	intel_screen_private *intel = intel_get_screen_private(scrn);
1067
1068	xf86RotateFreeShadow(scrn);
1069
1070	xf86_hide_cursors(scrn);
1071
1072	if (intel_put_master(intel->dev))
1073		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1074			   "drmDropMaster failed: %s\n", strerror(errno));
1075}
1076
1077/*
1078 * This gets called when gaining control of the VT, and from ScreenInit().
1079 */
1080static Bool I830EnterVT(VT_FUNC_ARGS_DECL)
1081{
1082	SCRN_INFO_PTR(arg);
1083	intel_screen_private *intel = intel_get_screen_private(scrn);
1084
1085	if (intel_get_master(intel->dev)) {
1086		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1087			   "drmSetMaster failed: %s\n",
1088			   strerror(errno));
1089		return FALSE;
1090	}
1091
1092	if (!xf86SetDesiredModes(scrn))
1093		return FALSE;
1094
1095	intel_mode_disable_unused_functions(scrn);
1096	return TRUE;
1097}
1098
1099static Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL)
1100{
1101	SCRN_INFO_PTR(arg);
1102
1103	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
1104}
1105
1106static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
1107{
1108	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1109	intel_screen_private *intel = intel_get_screen_private(scrn);
1110
1111#if HAVE_UDEV
1112	I830UeventFini(scrn);
1113#endif
1114
1115	intel_mode_close(intel);
1116
1117	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
1118
1119	TimerFree(intel->cache_expire);
1120	intel->cache_expire = NULL;
1121
1122	if (intel->uxa_driver) {
1123		uxa_driver_fini(screen);
1124		free(intel->uxa_driver);
1125		intel->uxa_driver = NULL;
1126	}
1127
1128	if (intel->back_buffer) {
1129		drm_intel_bo_unreference(intel->back_buffer);
1130		intel->back_buffer = NULL;
1131	}
1132
1133	if (intel->front_buffer) {
1134		intel_mode_remove_fb(intel);
1135		drm_intel_bo_unreference(intel->front_buffer);
1136		intel->front_buffer = NULL;
1137	}
1138
1139	if (scrn->vtSema == TRUE) {
1140		I830LeaveVT(VT_FUNC_ARGS(0));
1141	}
1142
1143	intel_batch_teardown(scrn);
1144
1145	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
1146		gen4_render_state_cleanup(scrn);
1147
1148	xf86_cursors_fini(screen);
1149
1150	i965_free_video(scrn);
1151
1152	screen->CloseScreen = intel->CloseScreen;
1153	(*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
1154
1155	if (intel->dri2 == DRI_ACTIVE) {
1156		I830DRI2CloseScreen(screen);
1157		intel->dri2 = DRI_NONE;
1158	}
1159
1160	if (intel->dri3 == DRI_ACTIVE) {
1161		/* nothing to do here? */
1162		intel->dri3 = DRI_NONE;
1163	}
1164
1165	intel_sync_close(screen);
1166
1167	xf86GARTCloseScreen(scrn->scrnIndex);
1168
1169	scrn->vtSema = FALSE;
1170	return TRUE;
1171}
1172
1173static ModeStatus
1174I830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
1175{
1176	SCRN_INFO_PTR(arg);
1177	if (mode->Flags & V_INTERLACE) {
1178		if (verbose) {
1179			xf86DrvMsg(scrn->scrnIndex, X_PROBED,
1180				   "Removing interlaced mode \"%s\"\n",
1181				   mode->name);
1182		}
1183		return MODE_BAD;
1184	}
1185	return MODE_OK;
1186}
1187
1188#ifndef SUSPEND_SLEEP
1189#define SUSPEND_SLEEP 0
1190#endif
1191#ifndef RESUME_SLEEP
1192#define RESUME_SLEEP 0
1193#endif
1194
1195/*
1196 * This function is only required if we need to do anything differently from
1197 * DoApmEvent() in common/xf86PM.c, including if we want to see events other
1198 * than suspend/resume.
1199 */
1200static Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
1201{
1202	SCRN_INFO_PTR(arg);
1203	intel_screen_private *intel = intel_get_screen_private(scrn);
1204
1205	switch (event) {
1206	case XF86_APM_SYS_SUSPEND:
1207	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
1208	case XF86_APM_USER_SUSPEND:
1209	case XF86_APM_SYS_STANDBY:
1210	case XF86_APM_USER_STANDBY:
1211		if (!undo && !intel->suspended) {
1212			scrn->LeaveVT(VT_FUNC_ARGS(0));
1213			intel->suspended = TRUE;
1214			sleep(SUSPEND_SLEEP);
1215		} else if (undo && intel->suspended) {
1216			sleep(RESUME_SLEEP);
1217			scrn->EnterVT(VT_FUNC_ARGS(0));
1218			intel->suspended = FALSE;
1219		}
1220		break;
1221	case XF86_APM_STANDBY_RESUME:
1222	case XF86_APM_NORMAL_RESUME:
1223	case XF86_APM_CRITICAL_RESUME:
1224		if (intel->suspended) {
1225			sleep(RESUME_SLEEP);
1226			scrn->EnterVT(VT_FUNC_ARGS(0));
1227			intel->suspended = FALSE;
1228			/*
1229			 * Turn the screen saver off when resuming.  This seems to be
1230			 * needed to stop xscreensaver kicking in (when used).
1231			 *
1232			 * XXX DoApmEvent() should probably call this just like
1233			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
1234			 * compatibility mode.
1235			 */
1236			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1237		}
1238		break;
1239		/* This is currently used for ACPI */
1240	case XF86_APM_CAPABILITY_CHANGED:
1241		ErrorF("I830PMEvent: Capability change\n");
1242
1243		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1244
1245		break;
1246	default:
1247		ErrorF("I830PMEvent: received APM event %d\n", event);
1248	}
1249	return TRUE;
1250}
1251
1252Bool intel_init_scrn(ScrnInfoPtr scrn)
1253{
1254	scrn->PreInit = I830PreInit;
1255	scrn->ScreenInit = I830ScreenInit;
1256	scrn->SwitchMode = I830SwitchMode;
1257	scrn->AdjustFrame = i830AdjustFrame;
1258	scrn->EnterVT = I830EnterVT;
1259	scrn->LeaveVT = I830LeaveVT;
1260	scrn->FreeScreen = I830FreeScreen;
1261	scrn->ValidMode = I830ValidMode;
1262	scrn->PMEvent = I830PMEvent;
1263	return TRUE;
1264}
1265