fbdev.c 30 KB
Newer Older
Kaleb Keithley's avatar
Kaleb Keithley committed
1
2
/*
 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
Michel Dänzer's avatar
Michel Dänzer committed
3
 *	     Michel Dänzer, <michel@tungstengraphics.com>
Kaleb Keithley's avatar
Kaleb Keithley committed
4
5
 */

6
7
8
9
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

10
11
#include <string.h>

Kaleb Keithley's avatar
Kaleb Keithley committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* all driver need this */
#include "xf86.h"
#include "xf86_OSproc.h"

#include "mipointer.h"
#include "mibstore.h"
#include "micmap.h"
#include "colormapst.h"
#include "xf86cmap.h"
#include "shadow.h"
#include "dgaproc.h"

/* for visuals */
#include "fb.h"

27
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
Kaleb Keithley's avatar
Kaleb Keithley committed
28
29
#include "xf86Resources.h"
#include "xf86RAC.h"
30
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
31
32
33
34
35

#include "fbdevhw.h"

#include "xf86xv.h"

Dave Airlie's avatar
Dave Airlie committed
36
37
#include "compat-api.h"

38
#ifdef XSERVER_LIBPCIACCESS
39
40
41
#include <pciaccess.h>
#endif

42
static Bool debug = 0;
Kaleb Keithley's avatar
Kaleb Keithley committed
43

44
45
46
47
48
49
#define TRACE_ENTER(str) \
    do { if (debug) ErrorF("fbdev: " str " %d\n",pScrn->scrnIndex); } while (0)
#define TRACE_EXIT(str) \
    do { if (debug) ErrorF("fbdev: " str " done\n"); } while (0)
#define TRACE(str) \
    do { if (debug) ErrorF("fbdev trace: " str "\n"); } while (0)
Kaleb Keithley's avatar
Kaleb Keithley committed
50
51
52
53
54
55
56

/* -------------------------------------------------------------------- */
/* prototypes                                                           */

static const OptionInfoRec * FBDevAvailableOptions(int chipid, int busid);
static void	FBDevIdentify(int flags);
static Bool	FBDevProbe(DriverPtr drv, int flags);
57
#ifdef XSERVER_LIBPCIACCESS
58
59
60
static Bool	FBDevPciProbe(DriverPtr drv, int entity_num,
     struct pci_device *dev, intptr_t match_data);
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
61
static Bool	FBDevPreInit(ScrnInfoPtr pScrn, int flags);
Dave Airlie's avatar
Dave Airlie committed
62
63
static Bool	FBDevScreenInit(SCREEN_INIT_ARGS_DECL);
static Bool	FBDevCloseScreen(CLOSE_SCREEN_ARGS_DECL);
Kaleb Keithley's avatar
Kaleb Keithley committed
64
65
static void *	FBDevWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
				  CARD32 *size, void *closure);
Dave Airlie's avatar
Dave Airlie committed
66
static void	FBDevPointerMoved(SCRN_ARG_TYPE arg, int x, int y);
Kaleb Keithley's avatar
Kaleb Keithley committed
67
static Bool	FBDevDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
68
69
static Bool	FBDevDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
				pointer ptr);
Kaleb Keithley's avatar
Kaleb Keithley committed
70
71
72
73
74
75
76
77
78
79
80
81
82


enum { FBDEV_ROTATE_NONE=0, FBDEV_ROTATE_CW=270, FBDEV_ROTATE_UD=180, FBDEV_ROTATE_CCW=90 };


/* -------------------------------------------------------------------- */

/*
 * This is intentionally screen-independent.  It indicates the binding
 * choice made in the first PreInit.
 */
static int pix24bpp = 0;

83
#define FBDEV_VERSION		4000
Kaleb Keithley's avatar
Kaleb Keithley committed
84
85
86
#define FBDEV_NAME		"FBDEV"
#define FBDEV_DRIVER_NAME	"fbdev"

87
#ifdef XSERVER_LIBPCIACCESS
88
89
90
91
92
93
94
95
96
97
static const struct pci_id_match fbdev_device_match[] = {
    {
	PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
	0x00030000, 0x00ffffff, 0
    },

    { 0, 0, 0 },
};
#endif

98
_X_EXPORT DriverRec FBDEV = {
99
	FBDEV_VERSION,
Kaleb Keithley's avatar
Kaleb Keithley committed
100
101
102
103
104
105
106
107
	FBDEV_DRIVER_NAME,
#if 0
	"driver for linux framebuffer devices",
#endif
	FBDevIdentify,
	FBDevProbe,
	FBDevAvailableOptions,
	NULL,
108
	0,
109
110
	FBDevDriverFunc,

111
#ifdef XSERVER_LIBPCIACCESS
112
113
114
    fbdev_device_match,
    FBDevPciProbe
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
115
116
117
118
119
120
121
122
123
124
125
126
};

/* Supported "chipsets" */
static SymTabRec FBDevChipsets[] = {
    { 0, "fbdev" },
    {-1, NULL }
};

/* Supported options */
typedef enum {
	OPTION_SHADOW_FB,
	OPTION_ROTATE,
127
128
	OPTION_FBDEV,
	OPTION_DEBUG
Kaleb Keithley's avatar
Kaleb Keithley committed
129
130
131
132
133
134
} FBDevOpts;

static const OptionInfoRec FBDevOptions[] = {
	{ OPTION_SHADOW_FB,	"ShadowFB",	OPTV_BOOLEAN,	{0},	FALSE },
	{ OPTION_ROTATE,	"Rotate",	OPTV_STRING,	{0},	FALSE },
	{ OPTION_FBDEV,		"fbdev",	OPTV_STRING,	{0},	FALSE },
135
	{ OPTION_DEBUG,		"debug",	OPTV_BOOLEAN,	{0},	FALSE },
Kaleb Keithley's avatar
Kaleb Keithley committed
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	{ -1,			NULL,		OPTV_NONE,	{0},	FALSE }
};

