[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [Xpert]Re: DPMS, Screen blanking with Sun Creator3D (sun4u systems)



On Tue, 11 Dec 2001, Ferris McCormick wrote:

> On Fri, 7 Dec 2001, Antonio Prioglio wrote:
> 
> > On Thu, 6 Dec 2001, Ferris McCormick wrote:
[...]
> > 
> > I'd be getting a Creator 2D soon. I'll be happy to test it with a
> > GDM-17E10.
> > 
> > Saluti,
> > Antonio Prioglio [antonio.prioglio@britishlibrary.net]
> 
> Thanks for the interest.  I'll send out a patch file in the next day
> or so.  It modifies three source files:
> 	ffb.h
> 	ffb_driver.c
> 	ffb_dac.c
> and applies to the CVS version 4.1.99.1, of about November 1.  However
> the three files involved are dated 2001/05/04, and I haven't seen anything
> else posted which would indicate conflicting changes to the driver.

As indicated, attached source patch file puts some DPMS support into
the Sun Creator/Elite driver for XF86, release 4.1.99(.1?)-CVS.
The driver is in the Xfree source tree at (if I type all this right)
	xc/programs/Xserver/hw/xfree86/drivers/sunffb

In that directory, the command
	patch -b < sunffb-4.1.99-DPMSMode.patch
should successfully patch the files "ffb.h, ffb_driver.c, ffb_dac.c";
after that just 'make' in that directory should get you a new
"sunffb_drv.o" (assuming you have already built everything once.)

Now, with X inactive, go to wherever your existing drivers are
(something like /usr/X11R6/lib/modules/drivers depending on your
configuration), save the existing sunffb_drv.o, and bring in the new
one.

To play with it, make sure that the already-working-with-your-
Creator-card XF86Config file has the line
	Option	"DPMS"	"on"
in its "Monitor" section, and restart X.  "xset q" should now
report that you can use DPMS, and you can play with it.  Also,
if you want, "xset s on; xset s blank" should now work.  (If DPMS
Option is not set, the driver will not enable DPMS, but you can
change that behavior, of course.)

Also, keep in mind Jon Leonard's note I sent you.  I have no way
of knowing if his remarks apply to your configuration or not.

Good luck,
Regards,
Ferris

--
Ferris McCormick (P44646, MI) <fmccor@inforead.com>
Phone: (703) 392-0303
Fax:   (703) 392-0401

--- ffb.h.orig	Thu Dec  6 23:39:31 2001
+++ ffb.h	Thu Dec  6 23:53:59 2001
@@ -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,7 +241,8 @@
 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_driver.c.orig	Sat Nov 17 18:37:18 2001
+++ ffb_driver.c	Tue Dec 11 22:26:18 2001
@@ -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 +97,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 +942,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 +1099,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 +1116,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;
 }
--- ffb_dac.c.orig	Wed Dec  5 23:43:34 2001
+++ ffb_dac.c	Sat Dec  8 17:38:32 2001
@@ -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;
 }

Reply to: