xf86-video-intel: Branch 'modesetting' - 5 commits - src/i810_reg.h src/i830_driver.c src/i830.h src/i830_sdvo.c src/i830_sdvo.h src/i830_sdvo_regs.h

Eric Anholt anholt at kemper.freedesktop.org
Tue Apr 25 02:56:11 EEST 2006


 src/i810_reg.h       |    5 
 src/i830.h           |    8 +
 src/i830_driver.c    |   43 +++++-
 src/i830_sdvo.c      |  319 +++++++++++++++++++++++++++++++++------------------
 src/i830_sdvo.h      |   54 ++++++++
 src/i830_sdvo_regs.h |    6 
 6 files changed, 315 insertions(+), 120 deletions(-)

New commits:
diff-tree a555e28e5afc81969ef7b28482e654cc26b3a446 (from cc70e6b789a1901bbe4e3501b6b654542d3cdc20)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 16:55:44 2006 -0700

    Correct some SDVO-related register definitions.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index dee39ce..53c65bb 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -757,11 +757,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SDVO_INTERRUPT_ENABLE			(1 << 26)
 /* Programmed value is multiplier - 1, up to 5x.  alv, gdg only */
 #define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PHASE_SELECT_MASK			(15 << 23)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 23)
+#define SDVO_PHASE_SELECT_MASK			(15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
 #define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
 #define SDVOC_GANG_MODE				(1 << 16)
 #define SDVO_BORDER_ENABLE			(1 << 7)
+#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
 #define SDVO_DETECTED				(1 << 2)
 /* Bits to be preserved when writing */
 #define SDVO_PRESERVE_MASK			(1 << 17)
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 9165c39..37cfcf2 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -122,7 +122,7 @@
 # define SDVO_DTD_HSYNC_OFF				SDVO_I2C_ARG_0
 # define SDVO_DTD_HSYNC_WIDTH				SDVO_I2C_ARG_1
 # define SDVO_DTD_VSYNC_OFF_WIDTH			SDVO_I2C_ARG_2
-# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
+# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
 # define SDVO_DTD_DTD_FLAGS				SDVO_I2C_ARG_4
 # define SDVO_DTD_DTD_FLAG_INTERLACED				(1 << 7)
 # define SDVO_DTD_DTD_FLAG_STEREO_MASK				(3 << 5)
@@ -155,9 +155,9 @@
 
 #define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
-# define SDVO_CLOCK_RATE_MULT_1X				0
-# define SDVO_CLOCK_RATE_MULT_2X				1
-# define SDVO_CLOCK_RATE_MULT_4X				3
+# define SDVO_CLOCK_RATE_MULT_1X				(1 << 0)
+# define SDVO_CLOCK_RATE_MULT_2X				(1 << 1)
+# define SDVO_CLOCK_RATE_MULT_4X				(1 << 3)
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree cc70e6b789a1901bbe4e3501b6b654542d3cdc20 (from b498d2b1d1170123595ada65353428578b59a361)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 16:49:48 2006 -0700

    Save/restore the output's SDVO reg.  Note that we might be programming the other
    SDVO reg instead of the one assigned to the output.  When trying to fix that, I
    ended up getting no output at all.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e58b659..99cdc6a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -438,7 +438,7 @@ I830SDVOGetClockRateMult(I830SDVOPtr s)
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
-    if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) {
+    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
 	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
 		   "Couldn't get SDVO clock rate multiplier\n");
 	return SDVO_CLOCK_RATE_MULT_1X;
@@ -592,6 +592,8 @@ i830SDVOSave(ScrnInfoPtr pScrn, int outp
     I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
     I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
 		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+
+    sdvo->save_SDVOX = INREG(sdvo->output_device);
 }
 
 void
@@ -624,6 +626,9 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, i
 		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
 
     I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+
+    OUTREG(sdvo->output_device, sdvo->save_SDVOX);
+
     I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
 			     sdvo->save_sdvo_active_2);
 }
diff-tree b498d2b1d1170123595ada65353428578b59a361 (from 56c1f8b0de9b6acc50f51561caf14d3e6bac09ec)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 15:42:46 2006 -0700

    Start trying to save/restore SDVO state on VT switches.

diff --git a/src/i830.h b/src/i830.h
index 3b81c92..d72b72b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -69,6 +69,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #endif
 
 #include "common.h"
+#include "i830_sdvo.h"
 
 /* I830 Video BIOS support */
 