/* -------------------------------------------------------------------- */

#ifdef XFree86LOADER

MODULESETUPPROTO(FBDevSetup);

static XF86ModuleVersionInfo FBDevVersRec =
{
	"fbdev",
	MODULEVENDORSTRING,
	MODINFOSTRING1,
	MODINFOSTRING2,
151
	XORG_VERSION_CURRENT,
152
	PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
Kaleb Keithley's avatar
Kaleb Keithley committed
153
154
	ABI_CLASS_VIDEODRV,
	ABI_VIDEODRV_VERSION,
155
	MOD_CLASS_VIDEODRV,
Kaleb Keithley's avatar
Kaleb Keithley committed
156
157
158
	{0,0,0,0}
};

159
_X_EXPORT XF86ModuleData fbdevModuleData = { &FBDevVersRec, FBDevSetup, NULL };
Kaleb Keithley's avatar
Kaleb Keithley committed
160
161
162
163
164
165
166
167

pointer
FBDevSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
	static Bool setupDone = FALSE;

	if (!setupDone) {
		setupDone = TRUE;
168
		xf86AddDriver(&FBDEV, module, HaveDriverFuncs);
Kaleb Keithley's avatar
Kaleb Keithley committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
		return (pointer)1;
	} else {
		if (errmaj) *errmaj = LDR_ONCEONLY;
		return NULL;
	}
}

#endif /* XFree86LOADER */

/* -------------------------------------------------------------------- */
/* our private data, and two functions to allocate/free this            */

typedef struct {
	unsigned char*			fbstart;
	unsigned char*			fbmem;
	int				fboff;
	int				lineLength;
	int				rotate;
	Bool				shadowFB;
188
	void				*shadow;
Kaleb Keithley's avatar
Kaleb Keithley committed
189
	CloseScreenProcPtr		CloseScreen;
190
	CreateScreenResourcesProcPtr	CreateScreenResources;
Dave Airlie's avatar
Dave Airlie committed
191
	void				(*PointerMoved)(SCRN_ARG_TYPE arg, int x, int y);
Kaleb Keithley's avatar
Kaleb Keithley committed
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
	EntityInfoPtr			pEnt;
	/* DGA info */
	DGAModePtr			pDGAMode;
	int				nDGAMode;
	OptionInfoPtr			Options;
} FBDevRec, *FBDevPtr;

#define FBDEVPTR(p) ((FBDevPtr)((p)->driverPrivate))

static Bool
FBDevGetRec(ScrnInfoPtr pScrn)
{
	if (pScrn->driverPrivate != NULL)
		return TRUE;
	
	pScrn->driverPrivate = xnfcalloc(sizeof(FBDevRec), 1);
	return TRUE;
}

static void
FBDevFreeRec(ScrnInfoPtr pScrn)
{
	if (pScrn->driverPrivate == NULL)
		return;
216
	free(pScrn->driverPrivate);
Kaleb Keithley's avatar
Kaleb Keithley committed
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	pScrn->driverPrivate = NULL;
}

/* -------------------------------------------------------------------- */

static const OptionInfoRec *
FBDevAvailableOptions(int chipid, int busid)
{
	return FBDevOptions;
}

static void
FBDevIdentify(int flags)
{
	xf86PrintChipsets(FBDEV_NAME, "driver for framebuffer", FBDevChipsets);
}

234

235
#ifdef XSERVER_LIBPCIACCESS
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
static Bool FBDevPciProbe(DriverPtr drv, int entity_num,
			  struct pci_device *dev, intptr_t match_data)
{
    ScrnInfoPtr pScrn = NULL;

    if (!xf86LoadDrvSubModule(drv, "fbdevhw"))
	return FALSE;
	    
    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, NULL,
				NULL, NULL, NULL, NULL);
    if (pScrn) {
	char *device;
	GDevPtr devSection = xf86GetDevFromEntity(pScrn->entityList[0],
						  pScrn->entityInstanceList[0]);

	device = xf86FindOptionValue(devSection->options, "fbdev");
	if (fbdevHWProbe(NULL, device, NULL)) {
	    pScrn->driverVersion = FBDEV_VERSION;
	    pScrn->driverName    = FBDEV_DRIVER_NAME;
	    pScrn->name          = FBDEV_NAME;
	    pScrn->Probe         = FBDevProbe;
	    pScrn->PreInit       = FBDevPreInit;
	    pScrn->ScreenInit    = FBDevScreenInit;
	    pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
	    pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
	    pScrn->EnterVT       = fbdevHWEnterVTWeak();
	    pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
	    pScrn->ValidMode     = fbdevHWValidModeWeak();

	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		       "claimed PCI slot %d@%d:%d:%d\n", 
		       dev->bus, dev->domain, dev->dev, dev->func);
	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		       "using %s\n", device ? device : "default device");
	}
	else {
	    pScrn = NULL;
	}
    }

    return (pScrn != NULL);
}
#endif


