Attached is a patch to the Sun Creator3D/Elite3D XF86 driver,
sunffb (XF86 4.2.0 release) which works for me on an Ultra 10 with
Creator 3D(Vertical, 2+). I don't know if it works for other
cards supported by this driver.
This patch is the same as the test version for XF86 4.1.99+, except
that
1. It applies to an officially released XF86 version,
2. It does not require that a couple lines be installed into
the header file 'ffb.h' by hand because of some mistake on
my part.
If anyone else uses a creator (or elite) card with XF86 and needs this,
I'd appreciate it if you'ld let me know if this works for you if you
have a chance.
Regards,
Ferris
--
Ferris McCormick (P44646, MI) <[EMAIL PROTECTED]>
Phone: (703) 392-0303
Fax: (703) 392-0401
--- ffb.h.orig Fri May 4 19:05:46 2001
+++ ffb.h Mon Jan 21 22:26:21 2002
@@ -43,6 +43,14 @@
#include "xf86drm.h"
#include "ffb_drishare.h"
#endif
+/*
+ Bring in the dpms definitions.
+*/
+#ifndef DPMS_SERVER
+#define DPMS_SERVER
+#endif /* DPMS_SERVER */
+#include "extensions/dpms.h"
+
/* Various offsets in virtual (ie. mmap()) spaces Linux and Solaris support. */
/* Note: do not mmap FFB_DFB8R_VOFF and following mappings using one mmap together
@@ -233,6 +241,9 @@
extern void FFBDacFini(FFBPtr);
extern void FFBDacEnterVT(FFBPtr);
extern void FFBDacLeaveVT(FFBPtr);
+extern Bool FFBDacSaveScreen(FFBPtr, int);
+extern void FFBDacDPMSMode(FFBPtr, int, int);
+
/* Exported WID layer routines. */
extern void FFBWidPoolInit(FFBPtr);
--- ffb_dac.c.orig Thu Apr 5 17:42:33 2001
+++ ffb_dac.c Mon Jan 21 22:25:19 2002
@@ -33,6 +33,14 @@
#include "xf86DDC.h"
+/*
+ Used for stabalize time after playing with power management on the display
+*/
+
+#ifndef DPMS_SPIN_COUNT
+#define DPMS_SPIN_COUNT 100
+#endif /* DPMS_SPIN_COUNT */
+
/* Cursor programming */
void
@@ -493,4 +501,119 @@
/* Restore kernel DAC and x-channel state. */
dac_state_restore(pFfb, &p->kern_dac_state);
restore_kernel_xchannel(pFfb);
+}
+
+
+/* DPMS stuff, courtesy of a hint from David S. Miller.
+ 05.xii.01, FEM
+*/
+
+
+/*
+ I don't know why, if at all, this is needed, but JJ or DSM does it
+ on restore. I observe that when just blanking/unblanking, everything
+ works fine without it, but that sometimes DPMS -> Standby actually
+ results in Off. Maybe related?
+*/
+
+static __inline__ void
+SPIN(ffb_dacPtr d, int count) {
+ while(count-- > 0) {
+ (void) DACCFG_READ(d, FFBDAC_CFG_TGVC);
+ }
+ return;
+}
+
+
+/* Screen save (blank) restore */
+
+Bool
+FFBDacSaveScreen(FFBPtr pFfb, int mode) {
+ int tmp;
+ ffb_dacPtr dac;
+ if(!pFfb) return FALSE; /* Is there any way at all this could happen? */
+ else dac = pFfb -> dac;
+
+ tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get the timing information */
+
+ switch(mode) {
+ case SCREEN_SAVER_ON:
+ case SCREEN_SAVER_CYCLE:
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case SCREEN_SAVER_OFF:
+ case SCREEN_SAVER_FORCER:
+ tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */
+ break;
+
+ default:
+ return FALSE; /* Don't know what to do; gently fail. */
+ }
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, tmp); /* Restore timing register, video set as
+asked */
+ SPIN(dac, DPMS_SPIN_COUNT/10);
+ return TRUE;
+}
+
+/* DPMS Control, also hinted at by David Miller.
+
+ The rule seems to be:
+
+ StandBy = -HSYNC +VSYNC -VIDEO
+ Suspend = +HSYNC -VSYNC -VIDEO
+ Off = -HSYNC -VSYNC -VIDEO
+ On = +HSYNC +VSINC +VIDEO
+
+ If you don't force video off, someone periodically tries to turn the
+ monitor on for some reason. I don't know who or why, so I kill the video
+ when trying to go into some sort of energy saving mode. (In real life,
+ 'xset s blank s xx' could well have taken care of this.)
+
+ Also, on MY monitor, StandBy as above defined (-H+V-Vid) in fact
+ gives the same as Off, which I don't want. Hence, I just do (-Vid)
+
+ 05.xii.01, FEM
+ 08.xii.01, FEM
+*/
+
+void
+FFBDacDPMSMode(FFBPtr pFfb, int DPMSMode, int flags) {
+ int tmp;
+ ffb_dacPtr dac = pFfb -> dac;
+
+ tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get timing control */
+
+ switch(DPMSMode) {
+
+ case DPMSModeOn:
+ tmp &= ~(FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Turn off VSYNC, HSYNC
+ disable bits */
+ tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */
+ break;
+
+ case DPMSModeStandby:
+#ifdef DPMS_TRUE_STANDBY
+ tmp |= FFBDAC_CFG_TGEN_HSD; /* HSYNC = OFF */
+#endif /* DPMS_TRUE_STANDBY */
+ tmp &= ~FFBDAC_CFG_TGEN_VSD; /* VSYNC = ON */
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case DPMSModeSuspend:
+ tmp |= FFBDAC_CFG_TGEN_VSD; /* VSYNC = OFF */
+ tmp &= ~FFBDAC_CFG_TGEN_HSD; /* HSYNC = ON */
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case DPMSModeOff:
+ tmp |= (FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Kill HSYNC, VSYNC both
+*/
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video
+*/
+ break;
+
+ default:
+ return; /* If we get here, we really should log an error */
+ }
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN,tmp); /* Restore timing register, video set as
+asked */
+ SPIN(dac, DPMS_SPIN_COUNT); /* Is this necessary? Why? */
+ return;
}
--- ffb_driver.c.orig Fri May 4 19:05:46 2001
+++ ffb_driver.c Mon Jan 21 22:25:19 2002
@@ -60,7 +60,9 @@
static void FFBFreeScreen(int scrnIndex, int flags);
static int FFBValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
int flags);
+/* DPMS Mode hook */
+static void FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags);
/* ffb_dga.c */
extern void FFB_InitDGA(ScreenPtr pScreen);
@@ -94,13 +96,15 @@
typedef enum {
OPTION_SW_CURSOR,
OPTION_HW_CURSOR,
- OPTION_NOACCEL
+ OPTION_NOACCEL,
+ OPTION_DPMS /* Establish a hook for DPMS Mode */
} FFBOpts;
static const OptionInfoRec FFBOptions[] = {
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DPMS, "DPMS", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -937,6 +941,15 @@
pScreen->CloseScreen = FFBCloseScreen;
pScreen->SaveScreen = FFBSaveScreen;
+ /*
+ Check finally for DPMS Mode. If so, set up a hook for it. If not,
+ keep dpms disabled.
+ */
+
+ if (xf86ReturnOptValBool(pFfb->Options, OPTION_DPMS, FALSE)) {
+ (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
+ }
+
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1) {
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -1085,11 +1098,14 @@
/* Mandatory */
static Bool
FFBSaveScreen(ScreenPtr pScreen, int mode)
- /* this function should blank the screen when unblank is FALSE and
- unblank it when unblank is TRUE -- it doesn't actually seem to be
- used for much though */
+ /* This function blanks the screen when mode=SCREEN_SAVER_ON and
+ unblanks it when mode=SCREEN_SAVER_OFF. It is used internally in the
+ FFBScreenInit code `for aesthetic reasons,' and it is used for
+ blanking if you set "xset s on s blank." The work (such as it is) is
+ done in "ffb_dac.c" `for aesthetic reasons.'
+ */
{
- return TRUE;
+ return FFBDacSaveScreen(GET_FFB_FROM_SCREEN(pScreen), mode);
}
/*
@@ -1099,4 +1115,15 @@
FFBSync(ScrnInfoPtr pScrn)
{
return;
+}
+
+/*
+ Hook for DPMS Mode.
+*/
+
+static void
+FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
+{
+ FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
+ return;
}