xf86-video-intel: Branch 'modesetting' - 3 commits - src/i810_reg.h src/i830_display.c src/i830_display.h src/i830_driver.c src/i830.h src/i830_sdvo.c src/i830_sdvo_regs.h src/Makefile.am
Eric Anholt
anholt at kemper.freedesktop.org
Thu Apr 20 01:06:29 EEST 2006
src/Makefile.am | 3
src/i810_reg.h | 17 +
src/i830.h | 2
src/i830_display.c | 37 +++
src/i830_display.h | 7
src/i830_driver.c | 61 +++--
src/i830_sdvo.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/i830_sdvo_regs.h | 173 +++++++++++++++
8 files changed, 849 insertions(+), 29 deletions(-)
New commits:
diff-tree 132dc0599cf44389c4cc03919f1da8d3a0762b44 (from 88bb4b578857588f34ac84b7a20577139eccab6d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date: Wed Apr 19 15:04:17 2006 -0700
Whine if SDVO I2C device init fails, rather than be silent.
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3b3efa1..b656bc6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -547,13 +547,13 @@ I830SDVOInit(I2CBusPtr b)
sdvo->d.ByteTimeout = b->ByteTimeout;
sdvo->d.DriverPrivate.ptr = sdvo;
- if (!xf86I2CDevInit(&sdvo->d))
- goto out;
+ if (!xf86I2CDevInit(&sdvo->d)) {
+ xf86DrvMsg(b->scrnIndex, X_ERROR,
+ "Failed to initialize SDVO I2C device\n");
+ xfree(sdvo);
+ return NULL;
+ }
return sdvo;
-
-out:
- xfree(sdvo);
- return NULL;
}
Bool
diff-tree 88bb4b578857588f34ac84b7a20577139eccab6d (from d8f7dfac769d7b03f069306b1296bb2e1e08b009)
Author: Eric Anholt <anholt at FreeBSD.org>
Date: Wed Apr 19 14:23:45 2006 -0700
Add more SDVO code. It's taken from airlied's driver, but with magic numbers
replaced by symbolic names in many places. I tried to restrain myself from
functional changes in airlied's code in this pass.
diff --git a/src/i830.h b/src/i830.h
index a631258..fa1f017 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -580,10 +580,6 @@ extern Bool I830RandRInit(ScreenPtr pScr
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
char *name);
-/* i830_sdvo.c */
-extern I830SDVOPtr I830SDVOInit(I2CBusPtr b);
-extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
-
/*
* 12288 is set as the maximum, chosen because it is enough for
* 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_display.c b/src/i830_display.c
index fd3c352..6fef425 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -571,6 +571,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
#ifdef XF86DRI
Bool didLock = FALSE;
#endif
+ int i;
DPRINTF(PFX, "i830SetMode\n");
@@ -590,6 +591,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
pI830->planeEnabled[1] = 0;
}
+ for (i = 0; i < pI830->num_outputs; i++) {
+ if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+ I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
+ }
+
if (pI830->planeEnabled[0]) {
ok = i830PipeSetMode(pScrn, pMode, 0);
if (!ok)
@@ -600,6 +606,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
if (!ok)
goto done;
}
+ for (i = 0; i < pI830->num_outputs; i++) {
+ if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+ I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
+ }
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
(int)(pMode->HDisplay * pMode->VDisplay *
diff --git a/src/i830_display.h b/src/i830_display.h
index d8e4e5e..9f07ba1 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -25,7 +25,14 @@
*
*/
+/* i830_display.c */
Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
Bool i830DetectCRT(ScrnInfoPtr pScrn);
void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
+
+/* i830_sdvo.c */
+I830SDVOPtr I830SDVOInit(I2CBusPtr b);
+Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
+Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
+Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 7f5549c..3b3efa1 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -28,6 +28,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "xf86_OSproc.h"
#include "compiler.h"
#include "i830.h"
+#include "i830_sdvo_regs.h"
+
+CARD16 curr_table[6];
/* SDVO support for i9xx chipsets */
static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
@@ -41,7 +44,6 @@ static Bool sReadByte(I830SDVOPtr s, int
return TRUE;
}
-#if 0
static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
{
if (!xf86I2CWriteByte(&s->d, addr, ch)) {
@@ -52,8 +54,481 @@ static Bool sWriteByte(I830SDVOPtr s, in
}
return TRUE;
}
+
+/* following on from tracing the intel BIOS i2c routines */
+static void
+I830SDVOWriteOutputs(I830SDVOPtr s, int num_out)
+{
+ int i;
+
+ ErrorF("SDVO: W: ");
+ for (i = num_out; i <= SDVO_I2C_ARG_0; i++)
+ ErrorF("%02X ", s->sdvo_regs[i]);
+ ErrorF("\n");
+
+ /* blast the output regs */
+ for (i = SDVO_I2C_ARG_0; i >= 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 void
+I830SDVOReadInputRegs(I830SDVOPtr s)
+{
+ int i;
+
+ /* follow BIOS ordering */
+ sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+
+ sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]);
+ sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]);
+ sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]);
+ sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]);
+ sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]);
+ sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]);
+ sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]);
+ 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++)
+ ErrorF("%02X ", s->sdvo_regs[i]);
+ ErrorF("\n");
+}
+
+Bool
+I830SDVOSetupDDC(I830SDVOPtr s, int enable)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
+ s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2;
+
+ I830SDVOWriteOutputs(s, 7);
+
+ sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+
+ ErrorF("SDVO: R: ");
+ ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
+ ErrorF("\n");
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetTargetInput(I830SDVOPtr s)
+{
+ /* write out 0x10 */
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
+
+ I830SDVOWriteOutputs(s, 0);
+
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOGetTrainedInputs(I830SDVOPtr s, int on)
+{
+ 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);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOGetActiveOutputs(I830SDVOPtr s, int on)
+{
+ 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);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetActiveOutputs(I830SDVOPtr s, int on)
+{
+ 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;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height)
+{
+ 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);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetTargetOutput(I830SDVOPtr s)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
+
+ 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 */
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+#if 0
+static Bool
+I830SDVOGetOutputTimingsPart1(I830SDVOPtr s)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1;
+
+ /* XXX: No args */
+ s->sdvo_regs[0x07] = 0x0;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOGetOutputTimingsPart2(I830SDVOPtr s)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2;
+
+ /* XXX: No args */
+ s->sdvo_regs[0x07] = 0x0;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
#endif
+static Bool
+I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
+ CARD16 magic2, CARD16 magic3)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+
+ /* set clock regs */
+ s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock,
+ CARD16 magic1, CARD16 magic2, CARD16 magic3)
+{
+ return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1,
+ clock, magic1, magic2, magic3);
+}
+
+static Bool
+I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1,
+ CARD16 magic2, CARD16 magic3)
+{
+ return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
+ clock, magic1, magic2, magic3);
+}
+
+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)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+
+ /* set clock regs */
+ s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
+ CARD16 magic6)
+{
+ return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4,
+ magic5, magic6);
+}
+
+static Bool
+I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
+ CARD16 magic6)
+{
+ return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4,
+ magic5, magic6);
+}
+
+static Bool
+I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width,
+ CARD16 height)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
+
+ s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] |
+ (s->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
+ curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] |
+ (s->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
+ curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
+ (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
+
+ return TRUE;
+}
+
+static Bool
+I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
+
+ s->sdvo_regs[SDVO_I2C_ARG_0] = val;
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
+Bool
+I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode)
+{
+ CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
+ CARD16 height = mode->CrtcVDisplay;
+ CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+ CARD16 h_sync_offset, v_sync_offset;
+ CARD16 sync_flags;
+ CARD8 c16a[8];
+ CARD8 c17a[8];
+ CARD16 out_timings[6];
+
+ /* do some mode translations */
+ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
+ h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
+
+ v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart;
+ v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+
+ h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
+ v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
+
+ sync_flags = 0x18;
+ if (mode->Flags & V_PHSYNC)
+ sync_flags |= 0x2;
+ if (mode->Flags & V_PVSYNC)
+ sync_flags |= 0x4;
+ /* high bits of 0 */
+ c16a[7] = clock & 0xff;
+ c16a[6] = (clock >> 8) & 0xff;
+ c16a[5] = (width & 0xff);
+ c16a[4] = (h_blank_len & 0xff);
+ c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf);
+ c16a[2] = (height & 0xff);
+ c16a[1] = (v_blank_len & 0xff);
+ c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf);
+
+ c17a[7] = h_sync_offset;
+ c17a[6] = h_sync_len & 0xff;
+ c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf);
+ c17a[4] = 0;
+ c17a[3] = sync_flags;
+ c17a[2] = 0;
+ out_timings[0] = c16a[1] | ((short)c16a[0] << 8);
+ out_timings[1] = c16a[3] | ((short)c16a[2] << 8);
+ out_timings[2] = c16a[5] | ((short)c16a[4] << 8);
+ out_timings[3] = c17a[7] | ((short)c17a[6] << 8);
+ out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
+ out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
+
+ I830SDVOSetTargetInput(s);
+ I830SDVOGetInputPixelClockRange(s, clock, height);
+
+ I830SDVOGetActiveOutputs(s, 0);
+ I830SDVOSetActiveOutputs(s, 0);
+
+ I830SDVOSetTargetOutput(s);
+ 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);
+
+ 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 */
+ I830SDVOSetClockRateMult(s, 0x01);
+
+ return TRUE;
+}
+
+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);
+
+ /* THIS IS A DIRTY HACK - sometimes for some reason on startup
+ * the BIOS doesn't find my DVI monitor -
+ * without this hack the driver doesn't work.. this causes the modesetting
+ * to be re-run
+ */
+ if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
+ ret = FALSE;
+ }
+
+ I830SDVOGetActiveOutputs(s, 1);
+ I830SDVOSetActiveOutputs(s, 1);
+
+ I830SDVOSetTargetInput(s);
+ I830SDVOGetInputPixelClockRange(s, clock, height);
+
+ return ret;
+}
+
I830SDVOPtr
I830SDVOInit(I2CBusPtr b)
{
@@ -92,7 +567,7 @@ I830I2CDetectSDVOController(ScrnInfoPtr
if (sdvo == NULL)
return FALSE;
- for (i=0; i<0x40; i++) {
+ for (i = 0; i < 0x40; i++) {
if (!sReadByte(sdvo, i, &ch[i]))
return FALSE;
}
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
new file mode 100644
index 0000000..5ad4ac9
--- /dev/null
+++ b/src/i830_sdvo_regs.h
@@ -0,0 +1,173 @@
+/*
+ * 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>
+ *
+ */
+
+/* I2C registers for SDVO */
+#define SDVO_I2C_ARG_0 0x07
+#define SDVO_I2C_ARG_1 0x06
+#define SDVO_I2C_ARG_2 0x05
+#define SDVO_I2C_ARG_3 0x04
+#define SDVO_I2C_ARG_4 0x03
+#define SDVO_I2C_ARG_5 0x02
+#define SDVO_I2C_ARG_6 0x01
+#define SDVO_I2C_ARG_7 0x00
+#define SDVO_I2C_OPCODE 0x08
+#define SDVO_I2C_CMD_STATUS 0x09
+#define SDVO_I2C_RETURN_0 0x0a
+#define SDVO_I2C_RETURN_1 0x0b
+#define SDVO_I2C_RETURN_2 0x0c
+#define SDVO_I2C_RETURN_3 0x0d
+#define SDVO_I2C_RETURN_4 0x0e
+#define SDVO_I2C_RETURN_5 0x0f
+#define SDVO_I2C_RETURN_6 0x10
+#define SDVO_I2C_RETURN_7 0x11
+#define SDVO_I2C_VENDOR_BEGIN 0x20
+
+/* Status results */
+#define SDVO_CMD_STATUS_POWER_ON 0x0
+#define SDVO_CMD_STATUS_SUCCESS 0x1
+#define SDVO_CMD_STATUS_NOTSUPP 0x2
+#define SDVO_CMD_STATUS_INVALID_ARG 0x3
+#define SDVO_CMD_STATUS_PENDING 0x4
+#define SDVO_CMD_STATUS_TARGET_NOT_SUPP 0x5
+#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
+
+/* SDVO commands, argument/result registers */
+#define SDVO_CMD_RESET 0x01
+#define SDVO_CMD_GET_DEVICE_CAPS 0x02
+# define SDVO_DEVICE_CAPS_VENDOR_ID SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_CAPS_DEVICE_ID SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_CAPS_DEVICE_REV_ID SDVO_I2C_RETURN_2
+# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR SDVO_I2C_RETURN_3
+# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR SDVO_I2C_RETURN_4
+# define SDVO_DEVICE_CAPS_CAPS SDVO_I2C_RETURN_5
+# define SDVO_DEVICE_CAPS_INPUTS_MASK (3 << 0)
+# define SDVO_DEVICE_CAPS_SMOOTH_SCALING (1 << 2)
+# define SDVO_DEVICE_CAPS_SHARP_SCALING (1 << 3)
+# define SDVO_DEVICE_CAPS_UP_SCALING (1 << 4)
+# define SDVO_DEVICE_CAPS_DOWN_SCALING (1 << 5)
+# define SDVO_DEVICE_CAPS_STALL_SUPPORT (1 << 6)
+# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED SDVO_I2C_RETURN_6
+# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED SDVO_I2C_RETURN_7
+
+#define SDVO_CMD_GET_FIRMWARE_REV 0x86
+# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
+
+#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
+
+#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
+
+#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
+
+#define SDVO_CMD_GET_IN_OUT_MAP 0x06
+
+#define SDVO_CMD_SET_IN_OUT_MAP 0x07
+
+#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
+
+#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
+
+#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
+
+#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
+
+#define SDVO_CMD_GET_INTR_EVENT_SOURCE 0x0f
+
+#define SDVO_CMD_SET_TARGET_INPUT 0x10
+
+#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
+
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
+/* Part 1 */
+# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
+# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
+# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
+# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
+# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
+# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
+# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
+# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
+/* Part 2 */
+# 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_DTD_FLAGS SDVO_I2C_ARG_4
+# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
+# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
+# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
+# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
+# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
+# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
+# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED (1 << 6)
+# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
+# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
+
+#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
+
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
+
+#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
+#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
+
+#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_CMD_GET_SUPPORTED_TV_FORMATS 0x27
+
+#define SDVO_CMD_GET_TV_FORMAT 0x28
+
+#define SDVO_CMD_SET_TV_FORMAT 0x29
+
+#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
+
+#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
+# define SDVO_CONTROL_BUS_PROM 0x0
+# define SDVO_CONTROL_BUS_DDC1 0x1
+# define SDVO_CONTROL_BUS_DDC2 0x2
+# define SDVO_CONTROL_BUS_DDC3 0x3
+
diff-tree d8f7dfac769d7b03f069306b1296bb2e1e08b009 (from a371a04a57620b7128e3c4395bc7c2ac55effe19)
Author: Eric Anholt <anholt at FreeBSD.org>
Date: Wed Apr 19 10:45:13 2006 -0700
Start bringing in some SDVO code, mostly from airlied.
diff --git a/src/Makefile.am b/src/Makefile.am
index 1789af2..da48149 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,7 +61,8 @@ i810_drv_la_SOURCES = \
i830_modes.c \
i830_video.c \
i830_rotate.c \
- i830_randr.c
+ i830_randr.c \
+ i830_sdvo.c
if DRI
i810_drv_la_SOURCES += \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 92d9cf9..82571e0 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -745,6 +745,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
+#define SDVOB 0x61140
+#define SDVOC 0x61160
+#define SDVO_ENABLE (1 << 31)
+#define SDVO_PIPE_B_SELECT (1 << 30)
+#define SDVO_STALL_SELECT (1 << 29)
+#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_CLOCK_OUTPUT_INVERT (1 << 18)
+#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVO_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVO_PRESERVE_MASK (1 << 17)
+
#define I830_HTOTAL_MASK 0xfff0000
#define I830_HACTIVE_MASK 0x7ff
diff --git a/src/i830.h b/src/i830.h
index babbe08..a631258 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -202,7 +202,7 @@ struct _I830OutputRec {
I2CBusPtr pI2CBus;
I2CBusPtr pDDCBus;
struct _I830DVODriver *i2c_drv;
- struct _I830SDVODriver *sdvo_drv;
+ I830SDVOPtr sdvo_drv;
};
typedef struct _I830Rec {
@@ -580,6 +580,10 @@ extern Bool I830RandRInit(ScreenPtr pScr
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
char *name);
+/* i830_sdvo.c */
+extern I830SDVOPtr I830SDVOInit(I2CBusPtr b);
+extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
+
/*
* 12288 is set as the maximum, chosen because it is enough for
* 1920x1440 at 32bpp with a 2048 pixel line pitch with some to spare.
diff --git a/src/i830_display.c b/src/i830_display.c
index 8eebfca..fd3c352 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -255,8 +255,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
CARD32 dpll = 0, fp = 0, temp;
CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
- CARD32 pipesrc, dspsize, adpa;
- Bool ok;
+ CARD32 pipesrc, dspsize, adpa, sdvoc = 0;
+ Bool ok, is_sdvo;
int refclk, pixel_clock;
int outputs;
@@ -283,6 +283,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
"Can't support LVDS on pipe A\n");
return FALSE;
}
+ if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) {
+ /* We'll change how we control outputs soon, but to get the SDVO code up
+ * and running, just check for these two possibilities.
+ */
+ is_sdvo = TRUE;
+ } else {
+ is_sdvo = FALSE;
+ }
htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
@@ -378,6 +386,19 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
dpll |= PLL_REF_INPUT_DREFCLK;
dpll |= SDV0_DEFAULT_MULTIPLIER;
+ if (is_sdvo) {
+ dpll |= DPLL_DVO_HIGH_SPEED;
+
+ ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC));
+
+ sdvoc = INREG(SDVOC) & SDVO_PRESERVE_MASK;
+ sdvoc |= SDVO_ENABLE;
+ if (pipe == 1)
+ sdvoc |= SDVO_PIPE_B_SELECT;
+ sdvoc |= SDVO_PHASE_SELECT_DEFAULT;
+ sdvoc |= SDVO_BORDER_ENABLE;
+ }
+
fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
#if 1
@@ -532,6 +553,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
if (outputs & PIPE_CRT_ACTIVE)
OUTREG(ADPA, adpa);
+ if (is_sdvo)
+ OUTREG(SDVOC, sdvoc);
return TRUE;
}
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8930db0..591605a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1338,13 +1338,15 @@ static void
I830SetupOutputBusses(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
+ int i = 0;
+ Bool ret;
/* everyone has at least a single analog output */
- pI830->num_outputs = 1;
- pI830->output[0].type = I830_OUTPUT_ANALOG;
+ pI830->output[i].type = I830_OUTPUT_ANALOG;
/* setup the DDC bus for the analog output */
- I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A");
+ I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A");
+ i++;
/* need to add the output busses for each device
* - this function is very incomplete
@@ -1355,35 +1357,44 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
case PCI_CHIP_845_G:
case PCI_CHIP_I855_GM:
case PCI_CHIP_I865_G:
- pI830->num_outputs = 2;
- pI830->output[1].type = I830_OUTPUT_DVO;
- I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D");
- I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E");
+ pI830->output[i].type = I830_OUTPUT_DVO;
+ I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
+ I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+ i++;
break;
case PCI_CHIP_E7221_G:
/* ??? */
break;
- case PCI_CHIP_I915_G:
case PCI_CHIP_I915_GM:
- pI830->num_outputs = 2;
- pI830->output[1].type = I830_OUTPUT_LVDS;
- I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C");
+ case PCI_CHIP_I945_GM:
+ pI830->output[i].type = I830_OUTPUT_LVDS;
+ I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C");
+ i++;
break;
-#if 0
+ case PCI_CHIP_I915_G:
case PCI_CHIP_I945_G:
- case PCI_CHIP_I945_GM:
- /* SDVO ports have a single control bus */
- pI830->num_outputs = 2;
- pI830->output[1].type = I830_OUTPUT_SDVO;
- I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E");
+ /* Set up SDVOB */
+ pI830->output[i].type = I830_OUTPUT_SDVO;
+ I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
+
+ pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
+ ret = I830I2CDetectSDVOController(pScrn, i);
+ if (ret == TRUE)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOB\n");
+ i++;
+
+ /* Set up SDVOC */
+ pI830->output[i].type = I830_OUTPUT_SDVO;
+ I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E");
- pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus);
- ret = I830I2CDetectSDVOController(pScrn, 1);
+ pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus);
+ ret = I830I2CDetectSDVOController(pScrn, i);
if (ret == TRUE)
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOC\n");
+ i++;
break;
-#endif
}
+ pI830->num_outputs = i;
}
void
@@ -1442,8 +1453,8 @@ void I830DetectMonitors(ScrnInfoPtr pScr
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
pI830->output[i].pDDCBus->DriverPrivate.uval);
xf86PrintEDID(pI830->output[i].MonInfo);
-
-#if 0
+
+#if 0
/* if we are on an i2C bus > 0 and we see a monitor - try to
* find a controller chip
*/
@@ -1459,9 +1470,9 @@ void I830DetectMonitors(ScrnInfoPtr pScr
}
#endif
break;
-#if 0
case I830_OUTPUT_SDVO:
if (pI830->output[i].sdvo_drv->found) {
+#if 0
I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
@@ -1470,9 +1481,9 @@ void I830DetectMonitors(ScrnInfoPtr pScr
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i,
pI830->output[i].pI2CBus->DriverPrivate.uval);
xf86PrintEDID(pI830->output[i].MonInfo);
+#endif
}
break;
-#endif
case I830_OUTPUT_UNUSED:
break;
default:
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
new file mode 100644
index 0000000..7f5549c
--- /dev/null
+++ b/src/i830_sdvo.c
@@ -0,0 +1,103 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied at linux.ie>
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
+
+**************************************************************************/
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "i830.h"
+
+/* SDVO support for i9xx chipsets */
+static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
+{
+ if (!xf86I2CReadByte(&s->d, addr, ch)) {
+ xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to read from %s Slave %d.\n", s->d.pI2CBus->BusName,
+ s->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#if 0
+static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
+{
+ if (!xf86I2CWriteByte(&s->d, addr, ch)) {
+ xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave %d.\n", s->d.pI2CBus->BusName,
+ s->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+I830SDVOPtr
+I830SDVOInit(I2CBusPtr b)
+{
+ I830SDVOPtr sdvo;
+
+ sdvo = xcalloc(1, sizeof(I830SDVORec));
+ if (sdvo == NULL)
+ return NULL;
+
+ sdvo->d.DevName = "SDVO Controller";
+ sdvo->d.SlaveAddr = 0x39 << 1;
+ sdvo->d.pI2CBus = b;
+ sdvo->d.StartTimeout = b->StartTimeout;
+ sdvo->d.BitTimeout = b->BitTimeout;
+ sdvo->d.AcknTimeout = b->AcknTimeout;
+ sdvo->d.ByteTimeout = b->ByteTimeout;
+ sdvo->d.DriverPrivate.ptr = sdvo;
+
+ if (!xf86I2CDevInit(&sdvo->d))
+ goto out;
+ return sdvo;
+
+out:
+ xfree(sdvo);
+ return NULL;
+}
+
+Bool
+I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned char ch[64];
+ int i;
+ I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+ if (sdvo == NULL)
+ return FALSE;
+
+ for (i=0; i<0x40; i++) {
+ if (!sReadByte(sdvo, i, &ch[i]))
+ return FALSE;
+ }
+
+ pI830->output[output_index].sdvo_drv->found = 1;
+
+ return TRUE;
+}
More information about the xorg-commit
mailing list