Kaleb Keithley's avatar
Kaleb Keithley committed
281
282
283
284
285
286
287
static Bool
FBDevProbe(DriverPtr drv, int flags)
{
	int i;
	ScrnInfoPtr pScrn;
       	GDevPtr *devSections;
	int numDevSections;
288
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley's avatar
Kaleb Keithley committed
289
	int bus,device,func;
290
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	char *dev;
	Bool foundScreen = FALSE;

	TRACE("probe start");

	/* For now, just bail out for PROBE_DETECT. */
	if (flags & PROBE_DETECT)
		return FALSE;

	if ((numDevSections = xf86MatchDevice(FBDEV_DRIVER_NAME, &devSections)) <= 0) 
	    return FALSE;
	
	if (!xf86LoadDrvSubModule(drv, "fbdevhw"))
	    return FALSE;
	    
	for (i = 0; i < numDevSections; i++) {
	    Bool isIsa = FALSE;
	    Bool isPci = FALSE;

	    dev = xf86FindOptionValue(devSections[i]->options,"fbdev");
	    if (devSections[i]->busID) {
312
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley's avatar
Kaleb Keithley committed
313
314
315
316
317
	        if (xf86ParsePciBusString(devSections[i]->busID,&bus,&device,
					  &func)) {
		    if (!xf86CheckPciSlot(bus,device,func))
		        continue;
		    isPci = TRUE;
318
319
		} else
#endif
Adam Jackson's avatar
Adam Jackson committed
320
#ifdef HAVE_ISA
321
		if (xf86ParseIsaBusString(devSections[i]->busID))
Kaleb Keithley's avatar
Kaleb Keithley committed
322
		    isIsa = TRUE;
Adam Jackson's avatar
Adam Jackson committed
323
324
325
		else
#endif
		    0;
Kaleb Keithley's avatar
Kaleb Keithley committed
326
327
328
329
330
		  
	    }
	    if (fbdevHWProbe(NULL,dev,NULL)) {
		pScrn = NULL;
		if (isPci) {
Adam Jackson's avatar
Adam Jackson committed
331
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley's avatar
Kaleb Keithley committed
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
		    /* XXX what about when there's no busID set? */
		    int entity;
		    
		    entity = xf86ClaimPciSlot(bus,device,func,drv,
					      0,devSections[i],
					      TRUE);
		    pScrn = xf86ConfigPciEntity(pScrn,0,entity,
						      NULL,RES_SHARED_VGA,
						      NULL,NULL,NULL,NULL);
		    /* xf86DrvMsg() can't be called without setting these */
		    pScrn->driverName    = FBDEV_DRIVER_NAME;
		    pScrn->name          = FBDEV_NAME;
		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
			       "claimed PCI slot %d:%d:%d\n",bus,device,func);

347
#endif
Adam Jackson's avatar
Adam Jackson committed
348
349
		} else if (isIsa) {
#ifdef HAVE_ISA
Kaleb Keithley's avatar
Kaleb Keithley committed
350
351
352
353
354
355
356
		    int entity;
		    
		    entity = xf86ClaimIsaSlot(drv, 0,
					      devSections[i], TRUE);
		    pScrn = xf86ConfigIsaEntity(pScrn,0,entity,
						      NULL,RES_SHARED_VGA,
						      NULL,NULL,NULL,NULL);
Adam Jackson's avatar
Adam Jackson committed
357
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
358
359
360
361
362
363
364
365
366
367
368
369
		} else {
		   int entity;

		    entity = xf86ClaimFbSlot(drv, 0,
					      devSections[i], TRUE);
		    pScrn = xf86ConfigFbEntity(pScrn,0,entity,
					       NULL,NULL,NULL,NULL);
		   
		}
		if (pScrn) {
		    foundScreen = TRUE;
		    
370
		    pScrn->driverVersion = FBDEV_VERSION;
Kaleb Keithley's avatar
Kaleb Keithley committed
371
372
373
374
375
		    pScrn->driverName    = FBDEV_DRIVER_NAME;
		    pScrn->name          = FBDEV_NAME;
		    pScrn->Probe         = FBDevProbe;
		    pScrn->PreInit       = FBDevPreInit;
		    pScrn->ScreenInit    = FBDevScreenInit;
376
377
378
379
380
		    pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
		    pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
		    pScrn->EnterVT       = fbdevHWEnterVTWeak();
		    pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
		    pScrn->ValidMode     = fbdevHWValidModeWeak();
Kaleb Keithley's avatar
Kaleb Keithley committed
381
382
383
384
385
386
		    
		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
			       "using %s\n", dev ? dev : "default device");
		}
	    }
	}
387
	free(devSections);
Kaleb Keithley's avatar
Kaleb Keithley committed
388
389
390
391
392
393
394
395
396
	TRACE("probe done");
	return foundScreen;
}

static Bool
FBDevPreInit(ScrnInfoPtr pScrn, int flags)
{
	FBDevPtr fPtr;
	int default_depth, fbbpp;
Adam Jackson's avatar
Adam Jackson committed
397
	const char *s;
398
	int type;
Kaleb Keithley's avatar
Kaleb Keithley committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

	if (flags & PROBE_DETECT) return FALSE;

	TRACE_ENTER("PreInit");

	/* Check the number of entities, and fail if it isn't one. */
	if (pScrn->numEntities != 1)
		return FALSE;

	pScrn->monitor = pScrn->confScreen->monitor;

	FBDevGetRec(pScrn);
	fPtr = FBDEVPTR(pScrn);

	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);

415
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley's avatar
Kaleb Keithley committed
416
417
418
419
420
421
422
423
424
425
	pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
	/* XXX Is this right?  Can probably remove RAC_FB */
	pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;

	if (fPtr->pEnt->location.type == BUS_PCI &&
	    xf86RegisterResources(fPtr->pEnt->index,NULL,ResExclusive)) {
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "xf86RegisterResources() found resource conflicts\n");
		return FALSE;
	}
426
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
427
428
429
430
	/* open device */
	if (!fbdevHWInit(pScrn,NULL,xf86FindOptionValue(fPtr->pEnt->device->options,"fbdev")))
		return FALSE;
	default_depth = fbdevHWGetDepth(pScrn,&fbbpp);
431
	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, fbbpp,
432
			     Support24bppFb | Support32bppFb | SupportConvert32to24 | SupportConvert24to32))
