[Nouveau] [PATCH] Fix DPMS and Xvideo with Option Randr12 enabled and monitors side-by-side

Bernhard Kaindl bk at suse.de
Wed Sep 5 11:17:49 PDT 2007


On Wed, 5 Sep 2007, Bernhard Kaindl wrote:
>
> I can trick mplayer with Xv to work now side-by-side by doing chvt 1 and
> chvt7 (with the chvt fix which I just sent) before starting using mplayer.
> I slight guess that this is might be related to the DPMS fix/hack with
> last_mode which I sent initially because DPMS also works again after a
> VC switch when the monitors are side-by-side. I guess that last_mode might
> be wrongly set in that case, will check.

Done.

Option Randr12 now (next to) fully works for me with a simple dual head setup,
with this patch for the master branch:

diff --git a/src/nv_output.c b/src/nv_output.c
index 7499247..95ee772 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -157,7 +157,7 @@ nv_digital_output_dpms(xf86OutputPtr output, int mode)
  	if (crtc) {
  		nv_crtc = crtc->driver_private;

-		fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL) & 0xCfffffCC; 
+		fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL);
  		switch(mode) {
  			case DPMSModeStandby:
  			case DPMSModeSuspend:
@@ -167,8 +167,9 @@ nv_digital_output_dpms(xf86OutputPtr output, int mode)
  				nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
  				break;
  			case DPMSModeOn:
-				/* restore previous mode */
-				nv_output_mode_set(output, last_mode, NULL);
+				/* disable cutting the TMDS output */
+				fpcontrol &= ~0x20000022;
+				nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
  				break;
  		}
  	}

This is the minium to reverse my previous patch which was more a hack to
get something working in the randr branch, it was never tested in the
master branch by me before I was applied as I wasn't aware that Randr12
has now been merged into the master branch (but I subscribed the nouveau
mailing lists now and monitor the git log as well).

This is only the minimum patch to make it clear what the change actually
does, the cleanup to reverse everything which my initial hack patch did
is larger and the real change would not be as obvioius then.

How I arrived at this patch:

First, I just cleared the "cut TMDS output" bits in the fpcontrol variable,
and changed the code back to not call nv_output_mode_set but nvWriteRAMDAC()
as it was before which restored the initial state which re-enabled the output
(monitors got signal again, they woke up, turned on backlight, but still showed
a black screen) but that didn't make the X output come back.

Second, I tried "fpcontrol |= pNV->fpSync" (which was there initiallty) in
addition to restore any saved fpSync bits, but fpSync turned out to be
all Nulls at that point so it had no effect.

Third, I remoed "& 0xCfffffCC" which you can see in the patch above and that
made additional bits appear in fpcontrol. cutting TMDS outputs still worked
as before but in the "case DPMSModeOn:" the X screen came back to light! YES!

So that was the fix. As I do not know which other cards might need which
bits in fpcontrol, I'd just use the patch as is and not try to find which
bits we could mask out when reading the register. After all what we read
is in set in the register and we might need to write all of them back or
we might break something as it happened with my G70 card.

Here is the cleanup patch with comments:

--- src/nv_output.c	2007-09-05 19:43:41.000000000 +0200
+++ src/nv_output.c	2007-09-05 19:29:36.000000000 +0200
@@ -138,40 +138,28 @@
  }

  static void
-nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
-		   DisplayModePtr adjusted_mode);
-
-static DisplayModePtr last_mode;
-
-static void
# I added these in my previous patch, obsolete
  nv_digital_output_dpms(xf86OutputPtr output, int mode)
  {
-	NVOutputPrivatePtr nv_output = output->driver_private;
# remove unused variable
  	xf86CrtcPtr crtc = output->crtc;
-	ScrnInfoPtr pScrn = output->scrn;
-	NVPtr pNv = NVPTR(pScrn);
-	NVCrtcPrivatePtr nv_crtc;
# moved these into the if-clause where they are used
-
-	CARD32 fpcontrol;

  	if (crtc) {
-		nv_crtc = crtc->driver_private;
+		NVPtr pNv = NVPTR(output->scrn);
# integrated "pScrn = output->scrn" as we only need pScrn to get pNv.
+		NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
# just moved declaration down here

-		fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL); 
+		CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL); 
# just moved declaration down here
  		switch(mode) {
  			case DPMSModeStandby:
  			case DPMSModeSuspend:
  			case DPMSModeOff:
  				/* cut the TMDS output */
  				fpcontrol |= 0x20000022;
-				nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
  				break;
  			case DPMSModeOn:
  				/* disable cutting the TMDS output */
  				fpcontrol &= ~0x20000022;
-				nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
  				break;
  		}
+		nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
# nvWriteRAMDAC was placed here before, so there is only one call to it
  	}
  }

@@ -343,7 +331,6 @@
      int bpp;
      NVPtr pNv = NVPTR(pScrn);
      NVFBLayout *pLayout = &pNv->CurrentLayout;
-    last_mode = mode;
# clenup the no longer used last_mode variable from my previous patch,
# the definition is removed in the first lines of the cleanup patch
      RIVA_HW_STATE *state, *sv_state;
      Bool is_fp = FALSE;
      NVOutputRegPtr regp, savep;

Clean patches without comments in attachment.

Bernhard
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nouveau-fix-Randr12-DPMS-properly-minimum.diff
Type: text/x-patch
Size: 931 bytes
Desc: 
Url : http://lists.freedesktop.org/archives/nouveau/attachments/20070905/7802d9fd/attachment.bin 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nouveau-fix-Randr12-DPMS-properly-cleanup.diff
Type: text/x-patch
Size: 1655 bytes
Desc: 
Url : http://lists.freedesktop.org/archives/nouveau/attachments/20070905/7802d9fd/attachment-0001.bin 


More information about the Nouveau mailing list