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