Kaleb Keithley's avatar
Kaleb Keithley committed
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
		return FALSE;
	xf86PrintDepthBpp(pScrn);

	/* Get the depth24 pixmap format */
	if (pScrn->depth == 24 && pix24bpp == 0)
		pix24bpp = xf86GetBppFromDepth(pScrn, 24);

	/* color weight */
	if (pScrn->depth > 8) {
		rgb zeros = { 0, 0, 0 };
		if (!xf86SetWeight(pScrn, zeros, zeros))
			return FALSE;
	}

	/* visual init */
	if (!xf86SetDefaultVisual(pScrn, -1))
		return FALSE;

	/* We don't currently support DirectColor at > 8bpp */
	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
453
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "requested default visual"
Kaleb Keithley's avatar
Kaleb Keithley committed
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
			   " (%s) is not supported at depth %d\n",
			   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
		return FALSE;
	}

	{
		Gamma zeros = {0.0, 0.0, 0.0};

		if (!xf86SetGamma(pScrn,zeros)) {
			return FALSE;
		}
	}

	pScrn->progClock = TRUE;
	pScrn->rgbBits   = 8;
	pScrn->chipset   = "fbdev";
	pScrn->videoRam  = fbdevHWGetVidmem(pScrn);

472
473
	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s (video memory:"
		   " %dkB)\n", fbdevHWGetName(pScrn), pScrn->videoRam/1024);
Kaleb Keithley's avatar
Kaleb Keithley committed
474
475
476

	/* handle options */
	xf86CollectOptions(pScrn, NULL);
477
	if (!(fPtr->Options = malloc(sizeof(FBDevOptions))))
Kaleb Keithley's avatar
Kaleb Keithley committed
478
479
480
481
482
483
484
		return FALSE;
	memcpy(fPtr->Options, FBDevOptions, sizeof(FBDevOptions));
	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options, fPtr->Options);

	/* use shadow framebuffer by default */
	fPtr->shadowFB = xf86ReturnOptValBool(fPtr->Options, OPTION_SHADOW_FB, TRUE);

485
486
	debug = xf86ReturnOptValBool(fPtr->Options, OPTION_DEBUG, FALSE);

Kaleb Keithley's avatar
Kaleb Keithley committed
487
488
489
490
491
492
493
494
495
	/* rotation */
	fPtr->rotate = FBDEV_ROTATE_NONE;
	if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE)))
	{
	  if(!xf86NameCmp(s, "CW"))
	  {
	    fPtr->shadowFB = TRUE;
	    fPtr->rotate = FBDEV_ROTATE_CW;
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
496
		       "rotating screen clockwise\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
497
498
499
500
501
502
	  }
	  else if(!xf86NameCmp(s, "CCW"))
	  {
	    fPtr->shadowFB = TRUE;
	    fPtr->rotate = FBDEV_ROTATE_CCW;
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
503
		       "rotating screen counter-clockwise\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
504
505
506
507
508
509
	  }
	  else if(!xf86NameCmp(s, "UD"))
	  {
	    fPtr->shadowFB = TRUE;
	    fPtr->rotate = FBDEV_ROTATE_UD;
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
510
		       "rotating screen upside-down\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
511
512
513
514
515
516
	  }
	  else
	  {
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		       "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
517
		       "valid options are \"CW\", \"CCW\" and \"UD\"\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
518
519
520
521
522
	  }
	}

	/* select video modes */

523
	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against framebuffer device...\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
524
525
	fbdevHWSetVideoModes(pScrn);

526
	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against monitor...\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
	{
		DisplayModePtr mode, first = mode = pScrn->modes;
		
		if (mode != NULL) do {
			mode->status = xf86CheckModeForMonitor(mode, pScrn->monitor);
			mode = mode->next;
		} while (mode != NULL && mode != first);

		xf86PruneDriverModes(pScrn);
	}

	if (NULL == pScrn->modes)
		fbdevHWUseBuildinMode(pScrn);
	pScrn->currentMode = pScrn->modes;

542
543
	/* First approximation, may be refined in ScreenInit */
	pScrn->displayWidth = pScrn->virtualX;
Kaleb Keithley's avatar
Kaleb Keithley committed
544
545
546
547
548
549
550

	xf86PrintModes(pScrn);

	/* Set display resolution */
	xf86SetDpi(pScrn, 0, 0);

	/* Load bpp-specific modules */
551
	switch ((type = fbdevHWGetType(pScrn)))
Kaleb Keithley's avatar
Kaleb Keithley committed
552
553
554
555
556
557
558
559
560
561
562
	{
	case FBDEVHW_PACKED_PIXELS:
		switch (pScrn->bitsPerPixel)
		{
		case 8:
		case 16:
		case 24:
		case 32:
			break;
		default:
			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
563
564
			"unsupported number of bits per pixel: %d",
			pScrn->bitsPerPixel);
Kaleb Keithley's avatar
Kaleb Keithley committed
565
566
567
568
569
570
			return FALSE;
		}
		break;
	case FBDEVHW_INTERLEAVED_PLANES:
               /* Not supported yet, don't know what to do with this */
               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
571
572
                          "interleaved planes are not yet supported by the "
			  "fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
573
574
575
576
577
		return FALSE;
	case FBDEVHW_TEXT:
               /* This should never happen ...
                * we should check for this much much earlier ... */
               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
578
                          "text mode is not supported by the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
579
580
581
582
		return FALSE;
       case FBDEVHW_VGA_PLANES:
               /* Not supported yet */
               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
583
584
                          "EGA/VGA planes are not yet supported by the fbdev "
			  "driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
585
586
587
               return FALSE;
       default:
               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
588
                          "unrecognised fbdev hardware type (%d)\n", type);
Kaleb Keithley's avatar
Kaleb Keithley committed
589
590
               return FALSE;
	}