@@ -192,6 +193,12 @@ typedef struct _I830SDVODriver {
    I2CDevRec d;
    unsigned char sdvo_regs[20];
    CARD32 output_device;		/* SDVOB or SDVOC */
+
+   int save_sdvo_mult;
+   Bool save_sdvo_active_1, save_sdvo_active_2;
+   i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+   i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2;
+   CARD32 save_SDVOX;
 } I830SDVORec, *I830SDVOPtr;
 
 struct _I830OutputRec {
@@ -493,7 +500,6 @@ typedef struct _I830Rec {
    CARD32 savePaletteA[256];
    CARD32 savePaletteB[256];
    CARD32 saveSWF[17];
-
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 7c6de99..dcb1acf 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3276,9 +3276,11 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->savePP_CONTROL = INREG(PP_CONTROL);
    pI830->savePP_CYCLE = INREG(PP_CYCLE);
 
-   pI830->saveDVOA = INREG(DVOA);
-   pI830->saveDVOB = INREG(DVOB);
-   pI830->saveDVOC = INREG(DVOC);
+   if (!IS_I9XX(pI830)) {
+      pI830->saveDVOA = INREG(DVOA);
+      pI830->saveDVOB = INREG(DVOB);
+      pI830->saveDVOC = INREG(DVOC);
+   }
 
    for(i = 0; i < 7; i++) {
       pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
@@ -3287,7 +3289,15 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[14] = INREG(SWF30);
    pI830->saveSWF[15] = INREG(SWF31);
    pI830->saveSWF[16] = INREG(SWF32);
-   
+
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOSave(pScrn, i);
+      }
+   }
+
    vgaHWUnlock(hwp);
    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
 
@@ -3325,6 +3335,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    i830SetLVDSPanelPower(pScrn, FALSE);
 
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOPreRestore(pScrn, i);
+      }
+   }
+
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
    OUTREG(DPLL_A, pI830->saveDPLL_A);
@@ -3381,9 +3399,20 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(ADPA, pI830->saveADPA);
    OUTREG(LVDS, pI830->saveLVDS);
-   OUTREG(DVOA, pI830->saveDVOA);
-   OUTREG(DVOB, pI830->saveDVOB);
-   OUTREG(DVOC, pI830->saveDVOC);
+   if (!IS_I9XX(pI830)) {
+      OUTREG(DVOA, pI830->saveDVOA);
+      OUTREG(DVOB, pI830->saveDVOB);
+      OUTREG(DVOC, pI830->saveDVOC);
+   }
+
+   for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+	  pI830->output[i].sdvo_drv != NULL)
+      {
+	 i830SDVOPostRestore(pScrn, i);
+      }
+   }
+
    OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
 
    for(i = 0; i < 7; i++) {
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e8898fc..e58b659 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -160,7 +160,7 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s)
 }
 
 static Bool
-I830SDVOGetActiveOutputs(I830SDVOPtr s)
+I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
@@ -169,6 +169,9 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s)
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
+    *on_1 = s->sdvo_regs[SDVO_I2C_ARG_0];
+    *on_2 = s->sdvo_regs[SDVO_I2C_ARG_1];
+
     return TRUE;
 }
 
@@ -221,39 +224,73 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, B
     return TRUE;
 }
 
-#if 0
-static Bool
-I830SDVOGetOutputTimingsPart1(I830SDVOPtr s)
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1;
-
-    /* XXX: No args */
-    s->sdvo_regs[0x07] = 0x0;
+    dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7];
 
+    memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
-  
+
+    dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0];
+    dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1];
+    dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2];
+    dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3];
+    dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4];
+    dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5];
+    dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6];
+    dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7];
+
     return TRUE;
 }
 
-static Bool
-I830SDVOGetOutputTimingsPart2(I830SDVOPtr s)
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
 {
     memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
+    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
+    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
+    I830SDVOWriteOutputs(s, 8);
+    I830SDVOReadInputRegs(s);
 
-    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2;
-
-    /* XXX: No args */
-    s->sdvo_regs[0x07] = 0x0;
-
-    I830SDVOWriteOutputs(s, 0);
+    memset(s->sdvo_regs, 0, 9);
+    s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
+    s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
+    s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
+    s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
+    s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
+    s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
+    s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
 }
-#endif
 
 static Bool
 I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
@@ -391,6 +428,29 @@ I830SDVOGetPreferredInputTimingPart2(I83
     return TRUE;
 }
 
+static int
+I830SDVOGetClockRateMult(I830SDVOPtr s)
+{
+    memset(s->sdvo_regs, 0, 9);
+
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Couldn't get SDVO clock rate multiplier\n");
+	return SDVO_CLOCK_RATE_MULT_1X;
+    } else {
+	xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO,
+		   "Current clock rate multiplier: %d\n",
+		   s->sdvo_regs[SDVO_I2C_RETURN_0]);
+    }
+
+    return s->sdvo_regs[SDVO_I2C_RETURN_0];
+}
+
 static Bool
 I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
 {
@@ -460,7 +520,6 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
     ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
-    I830SDVOGetActiveOutputs(s);
     I830SDVOSetActiveOutputs(s, FALSE, FALSE);
 
     I830SDVOSetTargetOutput(s, TRUE, TRUE);
@@ -505,12 +564,70 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 	ret = FALSE;
     }
 
-    I830SDVOGetActiveOutputs(s);
     I830SDVOSetActiveOutputs(s, TRUE, TRUE);
 
     return ret;
 }
 
+void
+i830SDVOSave(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
+    I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
+			     &sdvo->save_sdvo_active_2);
+
+    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
+		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
+		       SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+
+    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
+		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+    I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
+		       SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+}
+
+void
+i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+}
+
+void
+i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+    I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
+		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+    I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
+		       SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+
+    I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
+		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+    I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+    I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
+		       SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+
+    I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+    I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
+			     sdvo->save_sdvo_active_2);
+}
+
 static Bool
 I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
 {
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
new file mode 100644
index 0000000..ec4b538
--- /dev/null
+++ b/src/i830_sdvo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+typedef struct _i830_sdvo_dtd {
+    CARD16 clock;
+    CARD8 h_active;
+    CARD8 h_blank;
+    CARD8 h_high;
+    CARD8 v_active;
+    CARD8 v_blank;
+    CARD8 v_high;
+
+    CARD8 h_sync_off;
+    CARD8 h_sync_width;
+    CARD8 v_sync_off_width;
+    CARD8 sync_off_width_high;
+    CARD8 dtd_flags;
+    CARD8 sdvo_flags;
+    CARD8 v_sync_off_high;
+    CARD8 reserved;
+} __attribute__((packed)) i830_sdvo_dtd;
+
+void
+i830SDVOSave(ScrnInfoPtr pScrn, int output_index);
+
+void
+i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index);
+
+void
+i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index);
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 5ad4ac9..9165c39 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -154,8 +154,10 @@
 #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
 
 #define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
-
 #define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
+# define SDVO_CLOCK_RATE_MULT_1X				0
+# define SDVO_CLOCK_RATE_MULT_2X				1
+# define SDVO_CLOCK_RATE_MULT_4X				3
 
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 
diff-tree 56c1f8b0de9b6acc50f51561caf14d3e6bac09ec (from 9ba5319b36e7286e33cf0dcdd804dfc0458a81f5)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 14:10:20 2006 -0700

    Clean up some argument passing, and remove extra SetTarget{In,Out}Puts that had
    no effect.  Note that we are currently trying to program both outputs of any
    SDVO device the same way.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 172a9be..e8898fc 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -131,12 +131,13 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr 
 }
 
 static Bool
-I830SDVOSetTargetInput(I830SDVOPtr s)
+I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2)
 {
-    /* write out 0x10 */
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
     I830SDVOWriteOutputs(s, 1);
 
@@ -146,16 +147,12 @@ I830SDVOSetTargetInput(I830SDVOPtr s)
 }
 
 static Bool
-I830SDVOGetTrainedInputs(I830SDVOPtr s, int on)
+I830SDVOGetTrainedInputs(I830SDVOPtr s)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
 
-    /* XXX: I don't believe we need to set anything here --anholt */
-    s->sdvo_regs[0x07] = on ? 0x80 : 0x00;
-    s->sdvo_regs[0x04] = on ? 0x80 : 0x00;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
@@ -163,15 +160,12 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOGetActiveOutputs(I830SDVOPtr s, int on)
+I830SDVOGetActiveOutputs(I830SDVOPtr s)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
 
-    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
-    s->sdvo_regs[0x03] = 0x1;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
@@ -179,15 +173,13 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOSetActiveOutputs(I830SDVOPtr s, int on)
+I830SDVOSetActiveOutputs(I830SDVOPtr s, Bool on_1, Bool on_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
-
-    /* XXX: This should be touching args 0,1, I believe.  --anholt */
-    s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
-    s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = on_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = on_2;
 
     I830SDVOWriteOutputs(s, 2);
     I830SDVOReadInputRegs(s);
@@ -196,39 +188,34 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, 
 }
 
 static Bool
-I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height)
+I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 *clock_min,
+				CARD16 *clock_max)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
 
-    /* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */
-
-    /* set clock regs */
-    s->sdvo_regs[0x06] = (clock >> 8) & 0xff;
-    s->sdvo_regs[0x07] = clock & 0xff;
-
-    /* set height regs */
-    s->sdvo_regs[0x02] = (height >> 8) & 0xff;
-    s->sdvo_regs[0x03] = height & 0xff;
-
     I830SDVOWriteOutputs(s, 0);
     I830SDVOReadInputRegs(s);
 
+    *clock_min = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    *clock_max = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		 (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+
     return TRUE;
 }
 
 static Bool
-I830SDVOSetTargetOutput(I830SDVOPtr s)
+I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2)
 {
     memset(s->sdvo_regs, 0, 9);
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
+    s->sdvo_regs[SDVO_I2C_ARG_0] = target_1;
+    s->sdvo_regs[SDVO_I2C_ARG_1] = target_2;
 
-    s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1;	/* Enable */
-    s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
-
-    I830SDVOWriteOutputs(s, 1);		/* XXX: Only write these two */
+    I830SDVOWriteOutputs(s, 1);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -309,26 +296,6 @@ I830SDVOSetOutputTimingsPart1(I830SDVOPt
 }
 
 static Bool
-I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock,
-				     CARD16 magic1, CARD16 magic2,
-				     CARD16 magic3)
-{
-    Bool ok;
-
-    /* XXX: This is a rather different command */
-    ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
-				 clock, magic1, magic2, magic3);
-
-    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
-    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
-		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
-    curr_table[5] = 0x1e;
-
-    return ok;
-}
-
-static Bool
 I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5,
 			CARD16 magic6)
 {
@@ -408,6 +375,23 @@ I830SDVOGetPreferredInputTimingPart1(I83
 }
 
 static Bool
+I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s)
+{
+    s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2;
+
+    I830SDVOWriteOutputs(s, 0);
+    I830SDVOReadInputRegs(s);
+
+    curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+    curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+		    (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+    curr_table[5] = 0x1e;
+
+    return TRUE;
+}
+
+static Bool
 I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
 {
     memset(s->sdvo_regs, 0, 9);
@@ -432,6 +416,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     CARD8 c16a[8];
     CARD8 c17a[8];
     CARD16 out_timings[6];
+    CARD16 clock_min, clock_max;
 
     /* do some mode translations */
     h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
@@ -471,40 +456,27 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
     out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
     out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
 
-    I830SDVOSetTargetInput(s);
-    I830SDVOGetInputPixelClockRange(s, clock, height);
+    I830SDVOSetTargetInput(s, TRUE, TRUE);
+    I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max);
+    ErrorF("clock min/max: %d %d\n", clock_min, clock_max);
 
-    I830SDVOGetActiveOutputs(s, 0);
-    I830SDVOSetActiveOutputs(s, 0);
+    I830SDVOGetActiveOutputs(s);
+    I830SDVOSetActiveOutputs(s, FALSE, FALSE);
 
-    I830SDVOSetTargetOutput(s);
+    I830SDVOSetTargetOutput(s, TRUE, TRUE);
     I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
 				  out_timings[2]);
-
-    I830SDVOSetTargetOutput(s);
     I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
 				  out_timings[5]);
 
-    I830SDVOSetTargetInput(s);
-
     I830SDVOCreatePreferredInputTiming(s, clock, width, height);
-    I830SDVOSetTargetInput(s);
-
     I830SDVOGetPreferredInputTimingPart1(s);
-    I830SDVOSetTargetInput(s);
-
-    I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1],
-					 out_timings[2]);
-    I830SDVOSetTargetInput(s);
-
+    I830SDVOGetPreferredInputTimingPart2(s);
     I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
 				 curr_table[2]);
-
-    I830SDVOSetTargetInput(s);
     I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
 				 out_timings[5]);
 
-    I830SDVOSetTargetInput(s);
     /*if (mode->PrivFlags & I830_MFLAG_DOUBLE)
 	I830SDVOSetClockRateMult(s, 0x02);
     else */
@@ -516,15 +488,13 @@ I830SDVOPreSetMode(I830SDVOPtr s, Displa
 Bool
 I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
 {
-    int clock = mode->Clock/10, height=mode->CrtcVDisplay;
     Bool ret = TRUE;
 
     /* the BIOS writes out 6 commands post mode set */
     /* two 03s, 04 05, 10, 1d */
     /* these contain the height and mode clock / 10 by the looks of it */
 
-    I830SDVOGetTrainedInputs(s, 1);
-    I830SDVOGetTrainedInputs(s, 0);
+    I830SDVOGetTrainedInputs(s);
 
     /* THIS IS A DIRTY HACK - sometimes for some reason on startup
      * the BIOS doesn't find my DVI monitor -
@@ -535,11 +505,8 @@ I830SDVOPostSetMode(I830SDVOPtr s, Displ
 	ret = FALSE;
     }
 
-    I830SDVOGetActiveOutputs(s, 1);
-    I830SDVOSetActiveOutputs(s, 1);
-
-    I830SDVOSetTargetInput(s);
-    I830SDVOGetInputPixelClockRange(s, clock, height);
+    I830SDVOGetActiveOutputs(s);
+    I830SDVOSetActiveOutputs(s, TRUE, TRUE);
 
     return ret;
 }
diff-tree 9ba5319b36e7286e33cf0dcdd804dfc0458a81f5 (from d32514aee4b00b035652830e8b5e6c0b43cf159c)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Apr 24 13:55:05 2006 -0700

    Only write out as many arguments as the commands need, and fix up the numbers in
    some cases.  Pretty-print the return status.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 412d798..172a9be 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -64,19 +64,29 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int 
 {
     int i;
 
-    ErrorF("SDVO: W: ");
-    for (i = num_out; i <= SDVO_I2C_ARG_0; i++)
+    ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]);
+    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--)
 	ErrorF("%02X ", s->sdvo_regs[i]);
     ErrorF("\n");
 
     /* blast the output regs */
-    for (i = SDVO_I2C_ARG_0; i >= num_out; i--) {
+    for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) {
 	sWriteByte(s, i, s->sdvo_regs[i]);
     }
     /* blast the command reg */
     sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]);
 }
 
+static const char *cmd_status_names[] = {
+	"Power on",
+	"Success",
+	"Not supported",
+	"Invalid arg",
+	"Pending",
+	"Target not supported",
+	"Scaling not supported"
+};
+
 static void
 I830SDVOReadInputRegs(I830SDVOPtr s)
 {
@@ -95,8 +105,12 @@ I830SDVOReadInputRegs(I830SDVOPtr s)
     sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]);
 
     ErrorF("SDVO: R: ");
-    for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++)
+    for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++)
 	ErrorF("%02X ", s->sdvo_regs[i]);
+    if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+	ErrorF("(%s)", cmd_status_names[s->sdvo_regs[SDVO_I2C_CMD_STATUS]]);
+    else
+	ErrorF("(??? %d)", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
     ErrorF("\n");
 }
 
@@ -112,7 +126,7 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
     s->sdvo_regs[SDVO_I2C_ARG_0] = target;
 
-    I830SDVOWriteOutputs(s, 7);
+    I830SDVOWriteOutputs(s, 1);
     return TRUE;
 }
 
@@ -124,7 +138,7 @@ I830SDVOSetTargetInput(I830SDVOPtr s)
 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 1);
 
     I830SDVOReadInputRegs(s);
 
@@ -175,7 +189,7 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, 
     s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
     s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 2);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -214,7 +228,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s)
     s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1;	/* Enable */
     s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
 
-    I830SDVOWriteOutputs(s, 0);		/* XXX: Only write these two */
+    I830SDVOWriteOutputs(s, 1);		/* XXX: Only write these two */
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -272,7 +286,7 @@ I830SDVOSetTimingsPart1(I830SDVOPtr s, c
     s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
   
     return TRUE;
@@ -330,7 +344,7 @@ I830SDVOSetTimingsPart2(I830SDVOPtr s, C
     s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
     s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 8);
     I830SDVOReadInputRegs(s);
   
     return TRUE;
@@ -367,7 +381,7 @@ I830SDVOCreatePreferredInputTiming(I830S
     s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff;  
     s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff;
 
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 7);
     I830SDVOReadInputRegs(s);
 
     return TRUE;
@@ -401,7 +415,7 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, 
     s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
 
     s->sdvo_regs[SDVO_I2C_ARG_0] = val;
-    I830SDVOWriteOutputs(s, 0);
+    I830SDVOWriteOutputs(s, 1);
     I830SDVOReadInputRegs(s);
 
     return TRUE;



More information about the xorg-commit mailing list