1
2/*
3 * Leo (ZX) framebuffer driver.
4 *
5 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <string.h>
30
31#include "xf86.h"
32#include "xf86_OSproc.h"
33#include "mipointer.h"
34#include "micmap.h"
35
36#include "fb.h"
37#include "xf86cmap.h"
38#include "leo.h"
39
40static const OptionInfoRec * LeoAvailableOptions(int chipid, int busid);
41static void	LeoIdentify(int flags);
42static Bool	LeoProbe(DriverPtr drv, int flags);
43static Bool	LeoPreInit(ScrnInfoPtr pScrn, int flags);
44static Bool	LeoScreenInit(SCREEN_INIT_ARGS_DECL);
45static Bool	LeoEnterVT(VT_FUNC_ARGS_DECL);
46static void	LeoLeaveVT(VT_FUNC_ARGS_DECL);
47static Bool	LeoCloseScreen(CLOSE_SCREEN_ARGS_DECL);
48static Bool	LeoSaveScreen(ScreenPtr pScreen, int mode);
49
50/* Required if the driver supports mode switching */
51static Bool	LeoSwitchMode(SWITCH_MODE_ARGS_DECL);
52/* Required if the driver supports moving the viewport */
53static void	LeoAdjustFrame(ADJUST_FRAME_ARGS_DECL);
54
55/* Optional functions */
56static void	LeoFreeScreen(FREE_SCREEN_ARGS_DECL);
57static ModeStatus LeoValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
58			       Bool verbose, int flags);
59
60void LeoSync(ScrnInfoPtr pScrn);
61
62#define LEO_VERSION 4000
63#define LEO_NAME "SUNLEO"
64#define LEO_DRIVER_NAME "sunleo"
65#define LEO_MAJOR_VERSION PACKAGE_VERSION_MAJOR
66#define LEO_MINOR_VERSION PACKAGE_VERSION_MINOR
67#define LEO_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
68
69/*
70 * This contains the functions needed by the server after loading the driver
71 * module.  It must be supplied, and gets passed back by the SetupProc
72 * function in the dynamic case.  In the static case, a reference to this
73 * is compiled in, and this requires that the name of this DriverRec be
74 * an upper-case version of the driver name.
75 */
76
77_X_EXPORT DriverRec SUNLEO = {
78    LEO_VERSION,
79    LEO_DRIVER_NAME,
80    LeoIdentify,
81    LeoProbe,
82    LeoAvailableOptions,
83    NULL,
84    0
85};
86
87typedef enum {
88    OPTION_SW_CURSOR,
89    OPTION_HW_CURSOR,
90    OPTION_NOACCEL
91} LeoOpts;
92
93static const OptionInfoRec LeoOptions[] = {
94    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
95    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
96    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
97    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
98};
99
100#ifdef XFree86LOADER
101
102static MODULESETUPPROTO(leoSetup);
103
104static XF86ModuleVersionInfo sunleoVersRec =
105{
106	"sunleo",
107	MODULEVENDORSTRING,
108	MODINFOSTRING1,
109	MODINFOSTRING2,
110	XORG_VERSION_CURRENT,
111	LEO_MAJOR_VERSION, LEO_MINOR_VERSION, LEO_PATCHLEVEL,
112	ABI_CLASS_VIDEODRV,
113	ABI_VIDEODRV_VERSION,
114	MOD_CLASS_VIDEODRV,
115	{0,0,0,0}
116};
117
118_X_EXPORT XF86ModuleData sunleoModuleData = { &sunleoVersRec, leoSetup, NULL };
119
120pointer
121leoSetup(pointer module, pointer opts, int *errmaj, int *errmin)
122{
123    static Bool setupDone = FALSE;
124
125    if (!setupDone) {
126	setupDone = TRUE;
127	xf86AddDriver(&SUNLEO, module, 0);
128
129	/*
130	 * Modules that this driver always requires can be loaded here
131	 * by calling LoadSubModule().
132	 */
133
134	/*
135	 * The return value must be non-NULL on success even though there
136	 * is no TearDownProc.
137	 */
138	return (pointer)TRUE;
139    } else {
140	if (errmaj) *errmaj = LDR_ONCEONLY;
141	return NULL;
142    }
143}
144
145#endif /* XFree86LOADER */
146
147static Bool
148LeoGetRec(ScrnInfoPtr pScrn)
149{
150    /*
151     * Allocate an LeoRec, and hook it into pScrn->driverPrivate.
152     * pScrn->driverPrivate is initialised to NULL, so we can check if
153     * the allocation has already been done.
154     */
155    if (pScrn->driverPrivate != NULL)
156	return TRUE;
157
158    pScrn->driverPrivate = xnfcalloc(sizeof(LeoRec), 1);
159    return TRUE;
160}
161
162static void
163LeoFreeRec(ScrnInfoPtr pScrn)
164{
165    LeoPtr pLeo;
166
167    if (pScrn->driverPrivate == NULL)
168	return;
169
170    pLeo = GET_LEO_FROM_SCRN(pScrn);
171
172    free(pScrn->driverPrivate);
173    pScrn->driverPrivate = NULL;
174
175    return;
176}
177
178static const OptionInfoRec *
179LeoAvailableOptions(int chipid, int busid)
180{
181    return LeoOptions;
182}
183
184/* Mandatory */
185static void
186LeoIdentify(int flags)
187{
188    xf86Msg(X_INFO, "%s: driver for Leo (ZX)\n", LEO_NAME);
189}
190
191
192/* Mandatory */
193static Bool
194LeoProbe(DriverPtr drv, int flags)
195{
196    int i;
197    GDevPtr *devSections;
198    int *usedChips;
199    int numDevSections;
200    int numUsed;
201    Bool foundScreen = FALSE;
202    EntityInfoPtr pEnt;
203
204    /*
205     * The aim here is to find all cards that this driver can handle,
206     * and for the ones not already claimed by another driver, claim the
207     * slot, and allocate a ScrnInfoRec.
208     *
209     * This should be a minimal probe, and it should under no circumstances
210     * change the state of the hardware.  Because a device is found, don't
211     * assume that it will be used.  Don't do any initialisations other than
212     * the required ScrnInfoRec initialisations.  Don't allocate any new
213     * data structures.
214     */
215
216    /*
217     * Next we check, if there has been a chipset override in the config file.
218     * For this we must find out if there is an active device section which
219     * is relevant, i.e., which has no driver specified or has THIS driver
220     * specified.
221     */
222
223    if ((numDevSections = xf86MatchDevice(LEO_DRIVER_NAME,
224					  &devSections)) <= 0) {
225	/*
226	 * There's no matching device section in the config file, so quit
227	 * now.
228	 */
229	return FALSE;
230    }
231
232    /*
233     * We need to probe the hardware first.  We then need to see how this
234     * fits in with what is given in the config file, and allow the config
235     * file info to override any contradictions.
236     */
237
238    numUsed = xf86MatchSbusInstances(LEO_NAME, SBUS_DEVICE_LEO,
239		   devSections, numDevSections,
240		   drv, &usedChips);
241
242    free(devSections);
243    if (numUsed <= 0)
244	return FALSE;
245
246    if (flags & PROBE_DETECT)
247	foundScreen = TRUE;
248    else for (i = 0; i < numUsed; i++) {
249	pEnt = xf86GetEntityInfo(usedChips[i]);
250
251	/*
252	 * Check that nothing else has claimed the slots.
253	 */
254	if(pEnt->active) {
255	    ScrnInfoPtr pScrn;
256
257	    /* Allocate a ScrnInfoRec and claim the slot */
258	    pScrn = xf86AllocateScreen(drv, 0);
259
260	    /* Fill in what we can of the ScrnInfoRec */
261	    pScrn->driverVersion = LEO_VERSION;
262	    pScrn->driverName	 = LEO_DRIVER_NAME;
263	    pScrn->name		 = LEO_NAME;
264	    pScrn->Probe	 = LeoProbe;
265	    pScrn->PreInit	 = LeoPreInit;
266	    pScrn->ScreenInit	 = LeoScreenInit;
267  	    pScrn->SwitchMode	 = LeoSwitchMode;
268  	    pScrn->AdjustFrame	 = LeoAdjustFrame;
269	    pScrn->EnterVT	 = LeoEnterVT;
270	    pScrn->LeaveVT	 = LeoLeaveVT;
271	    pScrn->FreeScreen	 = LeoFreeScreen;
272	    pScrn->ValidMode	 = LeoValidMode;
273	    xf86AddEntityToScreen(pScrn, pEnt->index);
274	    foundScreen = TRUE;
275	}
276	free(pEnt);
277    }
278    free(usedChips);
279    return foundScreen;
280}
281
282/* Mandatory */
283static Bool
284LeoPreInit(ScrnInfoPtr pScrn, int flags)
285{
286    LeoPtr pLeo;
287    sbusDevicePtr psdp;
288    MessageType from;
289    int i;
290
291    if (flags & PROBE_DETECT) return FALSE;
292
293    /*
294     * Note: This function is only called once at server startup, and
295     * not at the start of each server generation.  This means that
296     * only things that are persistent across server generations can
297     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
298     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
299     * are too, and should be used for data that must persist across
300     * server generations.
301     *
302     * Per-generation data should be allocated with
303     * AllocateScreenPrivateIndex() from the ScreenInit() function.
304     */
305
306    /* Allocate the LeoRec driverPrivate */
307    if (!LeoGetRec(pScrn)) {
308	return FALSE;
309    }
310    pLeo = GET_LEO_FROM_SCRN(pScrn);
311
312    /* Set pScrn->monitor */
313    pScrn->monitor = pScrn->confScreen->monitor;
314
315    /* This driver doesn't expect more than one entity per screen */
316    if (pScrn->numEntities > 1)
317	return FALSE;
318    /* This is the general case */
319    for (i = 0; i < pScrn->numEntities; i++) {
320	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
321
322	/* LEO is purely SBUS */
323	if (pEnt->location.type == BUS_SBUS) {
324	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
325	    pLeo->psdp = psdp;
326	} else
327	    return FALSE;
328    }
329
330    /*********************
331    deal with depth
332    *********************/
333
334    if (!xf86SetDepthBpp(pScrn, 32, 0, 32, Support32bppFb)) {
335	return FALSE;
336    } else {
337	/* Check that the returned depth is one we support */
338	switch (pScrn->depth) {
339	case 32:
340	case 24:
341	    /* OK */
342	    break;
343	default:
344	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
345		       "Given depth (%d) is not supported by this driver\n",
346		       pScrn->depth);
347	    return FALSE;
348	}
349    }
350
351    /* Collect all of the relevant option flags (fill in pScrn->options) */
352    xf86CollectOptions(pScrn, NULL);
353    /* Process the options */
354    if (!(pLeo->Options = malloc(sizeof(LeoOptions))))
355	return FALSE;
356    memcpy(pLeo->Options, LeoOptions, sizeof(LeoOptions));
357    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pLeo->Options);
358
359    /*
360     * This must happen after pScrn->display has been set because
361     * xf86SetWeight references it.
362     */
363    if (pScrn->depth > 8) {
364	rgb weight = {0, 0, 0};
365	rgb mask = {0xff, 0xff00, 0xff0000};
366
367	if (!xf86SetWeight(pScrn, weight, mask)) {
368	    return FALSE;
369	}
370    }
371
372    if (!xf86SetDefaultVisual(pScrn, -1)) {
373	return FALSE;
374    } else {
375	/* We don't currently support DirectColor */
376	if (pScrn->defaultVisual != TrueColor) {
377	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
378		       " (%s) is not supported\n",
379		       xf86GetVisualName(pScrn->defaultVisual));
380	    return FALSE;
381	}
382    }
383
384    /*
385     * The new cmap code requires this to be initialised.
386     */
387
388    {
389	Gamma zeros = {0.0, 0.0, 0.0};
390
391	if (!xf86SetGamma(pScrn, zeros)) {
392	    return FALSE;
393	}
394    }
395
396    /* Set the bits per RGB for 8bpp mode */
397    from = X_DEFAULT;
398
399    /* determine whether we use hardware or software cursor */
400
401    pLeo->HWCursor = TRUE;
402    if (xf86GetOptValBool(pLeo->Options, OPTION_HW_CURSOR, &pLeo->HWCursor))
403	from = X_CONFIG;
404    if (xf86ReturnOptValBool(pLeo->Options, OPTION_SW_CURSOR, FALSE)) {
405	from = X_CONFIG;
406	pLeo->HWCursor = FALSE;
407    }
408
409    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
410		pLeo->HWCursor ? "HW" : "SW");
411
412    if (xf86ReturnOptValBool(pLeo->Options, OPTION_NOACCEL, FALSE)) {
413	pLeo->NoAccel = TRUE;
414	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
415    }
416
417    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
418	LeoFreeRec(pScrn);
419	return FALSE;
420    }
421
422    if (pLeo->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
423	LeoFreeRec(pScrn);
424	return FALSE;
425    }
426
427    /*********************
428    set up clock and mode stuff
429    *********************/
430
431    pScrn->progClock = TRUE;
432
433    if(pScrn->display->virtualX || pScrn->display->virtualY) {
434	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
435		   "Leo does not support a virtual desktop\n");
436	pScrn->display->virtualX = 0;
437	pScrn->display->virtualY = 0;
438    }
439
440    xf86SbusUseBuiltinMode(pScrn, pLeo->psdp);
441    pScrn->currentMode = pScrn->modes;
442    pScrn->displayWidth = pScrn->virtualX;
443
444    /* Set display resolution */
445    xf86SetDpi(pScrn, 0, 0);
446
447    return TRUE;
448}
449
450/* Mandatory */
451
452/* This gets called at the start of each server generation */
453
454static Bool
455LeoScreenInit(SCREEN_INIT_ARGS_DECL)
456{
457    ScrnInfoPtr pScrn;
458    LeoPtr pLeo;
459    int ret;
460    VisualPtr visual;
461    extern Bool LeoAccelInit(ScreenPtr pScreen, LeoPtr pLeo);
462
463    /*
464     * First get the ScrnInfoRec
465     */
466    pScrn = xf86ScreenToScrn(pScreen);
467
468    pLeo = GET_LEO_FROM_SCRN(pScrn);
469
470    /* Map the Leo memory */
471    pLeo->fb =
472	xf86MapSbusMem (pLeo->psdp, LEO_FB0_VOFF, 0x803000);
473
474    if (! pLeo->fb)
475	return FALSE;
476
477    /* Darken the screen for aesthetic reasons and set the viewport */
478    LeoSaveScreen(pScreen, SCREEN_SAVER_ON);
479
480    /*
481     * The next step is to setup the screen's visuals, and initialise the
482     * framebuffer code.  In cases where the framebuffer's default
483     * choices for things like visual layouts and bits per RGB are OK,
484     * this may be as simple as calling the framebuffer's ScreenInit()
485     * function.  If not, the visuals will need to be setup before calling
486     * a fb ScreenInit() function and fixed up after.
487     */
488
489    /*
490     * Reset visual list.
491     */
492    miClearVisualTypes();
493
494    /* Setup the visuals we support. */
495
496    if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
497			  pScrn->defaultVisual))
498	return FALSE;
499
500    /*
501     * Call the framebuffer layer's ScreenInit function, and fill in other
502     * pScreen fields.
503     */
504
505    ret = fbScreenInit(pScreen, pLeo->fb, pScrn->virtualX,
506		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
507		       2048, pScrn->bitsPerPixel);
508    if (!ret)
509	return FALSE;
510
511    xf86SetBackingStore(pScreen);
512    xf86SetSilkenMouse(pScreen);
513
514    xf86SetBlackWhitePixels(pScreen);
515
516    if (pScrn->bitsPerPixel > 8) {
517        /* Fixup RGB ordering */
518        visual = pScreen->visuals + pScreen->numVisuals;
519        while (--visual >= pScreen->visuals) {
520	    if ((visual->class | DynamicClass) == DirectColor) {
521		visual->offsetRed = pScrn->offset.red;
522		visual->offsetGreen = pScrn->offset.green;
523		visual->offsetBlue = pScrn->offset.blue;
524		visual->redMask = pScrn->mask.red;
525		visual->greenMask = pScrn->mask.green;
526		visual->blueMask = pScrn->mask.blue;
527	    }
528	}
529    }
530
531    if (!LeoAccelInit(pScreen, pLeo))
532	return FALSE;
533
534    if (!pLeo->NoAccel)
535	xf86Msg(X_INFO, "%s: Using acceleration\n", pLeo->psdp->device);
536
537    /* Initialise cursor functions */
538    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
539
540    /* Initialize HW cursor layer.
541       Must follow software cursor initialization*/
542    if (pLeo->HWCursor) {
543	extern Bool LeoHWCursorInit(ScreenPtr pScreen);
544
545	if(!LeoHWCursorInit(pScreen)) {
546	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
547		       "Hardware cursor initialization failed\n");
548	    return(FALSE);
549	}
550	xf86SbusHideOsHwCursor(pLeo->psdp);
551    }
552
553    /* Initialise default colourmap */
554    if (!miCreateDefColormap(pScreen))
555	return FALSE;
556
557    pLeo->CloseScreen = pScreen->CloseScreen;
558    pScreen->CloseScreen = LeoCloseScreen;
559    pScreen->SaveScreen = LeoSaveScreen;
560
561    /* Report any unused options (only for the first generation) */
562    if (serverGeneration == 1) {
563	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
564    }
565
566    /* unblank the screen */
567    LeoSaveScreen(pScreen, SCREEN_SAVER_OFF);
568
569    /* Done */
570    return TRUE;
571}
572
573
574/* Usually mandatory */
575static Bool
576LeoSwitchMode(SWITCH_MODE_ARGS_DECL)
577{
578    return TRUE;
579}
580
581
582/*
583 * This function is used to initialize the Start Address - the first
584 * displayed location in the video memory.
585 */
586/* Usually mandatory */
587static void
588LeoAdjustFrame(ADJUST_FRAME_ARGS_DECL)
589{
590    /* we don't support virtual desktops */
591    return;
592}
593
594extern void LeoVtChange (ScreenPtr pScreen, int enter);
595
596/*
597 * This is called when VT switching back to the X server.  Its job is
598 * to reinitialise the video mode.
599 */
600
601/* Mandatory */
602static Bool
603LeoEnterVT(VT_FUNC_ARGS_DECL)
604{
605    SCRN_INFO_PTR(arg);
606    LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn);
607
608    pLeo->vtSema = FALSE;
609    LeoVtChange (pScrn->pScreen, TRUE);
610    if (pLeo->HWCursor)
611	xf86SbusHideOsHwCursor (pLeo->psdp);
612    return TRUE;
613}
614
615
616/*
617 * This is called when VT switching away from the X server.
618 */
619
620/* Mandatory */
621static void
622LeoLeaveVT(VT_FUNC_ARGS_DECL)
623{
624    SCRN_INFO_PTR(arg);
625    LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn);
626
627    LeoVtChange (pScrn->pScreen, FALSE);
628    pLeo->vtSema = TRUE;
629}
630
631
632/*
633 * This is called at the end of each server generation.  It restores the
634 * original (text) mode.  It should really also unmap the video memory too.
635 */
636
637/* Mandatory */
638static Bool
639LeoCloseScreen(CLOSE_SCREEN_ARGS_DECL)
640{
641    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
642    LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn);
643
644    pScrn->vtSema = FALSE;
645    xf86UnmapSbusMem(pLeo->psdp, pLeo->fb, 0x803000);
646
647    if (pLeo->HWCursor)
648	xf86SbusHideOsHwCursor (pLeo->psdp);
649
650    pScreen->CloseScreen = pLeo->CloseScreen;
651    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
652    return FALSE;
653}
654
655
656/* Free up any per-generation data structures */
657
658/* Optional */
659static void
660LeoFreeScreen(FREE_SCREEN_ARGS_DECL)
661{
662    SCRN_INFO_PTR(arg);
663    LeoFreeRec(pScrn);
664}
665
666
667/* Checks if a mode is suitable for the selected chipset. */
668
669/* Optional */
670static ModeStatus
671LeoValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
672{
673    if (mode->Flags & V_INTERLACE)
674	return(MODE_BAD);
675
676    return(MODE_OK);
677}
678
679/* Do screen blanking */
680
681/* Mandatory */
682static Bool
683LeoSaveScreen(ScreenPtr pScreen, int mode)
684    /* this function should blank the screen when unblank is FALSE and
685       unblank it when unblank is TRUE -- it doesn't actually seem to be
686       used for much though */
687{
688    return TRUE;
689}
690
691/*
692 * This is the implementation of the Sync() function.
693 */
694void
695LeoSync(ScrnInfoPtr pScrn)
696{
697    return;
698}
699