Adam Jackson's avatar
Adam Jackson committed
591
	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
Kaleb Keithley's avatar
Kaleb Keithley committed
592
593
594
595
596
597
		FBDevFreeRec(pScrn);
		return FALSE;
	}

	/* Load shadow if needed */
	if (fPtr->shadowFB) {
598
599
		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "using shadow"
			   " framebuffer\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
600
601
602
603
604
605
606
607
608
609
		if (!xf86LoadSubModule(pScrn, "shadow")) {
			FBDevFreeRec(pScrn);
			return FALSE;
		}
	}

	TRACE_EXIT("PreInit");
	return TRUE;
}

610

611
static Bool
612
FBDevCreateScreenResources(ScreenPtr pScreen)
613
614
{
    PixmapPtr pPixmap;
615
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
616
617
618
619
620
621
622
623
    FBDevPtr fPtr = FBDEVPTR(pScrn);
    Bool ret;

    pScreen->CreateScreenResources = fPtr->CreateScreenResources;
    ret = pScreen->CreateScreenResources(pScreen);
    pScreen->CreateScreenResources = FBDevCreateScreenResources;

    if (!ret)
624
	return FALSE;
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

    pPixmap = pScreen->GetScreenPixmap(pScreen);

    if (!shadowAdd(pScreen, pPixmap, fPtr->rotate ?
		   shadowUpdateRotatePackedWeak() : shadowUpdatePackedWeak(),
		   FBDevWindowLinear, fPtr->rotate, NULL)) {
	return FALSE;
    }

    return TRUE;
}

static Bool
FBDevShadowInit(ScreenPtr pScreen)
{
640
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
641
    FBDevPtr fPtr = FBDEVPTR(pScrn);
642
643
644
645
646
    
    if (!shadowSetup(pScreen)) {
	return FALSE;
    }

647
648
    fPtr->CreateScreenResources = pScreen->CreateScreenResources;
    pScreen->CreateScreenResources = FBDevCreateScreenResources;
649

650
    return TRUE;
651
652
653
}


Kaleb Keithley's avatar
Kaleb Keithley committed
654
static Bool
Dave Airlie's avatar
Dave Airlie committed
655
FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
Kaleb Keithley's avatar
Kaleb Keithley committed
656
{
657
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Kaleb Keithley's avatar
Kaleb Keithley committed
658
659
660
	FBDevPtr fPtr = FBDEVPTR(pScrn);
	VisualPtr visual;
	int init_picture = 0;
661
	int ret, flags;
662
	int type;
Kaleb Keithley's avatar
Kaleb Keithley committed
663
664
665
666
667
668
669
670
671
672
673
674
675
676

	TRACE_ENTER("FBDevScreenInit");

#if DEBUG
	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
	       "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
	       pScrn->bitsPerPixel,
	       pScrn->depth,
	       xf86GetVisualName(pScrn->defaultVisual),
	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
#endif

	if (NULL == (fPtr->fbmem = fbdevHWMapVidmem(pScrn))) {
Dave Airlie's avatar
Dave Airlie committed
677
	        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"mapping of video memory"
678
			   " failed\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
679
680
681
682
683
684
685
		return FALSE;
	}
	fPtr->fboff = fbdevHWLinearOffset(pScrn);

	fbdevHWSave(pScrn);

	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) {
Dave Airlie's avatar
Dave Airlie committed
686
		xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"mode initialization failed\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
687
688
689
		return FALSE;
	}
	fbdevHWSaveScreen(pScreen, SCREEN_SAVER_ON);
Dave Airlie's avatar
Dave Airlie committed
690
	fbdevHWAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
Kaleb Keithley's avatar
Kaleb Keithley committed
691
692
693
694
695

	/* mi layer */
	miClearVisualTypes();
	if (pScrn->bitsPerPixel > 8) {
		if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor)) {
Dave Airlie's avatar
Dave Airlie committed
696
			xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"visual type setup failed"
697
698
				   " for %d bits per pixel [1]\n",
				   pScrn->bitsPerPixel);
Kaleb Keithley's avatar
Kaleb Keithley committed
699
700
701
702
703
704
			return FALSE;
		}
	} else {
		if (!miSetVisualTypes(pScrn->depth,
				      miGetDefaultVisualMask(pScrn->depth),
				      pScrn->rgbBits, pScrn->defaultVisual)) {
Dave Airlie's avatar
Dave Airlie committed
705
			xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"visual type setup failed"
706
707
				   " for %d bits per pixel [2]\n",
				   pScrn->bitsPerPixel);
Kaleb Keithley's avatar
Kaleb Keithley committed
708
709
710
711
			return FALSE;
		}
	}
	if (!miSetPixmapDepths()) {
Dave Airlie's avatar
Dave Airlie committed
712
	  xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"pixmap depth setup failed\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
713
714
715
716
717
	  return FALSE;
	}

	if(fPtr->rotate==FBDEV_ROTATE_CW || fPtr->rotate==FBDEV_ROTATE_CCW)
	{
718
719
720
	  int tmp = pScrn->virtualX;
	  pScrn->virtualX = pScrn->displayWidth = pScrn->virtualY;
	  pScrn->virtualY = tmp;
721
722
723
724
725
726
727
	} else if (!fPtr->shadowFB) {
		/* FIXME: this doesn't work for all cases, e.g. when each scanline
			has a padding which is independent from the depth (controlfb) */
		pScrn->displayWidth = fbdevHWGetLineLength(pScrn) /
				      (pScrn->bitsPerPixel / 8);

		if (pScrn->displayWidth != pScrn->virtualX) {
Dave Airlie's avatar
Dave Airlie committed
728
			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
729
730
731
				   "Pitch updated to %d after ModeInit\n",
				   pScrn->displayWidth);
		}
