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;
 }

Reply via email to