ngle_driver.c revision a7fd8e5e
1/* $NetBSD: ngle_driver.c,v 1.1 2024/10/16 11:00:36 macallan Exp $ */
2/*
3 * Copyright (c) 2024 Michael Lorenz
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 *    - Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    - Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials provided
15 *      with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32/* a driver for HP's NGLE family of graphics chips */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37#include <sys/types.h>
38#include <dev/ic/stireg.h>
39
40#include <fcntl.h>
41#include <errno.h>
42#include <sys/time.h>
43#include <sys/mman.h>
44#include <sys/ioctl.h>
45#include <dev/wscons/wsconsio.h>
46
47/* all driver need this */
48#include "xf86.h"
49#include "xf86_OSproc.h"
50
51#include "mipointer.h"
52#include "micmap.h"
53#include "colormapst.h"
54#include "xf86cmap.h"
55#ifdef XvExtension
56#include "xf86xv.h"
57#endif
58
59/* for visuals */
60#include "fb.h"
61
62#include "ngle.h"
63
64/* #include "wsconsio.h" */
65
66#define NGLE_DEFAULT_DEV "/dev/ttyE0"
67
68static pointer NGLESetup(pointer, pointer, int *, int *);
69static Bool NGLEGetRec(ScrnInfoPtr);
70static void NGLEFreeRec(ScrnInfoPtr);
71static const OptionInfoRec * NGLEAvailableOptions(int, int);
72static void NGLEIdentify(int);
73static Bool NGLEProbe(DriverPtr, int);
74static Bool NGLEPreInit(ScrnInfoPtr, int);
75static Bool NGLEScreenInit(SCREEN_INIT_ARGS_DECL);
76static Bool NGLECloseScreen(CLOSE_SCREEN_ARGS_DECL);
77static Bool NGLEEnterVT(VT_FUNC_ARGS_DECL);
78static void NGLELeaveVT(VT_FUNC_ARGS_DECL);
79static Bool NGLESwitchMode(SWITCH_MODE_ARGS_DECL);
80static int NGLEValidMode(SCRN_ARG_TYPE, DisplayModePtr, Bool, int);
81static void NGLELoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
82static Bool NGLESaveScreen(ScreenPtr, int);
83static void NGLESave(ScrnInfoPtr);
84static void NGLERestore(ScrnInfoPtr);
85
86/* helper functions */
87static int ngle_open(const char *);
88static pointer ngle_mmap(size_t, off_t, int, int);
89
90#define VERSION			4000
91#define NGLE_NAME		"ngle"
92#define NGLE_DRIVER_NAME	"ngle"
93#define NGLE_MAJOR_VERSION	0
94#define NGLE_MINOR_VERSION	1
95
96DriverRec NGLE = {
97	VERSION,
98	NGLE_DRIVER_NAME,
99	NGLEIdentify,
100	NGLEProbe,
101	NGLEAvailableOptions,
102	NULL,
103	0
104};
105
106/* Supported "chipsets" */
107static SymTabRec NGLEChipsets[] = {
108	{ STI_DD_EG, "Visualize EG" },
109	{ STI_DD_HCRX, "HCRX" },
110	{ -1, NULL }
111};
112
113/* Supported options */
114typedef enum {
115	OPTION_HW_CURSOR,
116	OPTION_SW_CURSOR
117} NGLEOpts;
118
119static const OptionInfoRec NGLEOptions[] = {
120	{ OPTION_SW_CURSOR, "SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
121	{ OPTION_HW_CURSOR, "HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
122	{ -1, NULL, OPTV_NONE, {0}, FALSE}
123};
124
125static XF86ModuleVersionInfo NGLEVersRec = {
126	"ngle",
127	"The NetBSD Foundation",
128	MODINFOSTRING1,
129	MODINFOSTRING2,
130	XORG_VERSION_CURRENT,
131	NGLE_MAJOR_VERSION, NGLE_MINOR_VERSION, 0,
132	ABI_CLASS_VIDEODRV,
133	ABI_VIDEODRV_VERSION,
134	NULL,
135	{0, 0, 0, 0}
136};
137
138_X_EXPORT XF86ModuleData ngleModuleData = { &NGLEVersRec, NGLESetup, NULL };
139
140static pointer
141NGLESetup(pointer module, pointer opts, int *errmaj, int *errmin)
142{
143	static Bool setupDone = FALSE;
144	const char *osname;
145
146	if (!setupDone) {
147		setupDone = TRUE;
148		xf86AddDriver(&NGLE, module, 0);
149		return (pointer)1;
150	} else {
151		if (errmaj != NULL)
152			*errmaj = LDR_ONCEONLY;
153		return NULL;
154	}
155}
156
157static Bool
158NGLEGetRec(ScrnInfoPtr pScrn)
159{
160
161	if (pScrn->driverPrivate != NULL)
162		return TRUE;
163
164	pScrn->driverPrivate = xnfcalloc(sizeof(NGLERec), 1);
165	return TRUE;
166}
167
168static void
169NGLEFreeRec(ScrnInfoPtr pScrn)
170{
171
172	if (pScrn->driverPrivate == NULL)
173		return;
174	free(pScrn->driverPrivate);
175	pScrn->driverPrivate = NULL;
176}
177
178static const OptionInfoRec *
179NGLEAvailableOptions(int chipid, int busid)
180{
181	return NGLEOptions;
182}
183
184static void
185NGLEIdentify(int flags)
186{
187	xf86PrintChipsets(NGLE_NAME, "driver for NGLE framebuffers",
188			  NGLEChipsets);
189}
190
191
192#define priv_open_device(n)	open(n,O_RDWR|O_NONBLOCK|O_EXCL)
193
194/* Open the framebuffer device */
195static int
196ngle_open(const char *dev)
197{
198	int fd = -1;
199
200	/* try argument from XF86Config first */
201	if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
202		/* second: environment variable */
203		dev = getenv("XDEVICE");
204		if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
205			/* last try: default device */
206			dev = NGLE_DEFAULT_DEV;
207			if ((fd = priv_open_device(dev)) == -1) {
208				return -1;
209			}
210		}
211	}
212	return fd;
213}
214
215/* Map the framebuffer's memory */
216static pointer
217ngle_mmap(size_t len, off_t off, int fd, int ro)
218{
219	pointer mapaddr;
220
221	/*
222	 * try and make it private first, that way once we get it, an
223	 * interloper, e.g. another server, can't get this frame buffer,
224	 * and if another server already has it, this one won't.
225	 */
226	if (ro) {
227		mapaddr = (pointer) mmap(NULL, len,
228					 PROT_READ, MAP_SHARED,
229					 fd, off);
230		xf86Msg(X_ERROR, "mapping %08x read only\n", off);
231	} else {
232		mapaddr = (pointer) mmap(NULL, len,
233					 PROT_READ | PROT_WRITE, MAP_SHARED,
234					 fd, off);
235		xf86Msg(X_ERROR, "mapping %08x read/write\n", off);
236	}
237	if (mapaddr == (pointer) -1) {
238		mapaddr = NULL;
239	}
240#ifdef NGLE_DEBUG
241	ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, len);
242#endif
243	return mapaddr;
244}
245
246static Bool
247NGLEProbe(DriverPtr drv, int flags)
248{
249	ScrnInfoPtr pScrn = NULL;
250	int i, fd, entity, wstype;
251       	GDevPtr *devSections;
252	int numDevSections;
253	char *dev;
254	const char *name;
255	uint32_t gid;
256	Bool foundScreen = FALSE;
257
258	if ((numDevSections = xf86MatchDevice(NGLE_DRIVER_NAME,
259					      &devSections)) <= 0)
260		return FALSE;
261
262
263	if ((fd = ngle_open(NGLE_DEFAULT_DEV)) == 0)
264		return FALSE;
265
266	if (ioctl(fd, WSDISPLAYIO_GTYPE, &wstype) == -1)
267		return FALSE;
268
269	if (wstype != WSDISPLAY_TYPE_STI)
270		return FALSE;
271
272	if (ioctl(fd, GCID, &gid) == -1)
273		return FALSE;
274
275	/* reject GIDs not in the table */
276	if ((name = xf86TokenToString(NGLEChipsets, gid)) == NULL)
277		return FALSE;
278
279	xf86Msg(X_INFO, "%s: found %s ( GID %08x )\n", __func__, name, gid);
280
281	if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
282		GDevPtr pGDev;
283
284		pGDev = xf86AddBusDeviceToConfigure(NGLE_DRIVER_NAME, BUS_NONE,
285			NULL, 0);
286		if (pGDev) {
287			/*
288			 * XF86Match???Instances() treat chipID and chipRev as
289			 * overrides, so clobber them here.
290			 */
291			pGDev->chipID = pGDev->chipRev = -1;
292	    	}
293	}
294
295	if (flags & PROBE_DETECT) {
296		return TRUE;
297	}
298
299	if (numDevSections > 1) {
300		xf86Msg(X_ERROR, "Ignoring additional device sections\n");
301		numDevSections = 1;
302	}
303	/* ok, at this point we know we've got a NGLE */
304	for (i = 0; i < numDevSections; i++) {
305
306		entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
307		pScrn = xf86ConfigFbEntity(NULL, 0, entity,
308		    NULL, NULL, NULL, NULL);
309		if (pScrn != NULL) {
310			foundScreen = TRUE;
311			pScrn->driverVersion = VERSION;
312			pScrn->driverName = NGLE_DRIVER_NAME;
313			pScrn->name = NGLE_NAME;
314			pScrn->Probe = NGLEProbe;
315			pScrn->PreInit = NGLEPreInit;
316			pScrn->ScreenInit = NGLEScreenInit;
317			pScrn->SwitchMode = NGLESwitchMode;
318			pScrn->AdjustFrame = NULL;
319			pScrn->EnterVT = NGLEEnterVT;
320			pScrn->LeaveVT = NGLELeaveVT;
321			pScrn->ValidMode = NGLEValidMode;
322
323		}
324	}
325	free(devSections);
326	return foundScreen;
327}
328
329static Bool
330NGLEPreInit(ScrnInfoPtr pScrn, int flags)
331{
332	NGLEPtr fPtr;
333	int default_depth, bitsperpixel, wstype;
334	const char *dev;
335	char *mod = NULL;
336	const char *reqSym = NULL;
337	Gamma zeros = {0.0, 0.0, 0.0};
338	DisplayModePtr mode;
339	MessageType from;
340	rgb rgbzeros = { 0, 0, 0 }, masks;
341
342	if (flags & PROBE_DETECT) return FALSE;
343
344	if (pScrn->numEntities != 1) return FALSE;
345
346	pScrn->monitor = pScrn->confScreen->monitor;
347
348	NGLEGetRec(pScrn);
349	fPtr = NGLEPTR(pScrn);
350
351	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
352
353	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
354	fPtr->fd = ngle_open(dev);
355	if (fPtr->fd == -1) {
356		return FALSE;
357	}
358
359	if (ioctl(fPtr->fd, WSDISPLAYIO_GET_FBINFO, &fPtr->fbi) == -1) {
360		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
361			   "ioctl WSDISPLAY_GINFO: %s\n",
362			   strerror(errno));
363		return FALSE;
364	}
365	if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) {
366		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
367			   "ioctl WSDISPLAY_GTYPE: %s\n",
368			   strerror(errno));
369		return FALSE;
370	}
371
372	/* Handle depth */
373	default_depth = fPtr->fbi.fbi_bitsperpixel <= 24 ? fPtr->fbi.fbi_bitsperpixel : 24;
374	bitsperpixel = fPtr->fbi.fbi_bitsperpixel == 15 ? 16 : fPtr->fbi.fbi_bitsperpixel;
375	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
376		bitsperpixel,
377		bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0))
378		return FALSE;
379
380	xf86PrintDepthBpp(pScrn);
381
382	/* color weight */
383	masks.red =   0x00ff0000;
384	masks.green = 0x0000ff00;
385	masks.blue =  0x000000ff;
386	if (!xf86SetWeight(pScrn, rgbzeros, masks))
387		return FALSE;
388
389	/* visual init */
390	if (!xf86SetDefaultVisual(pScrn, -1))
391		return FALSE;
392
393	/* We don't currently support DirectColor at > 8bpp */
394	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
395		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
396			   " (%s) is not supported at depth %d\n",
397			   xf86GetVisualName(pScrn->defaultVisual),
398			   pScrn->depth);
399		return FALSE;
400	}
401
402	xf86SetGamma(pScrn,zeros);
403
404	pScrn->progClock = TRUE;
405	pScrn->rgbBits   = 8;
406	pScrn->chipset   = "NGLE";
407	fPtr->fbmem_len = pScrn->videoRam  = fPtr->fbi.fbi_fbsize;
408
409	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
410		   pScrn->videoRam/1024);
411
412	/* handle options */
413	xf86CollectOptions(pScrn, NULL);
414	if (!(fPtr->Options = malloc(sizeof(NGLEOptions))))
415		return FALSE;
416	memcpy(fPtr->Options, NGLEOptions, sizeof(NGLEOptions));
417	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
418			   fPtr->Options);
419
420	/* fake video mode struct */
421	mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec));
422	mode->prev = mode;
423	mode->next = mode;
424	mode->name = "NGLE current mode";
425	mode->status = MODE_OK;
426	mode->type = M_T_BUILTIN;
427	mode->Clock = 0;
428	mode->HDisplay = fPtr->fbi.fbi_width;
429	mode->HSyncStart = 0;
430	mode->HSyncEnd = 0;
431	mode->HTotal = 0;
432	mode->HSkew = 0;
433	mode->VDisplay = fPtr->fbi.fbi_height;
434	mode->VSyncStart = 0;
435	mode->VSyncEnd = 0;
436	mode->VTotal = 0;
437	mode->VScan = 0;
438	mode->Flags = 0;
439	if (pScrn->modes != NULL) {
440		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
441		   "Ignoring mode specification from screen section\n");
442	}
443	pScrn->currentMode = pScrn->modes = mode;
444	pScrn->virtualX = fPtr->fbi.fbi_width;
445	pScrn->virtualY = fPtr->fbi.fbi_height;
446	pScrn->displayWidth = 2048;
447
448	/* Set the display resolution */
449	xf86SetDpi(pScrn, 0, 0);
450
451	from = X_DEFAULT;
452	fPtr->HWCursor = TRUE;
453	if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor))
454		from = X_CONFIG;
455	if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) {
456		from = X_CONFIG;
457		fPtr->HWCursor = FALSE;
458	}
459	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
460		fPtr->HWCursor ? "HW" : "SW");
461
462	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
463		NGLEFreeRec(pScrn);
464		return FALSE;
465	}
466
467	if (xf86LoadSubModule(pScrn, "exa") == NULL) {
468		NGLEFreeRec(pScrn);
469		return FALSE;
470	}
471
472	if (xf86LoadSubModule(pScrn, "ramdac") == NULL) {
473		NGLEFreeRec(pScrn);
474		return FALSE;
475	}
476
477	return TRUE;
478}
479
480static Bool
481NGLEScreenInit(SCREEN_INIT_ARGS_DECL)
482{
483	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
484	NGLEPtr fPtr = NGLEPTR(pScrn);
485	VisualPtr visual;
486	int ret, flags, width, height, i, j;
487	int wsmode = WSDISPLAYIO_MODE_MAPPED;
488	size_t len;
489
490#ifdef NGLE_DEBUG
491	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
492	       "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
493	       pScrn->bitsPerPixel,
494	       pScrn->depth,
495	       xf86GetVisualName(pScrn->defaultVisual),
496	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
497	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
498#endif
499
500	/* Switch to graphics mode - required before mmap */
501	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
502		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
503			   "ioctl WSDISPLAYIO_SMODE: %s\n",
504			   strerror(errno));
505		return FALSE;
506	}
507	fPtr->regs = ngle_mmap(0x40000, 0x80000000, fPtr->fd, 0);
508
509	if (fPtr->regs == NULL) {
510		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
511			   "ngle_mmap registers: %s\n", strerror(errno));
512		return FALSE;
513	}
514
515	fPtr->fbmem = ngle_mmap(fPtr->fbmem_len, 0, fPtr->fd, 0);
516	if (fPtr->fbmem == NULL) {
517		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
518			   "ngle_mmap fb: %s\n", strerror(errno));
519		return FALSE;
520	}
521
522	NGLESave(pScrn);
523	pScrn->vtSema = TRUE;
524
525	/* mi layer */
526	miClearVisualTypes();
527	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
528			      pScrn->rgbBits, TrueColor))
529		return FALSE;
530
531	if (!miSetPixmapDepths())
532		return FALSE;
533
534	height = pScrn->virtualY;
535	width = pScrn->virtualX;
536
537	ret = fbScreenInit(pScreen,
538			   fPtr->fbmem,
539			   width, height,
540			   pScrn->xDpi, pScrn->yDpi,
541			   pScrn->displayWidth,
542			   pScrn->bitsPerPixel);
543
544	if (!ret)
545		return FALSE;
546
547	if (pScrn->bitsPerPixel > 8) {
548		/* Fixup RGB ordering. */
549		visual = pScreen->visuals + pScreen->numVisuals;
550		while (--visual >= pScreen->visuals) {
551			if ((visual->class | DynamicClass) == DirectColor) {
552				visual->offsetRed   = pScrn->offset.red;
553				visual->offsetGreen = pScrn->offset.green;
554				visual->offsetBlue  = pScrn->offset.blue;
555				visual->redMask     = pScrn->mask.red;
556				visual->greenMask   = pScrn->mask.green;
557				visual->blueMask    = pScrn->mask.blue;
558			}
559		}
560	}
561
562	if (!fbPictureInit(pScreen, NULL, 0))
563		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
564			   "RENDER extension initialisation failed.");
565
566	xf86SetBlackWhitePixels(pScreen);
567	xf86SetBackingStore(pScreen);
568
569	if (fPtr) {
570		/* init accel here */
571		//xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using acceleration\n");
572	}
573
574	/* software cursor */
575	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
576
577	/* check for hardware cursor support */
578	NGLESetupCursor(pScreen);
579
580	/* colormap */
581	if (!miCreateDefColormap(pScreen))
582		return FALSE;
583
584	flags = CMAP_RELOAD_ON_MODE_SWITCH;
585	if(!xf86HandleColormaps(pScreen, 256, 8, NGLELoadPalette,
586				NULL, flags))
587		return FALSE;
588
589	pScreen->SaveScreen = NGLESaveScreen;
590
591#ifdef XvExtension
592	{
593		XF86VideoAdaptorPtr *ptr;
594
595		int n = xf86XVListGenericAdaptors(pScrn,&ptr);
596		if (n) {
597			xf86XVScreenInit(pScreen,ptr,n);
598		}
599	}
600#endif
601
602	/* Wrap the current CloseScreen function */
603	fPtr->CloseScreen = pScreen->CloseScreen;
604	pScreen->CloseScreen = NGLECloseScreen;
605
606	return TRUE;
607}
608
609static Bool
610NGLECloseScreen(CLOSE_SCREEN_ARGS_DECL)
611{
612	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
613	NGLEPtr fPtr = NGLEPTR(pScrn);
614
615	if (pScrn->vtSema) {
616		NGLERestore(pScrn);
617		if (munmap(fPtr->regs, 0x40000) == -1) {
618			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
619				   "munmap engine: %s\n", strerror(errno));
620		}
621
622		if (munmap(fPtr->fbmem, fPtr->fbmem_len) == -1) {
623			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
624				   "munmap fb: %s\n", strerror(errno));
625		}
626
627		fPtr->regs = NULL;
628		fPtr->fbmem = NULL;
629	}
630	pScrn->vtSema = FALSE;
631
632	/* unwrap CloseScreen */
633	pScreen->CloseScreen = fPtr->CloseScreen;
634	return (*pScreen->CloseScreen)(pScreen);
635}
636
637static Bool
638NGLEEnterVT(VT_FUNC_ARGS_DECL)
639{
640	SCRN_INFO_PTR(arg);
641
642	pScrn->vtSema = TRUE;
643	return TRUE;
644}
645
646static void
647NGLELeaveVT(VT_FUNC_ARGS_DECL)
648{
649}
650
651static Bool
652NGLESwitchMode(SWITCH_MODE_ARGS_DECL)
653{
654
655	/* Nothing else to do */
656	return TRUE;
657}
658
659static int
660NGLEValidMode(SCRN_ARG_TYPE, DisplayModePtr mode, Bool verbose, int flags)
661{
662
663	return MODE_OK;
664}
665
666static void
667NGLELoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
668	       LOCO *colors, VisualPtr pVisual)
669{
670	NGLEPtr fPtr = NGLEPTR(pScrn);
671	struct wsdisplay_cmap cmap;
672	unsigned char red[256],green[256],blue[256];
673	int i, indexMin=256, indexMax=0;
674
675	/* nothing to do if there is no color palette support */
676	if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0)
677		return;
678
679	cmap.count   = 1;
680	cmap.red   = red;
681	cmap.green = green;
682	cmap.blue  = blue;
683
684	if (numColors == 1) {
685		/* Optimisation */
686		cmap.index = indices[0];
687		red[0]   = colors[indices[0]].red;
688		green[0] = colors[indices[0]].green;
689		blue[0]  = colors[indices[0]].blue;
690		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
691			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
692	} else {
693		/*
694		 * Change all colors in 2 ioctls
695		 * and limit the data to be transferred.
696		 */
697		for (i = 0; i < numColors; i++) {
698			if (indices[i] < indexMin)
699				indexMin = indices[i];
700			if (indices[i] > indexMax)
701				indexMax = indices[i];
702		}
703		cmap.index = indexMin;
704		cmap.count = indexMax - indexMin + 1;
705		cmap.red = &red[indexMin];
706		cmap.green = &green[indexMin];
707		cmap.blue = &blue[indexMin];
708		/* Get current map. */
709		if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1)
710			ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno));
711		/* Change the colors that require updating. */
712		for (i = 0; i < numColors; i++) {
713			red[indices[i]]   = colors[indices[i]].red;
714			green[indices[i]] = colors[indices[i]].green;
715			blue[indices[i]]  = colors[indices[i]].blue;
716		}
717		/* Write the colormap back. */
718		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
719			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
720	}
721}
722
723static Bool
724NGLESaveScreen(ScreenPtr pScreen, int mode)
725{
726	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
727	NGLEPtr fPtr = NGLEPTR(pScrn);
728	int state;
729
730	if (!pScrn->vtSema)
731		return TRUE;
732
733	if (mode != SCREEN_SAVER_FORCER) {
734		state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON:
735		                            WSDISPLAYIO_VIDEO_OFF;
736		ioctl(fPtr->fd,
737		      WSDISPLAYIO_SVIDEO, &state);
738	}
739	return TRUE;
740}
741
742
743static void
744NGLESave(ScrnInfoPtr pScrn)
745{
746}
747
748static void
749NGLERestore(ScrnInfoPtr pScrn)
750{
751	NGLEPtr fPtr = NGLEPTR(pScrn);
752	int mode;
753
754	/* Restore the text mode */
755	mode = WSDISPLAYIO_MODE_EMUL;
756	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
757		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
758			   "error setting text mode %s\n", strerror(errno));
759	}
760}
761