Kaleb Keithley's avatar
Kaleb Keithley committed
732
733
734
735
736
737
738
	}

	if(fPtr->rotate && !fPtr->PointerMoved) {
		fPtr->PointerMoved = pScrn->PointerMoved;
		pScrn->PointerMoved = FBDevPointerMoved;
	}

739
	fPtr->fbstart = fPtr->fbmem + fPtr->fboff;
Kaleb Keithley's avatar
Kaleb Keithley committed
740

741
	if (fPtr->shadowFB) {
742
743
	    fPtr->shadow = calloc(1, pScrn->virtualX * pScrn->virtualY *
				  pScrn->bitsPerPixel);
744
745
746
747
748
749
750
751

	    if (!fPtr->shadow) {
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			   "Failed to allocate shadow framebuffer\n");
		return FALSE;
	    }
	}

752
	switch ((type = fbdevHWGetType(pScrn)))
Kaleb Keithley's avatar
Kaleb Keithley committed
753
754
755
756
757
758
759
	{
	case FBDEVHW_PACKED_PIXELS:
		switch (pScrn->bitsPerPixel) {
		case 8:
		case 16:
		case 24:
		case 32:
760
761
762
763
764
			ret = fbScreenInit(pScreen, fPtr->shadowFB ? fPtr->shadow
					   : fPtr->fbstart, pScrn->virtualX,
					   pScrn->virtualY, pScrn->xDpi,
					   pScrn->yDpi, pScrn->displayWidth,
					   pScrn->bitsPerPixel);
Kaleb Keithley's avatar
Kaleb Keithley committed
765
766
767
			init_picture = 1;
			break;
	 	default:
Dave Airlie's avatar
Dave Airlie committed
768
			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
769
770
771
				   "internal error: invalid number of bits per"
				   " pixel (%d) encountered in"
				   " FBDevScreenInit()\n", pScrn->bitsPerPixel);
Kaleb Keithley's avatar
Kaleb Keithley committed
772
773
774
775
776
777
778
			ret = FALSE;
			break;
		}
		break;
	case FBDEVHW_INTERLEAVED_PLANES:
		/* This should never happen ...
		* we should check for this much much earlier ... */
Dave Airlie's avatar
Dave Airlie committed
779
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
780
781
		           "internal error: interleaved planes are not yet "
			   "supported by the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
782
783
784
785
786
		ret = FALSE;
		break;
	case FBDEVHW_TEXT:
		/* This should never happen ...
		* we should check for this much much earlier ... */
Dave Airlie's avatar
Dave Airlie committed
787
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
788
789
		           "internal error: text mode is not supported by the "
			   "fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
790
791
792
793
		ret = FALSE;
		break;
	case FBDEVHW_VGA_PLANES:
		/* Not supported yet */
Dave Airlie's avatar
Dave Airlie committed
794
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
795
796
		           "internal error: EGA/VGA Planes are not yet "
			   "supported by the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
797
798
799
		ret = FALSE;
		break;
	default:
Dave Airlie's avatar
Dave Airlie committed
800
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
801
		           "internal error: unrecognised hardware type (%d) "
802
			   "encountered in FBDevScreenInit()\n", type);
Kaleb Keithley's avatar
Kaleb Keithley committed
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
		ret = FALSE;
		break;
	}
	if (!ret)
		return FALSE;

	if (pScrn->bitsPerPixel > 8) {
		/* Fixup RGB ordering */
		visual = pScreen->visuals + pScreen->numVisuals;
		while (--visual >= pScreen->visuals) {
			if ((visual->class | DynamicClass) == DirectColor) {
				visual->offsetRed   = pScrn->offset.red;
				visual->offsetGreen = pScrn->offset.green;
				visual->offsetBlue  = pScrn->offset.blue;
				visual->redMask     = pScrn->mask.red;
				visual->greenMask   = pScrn->mask.green;
				visual->blueMask    = pScrn->mask.blue;
			}
		}
	}

	/* must be after RGB ordering fixed */
	if (init_picture && !fbPictureInit(pScreen, NULL, 0))
		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
827
			   "Render extension initialisation failed\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
828

829
	if (fPtr->shadowFB && !FBDevShadowInit(pScreen)) {
Dave Airlie's avatar
Dave Airlie committed
830
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
831
		       "shadow framebuffer initialization failed\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
832
833
834
835
836
837
	    return FALSE;
	}

	if (!fPtr->rotate)
	  FBDevDGAInit(pScrn, pScreen);
	else {
Dave Airlie's avatar
Dave Airlie committed
838
839
	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "display rotated; disabling DGA\n");
	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "using driver rotation; disabling "
840
			                "XRandR\n");
841
	  xf86DisableRandR();
Kaleb Keithley's avatar
Kaleb Keithley committed
842
	  if (pScrn->bitsPerPixel == 24)
Dave Airlie's avatar
Dave Airlie committed
843
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "rotation might be broken at 24 "
844
                                             "bits per pixel\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
845
846
847
848
849
850
851
852
853
854
	}

	xf86SetBlackWhitePixels(pScreen);
	miInitializeBackingStore(pScreen);
	xf86SetBackingStore(pScreen);

	/* software cursor */
	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());

	/* colormap */
855
	switch ((type = fbdevHWGetType(pScrn)))
Kaleb Keithley's avatar
Kaleb Keithley committed
856
857
858
	{
	/* XXX It would be simpler to use miCreateDefColormap() in all cases. */
	case FBDEVHW_PACKED_PIXELS:
859
		if (!miCreateDefColormap(pScreen)) {
Dave Airlie's avatar
Dave Airlie committed
860
			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
861
862
                                   "internal error: miCreateDefColormap failed "
				   "in FBDevScreenInit()\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
863
			return FALSE;
864
		}
Kaleb Keithley's avatar
Kaleb Keithley committed
865
866
		break;
	case FBDEVHW_INTERLEAVED_PLANES:
Dave Airlie's avatar
Dave Airlie committed
867
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
868
869
		           "internal error: interleaved planes are not yet "
			   "supported by the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
870
871
		return FALSE;
	case FBDEVHW_TEXT:
Dave Airlie's avatar
Dave Airlie committed
872
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
873
874
		           "internal error: text mode is not supported by "
			   "the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
875
876
		return FALSE;
	case FBDEVHW_VGA_PLANES:
Dave Airlie's avatar
Dave Airlie committed
877
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
878
879
		           "internal error: EGA/VGA planes are not yet "
			   "supported by the fbdev driver\n");
Kaleb Keithley's avatar
Kaleb Keithley committed
880
881
		return FALSE;
	default:
Dave Airlie's avatar
Dave Airlie committed
882
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
883
884
		           "internal error: unrecognised fbdev hardware type "
			   "(%d) encountered in FBDevScreenInit()\n", type);
Kaleb Keithley's avatar
Kaleb Keithley committed
885
886
887
		return FALSE;
	}
	flags = CMAP_PALETTED_TRUECOLOR;
888
	if(!xf86HandleColormaps(pScreen, 256, 8, fbdevHWLoadPaletteWeak(), 
889
				NULL, flags))
Kaleb Keithley's avatar
Kaleb Keithley committed
890
891
		return FALSE;

892
	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
Kaleb Keithley's avatar
Kaleb Keithley committed
893

894
	pScreen->SaveScreen = fbdevHWSaveScreenWeak();
Kaleb Keithley's avatar
Kaleb Keithley committed
895
896
897
898
899

	/* Wrap the current CloseScreen function */
	fPtr->CloseScreen = pScreen->CloseScreen;
	pScreen->CloseScreen = FBDevCloseScreen;

900
#if XV
Kaleb Keithley's avatar
Kaleb Keithley committed
901
902
903
904
905
906
907
908
	{
	    XF86VideoAdaptorPtr *ptr;

	    int n = xf86XVListGenericAdaptors(pScrn,&ptr);
	    if (n) {
		xf86XVScreenInit(pScreen,ptr,n);
	    }
	}
909
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
910
911
912
913
914
915
916

	TRACE_EXIT("FBDevScreenInit");

	return TRUE;
}

static Bool
Dave Airlie's avatar
Dave Airlie committed
917
FBDevCloseScreen(CLOSE_SCREEN_ARGS_DECL)
Kaleb Keithley's avatar
Kaleb Keithley committed
918
{
Dave Airlie's avatar
Dave Airlie committed
919
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Kaleb Keithley's avatar
Kaleb Keithley committed
920
921
922
923
	FBDevPtr fPtr = FBDEVPTR(pScrn);
	
	fbdevHWRestore(pScrn);
	fbdevHWUnmapVidmem(pScrn);
924
	if (fPtr->shadow) {
925
	    shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
926
	    free(fPtr->shadow);
927
928
	    fPtr->shadow = NULL;
	}
Kaleb Keithley's avatar
Kaleb Keithley committed
929
	if (fPtr->pDGAMode) {
930
	  free(fPtr->pDGAMode);
Kaleb Keithley's avatar
Kaleb Keithley committed
931
932
933
934
935
	  fPtr->pDGAMode = NULL;
	  fPtr->nDGAMode = 0;
	}
	pScrn->vtSema = FALSE;

936
	pScreen->CreateScreenResources = fPtr->CreateScreenResources;
Kaleb Keithley's avatar
Kaleb Keithley committed
937
	pScreen->CloseScreen = fPtr->CloseScreen;
Dave Airlie's avatar
Dave Airlie committed
938
	return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
Kaleb Keithley's avatar
Kaleb Keithley committed
939
940
941
942
943
944
945
946
947
948
949
950
}



/***********************************************************************
 * Shadow stuff
 ***********************************************************************/

static void *
FBDevWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
		 CARD32 *size, void *closure)
{
951
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Kaleb Keithley's avatar
Kaleb Keithley committed
952
953
954
955
956
957
958
959
960
961
    FBDevPtr fPtr = FBDEVPTR(pScrn);

    if (!pScrn->vtSema)
      return NULL;

    if (fPtr->lineLength)
      *size = fPtr->lineLength;
    else
      *size = fPtr->lineLength = fbdevHWGetLineLength(pScrn);

962
    return ((CARD8 *)fPtr->fbstart + row * fPtr->lineLength + offset);
Kaleb Keithley's avatar
Kaleb Keithley committed
963
964
965
}

static void
Dave Airlie's avatar
Dave Airlie committed
966
FBDevPointerMoved(SCRN_ARG_TYPE arg, int x, int y)
Kaleb Keithley's avatar
Kaleb Keithley committed
967
{
Dave Airlie's avatar
Dave Airlie committed
968
    SCRN_INFO_PTR(arg);
Kaleb Keithley's avatar
Kaleb Keithley committed
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
    FBDevPtr fPtr = FBDEVPTR(pScrn);
    int newX, newY;

    switch (fPtr->rotate)
    {
    case FBDEV_ROTATE_CW:
	/* 90 degrees CW rotation. */
	newX = pScrn->pScreen->height - y - 1;
	newY = x;
	break;

    case FBDEV_ROTATE_CCW:
	/* 90 degrees CCW rotation. */
	newX = y;
	newY = pScrn->pScreen->width - x - 1;
	break;

    case FBDEV_ROTATE_UD:
	/* 180 degrees UD rotation. */
	newX = pScrn->pScreen->width - x - 1;
	newY = pScrn->pScreen->height - y - 1;
	break;

    default:
	/* No rotation. */
	newX = x;
	newY = y;
	break;
    }

    /* Pass adjusted pointer coordinates to wrapped PointerMoved function. */
Dave Airlie's avatar
Dave Airlie committed
1000
    (*fPtr->PointerMoved)(arg, newX, newY);
Kaleb Keithley's avatar
Kaleb Keithley committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
}


/***********************************************************************
 * DGA stuff
 ***********************************************************************/
static Bool FBDevDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
				   unsigned char **ApertureBase,
				   int *ApertureSize, int *ApertureOffset,
				   int *flags);
static Bool FBDevDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
static void FBDevDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);

static Bool
FBDevDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
		       unsigned char **ApertureBase, int *ApertureSize,
		       int *ApertureOffset, int *flags)
{
    *DeviceName = NULL;		/* No special device */
    *ApertureBase = (unsigned char *)(pScrn->memPhysBase);
    *ApertureSize = pScrn->videoRam;
    *ApertureOffset = pScrn->fbOffset;
    *flags = 0;

    return TRUE;
}

static Bool
FBDevDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
{
    DisplayModePtr pMode;
    int scrnIdx = pScrn->pScreen->myNum;
    int frameX0, frameY0;

    if (pDGAMode) {
	pMode = pDGAMode->mode;
	frameX0 = frameY0 = 0;
    }
    else {
	if (!(pMode = pScrn->currentMode))
	    return TRUE;

	frameX0 = pScrn->frameX0;
	frameY0 = pScrn->frameY0;
    }

Dave Airlie's avatar
Dave Airlie committed
1047
    if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode)))
Kaleb Keithley's avatar
Kaleb Keithley committed
1048
	return FALSE;
Dave Airlie's avatar
Dave Airlie committed
1049
    (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0));
Kaleb Keithley's avatar
Kaleb Keithley committed
1050
1051
1052
1053
1054
1055
1056

    return TRUE;
}

static void
FBDevDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
{
Dave Airlie's avatar
Dave Airlie committed
1057
    (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
Kaleb Keithley's avatar
Kaleb Keithley committed
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
}

static int
FBDevDGAGetViewport(ScrnInfoPtr pScrn)
{
    return (0);
}

static DGAFunctionRec FBDevDGAFunctions =
{
    FBDevDGAOpenFramebuffer,
    NULL,       /* CloseFramebuffer */
    FBDevDGASetMode,
    FBDevDGASetViewport,
    FBDevDGAGetViewport,
    NULL,       /* Sync */
    NULL,       /* FillRect */
    NULL,       /* BlitRect */
    NULL,       /* BlitTransRect */
};

static void
FBDevDGAAddModes(ScrnInfoPtr pScrn)
{
    FBDevPtr fPtr = FBDEVPTR(pScrn);
    DisplayModePtr pMode = pScrn->modes;
    DGAModePtr pDGAMode;

    do {
1087
1088
	pDGAMode = realloc(fPtr->pDGAMode,
		           (fPtr->nDGAMode + 1) * sizeof(DGAModeRec));
Kaleb Keithley's avatar
Kaleb Keithley committed
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
	if (!pDGAMode)
	    break;

	fPtr->pDGAMode = pDGAMode;
	pDGAMode += fPtr->nDGAMode;
	(void)memset(pDGAMode, 0, sizeof(DGAModeRec));

	++fPtr->nDGAMode;
	pDGAMode->mode = pMode;
	pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
	pDGAMode->byteOrder = pScrn->imageByteOrder;
	pDGAMode->depth = pScrn->depth;
	pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
	pDGAMode->red_mask = pScrn->mask.red;
	pDGAMode->green_mask = pScrn->mask.green;
	pDGAMode->blue_mask = pScrn->mask.blue;
	pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
	    TrueColor : PseudoColor;
	pDGAMode->xViewportStep = 1;
	pDGAMode->yViewportStep = 1;
	pDGAMode->viewportWidth = pMode->HDisplay;
	pDGAMode->viewportHeight = pMode->VDisplay;

	if (fPtr->lineLength)
	  pDGAMode->bytesPerScanline = fPtr->lineLength;
	else
	  pDGAMode->bytesPerScanline = fPtr->lineLength = fbdevHWGetLineLength(pScrn);

	pDGAMode->imageWidth = pMode->HDisplay;
	pDGAMode->imageHeight =  pMode->VDisplay;
	pDGAMode->pixmapWidth = pDGAMode->imageWidth;
	pDGAMode->pixmapHeight = pDGAMode->imageHeight;
	pDGAMode->maxViewportX = pScrn->virtualX -
				    pDGAMode->viewportWidth;
	pDGAMode->maxViewportY = pScrn->virtualY -
				    pDGAMode->viewportHeight;

	pDGAMode->address = fPtr->fbstart;

	pMode = pMode->next;
    } while (pMode != pScrn->modes);
}

static Bool
FBDevDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
{
1135
#ifdef XFreeXDGA
Kaleb Keithley's avatar
Kaleb Keithley committed
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
    FBDevPtr fPtr = FBDEVPTR(pScrn);

    if (pScrn->depth < 8)
	return FALSE;

    if (!fPtr->nDGAMode)
	FBDevDGAAddModes(pScrn);

    return (DGAInit(pScreen, &FBDevDGAFunctions,
	    fPtr->pDGAMode, fPtr->nDGAMode));
1146
1147
1148
#else
    return TRUE;
#endif
Kaleb Keithley's avatar
Kaleb Keithley committed
1149
}
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

static Bool
FBDevDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr)
{
    xorgHWFlags *flag;
    
    switch (op) {
	case GET_REQUIRED_HW_INTERFACES:
	    flag = (CARD32*)ptr;
	    (*flag) = 0;
	    return TRUE;
	default:
	    return FALSE;
    }
}