xf86-video-intel: Branch 'modesetting' - 10 commits - configure.ac src/ch7xxx/ch7xxx.c src/ch7xxx/ch7xxx.h src/ch7xxx/ch7xxx_module.c src/ch7xxx/ch7xxx_reg.h src/ch7xxx/Makefile.am src/i2c_vid.h src/i810_reg.h src/i830_display.c src/i830_driver.c src/i830_dvo.c src/i830.h src/i830_modes.c src/i830_xf86Modes.c src/Makefile.am src/sil164/Makefile.am src/sil164/sil164.c src/sil164/sil164.h src/sil164/sil164_module.c src/sil164/sil164_reg.h

Eric Anholt anholt at kemper.freedesktop.org
Tue Jul 11 04:37:17 EEST 2006


 configure.ac               |    2 
 src/Makefile.am            |    3 
 src/ch7xxx/Makefile.am     |   16 ++
 src/ch7xxx/ch7xxx.c        |  272 +++++++++++++++++++++++++++++++++++++++++++++
 src/ch7xxx/ch7xxx.h        |   31 +++++
 src/ch7xxx/ch7xxx_module.c |   36 +++++
 src/ch7xxx/ch7xxx_reg.h    |   91 +++++++++++++++
 src/i2c_vid.h              |   16 ++
 src/i810_reg.h             |   26 ++++
 src/i830.h                 |    9 -
 src/i830_display.c         |   52 +++++++-
 src/i830_driver.c          |   38 +++---
 src/i830_dvo.c             |   86 ++++++++++++++
 src/i830_modes.c           |   18 +-
 src/i830_xf86Modes.c       |    9 -
 src/sil164/Makefile.am     |   16 ++
 src/sil164/sil164.c        |  227 +++++++++++++++++++++++++++++++++++++
 src/sil164/sil164.h        |   31 +++++
 src/sil164/sil164_module.c |   38 ++++++
 src/sil164/sil164_reg.h    |   76 ++++++++++++
 20 files changed, 1055 insertions(+), 38 deletions(-)

New commits:
diff-tree b912bf5673e38e03b0b25c2f5d05fe7e26994ba1 (from d75490701cdbf2ab6eab82eaa078790a5fe0aea0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:35:20 2006 -0700

    Clean up warnings in sil164 module.

diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 93640ae..a274262 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -124,8 +124,6 @@ out:
 static Bool
 sil164Init(I2CDevPtr d)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     /* not much to do */
     return TRUE;
 }
@@ -133,16 +131,12 @@ sil164Init(I2CDevPtr d)
 static ModeStatus
 sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     return MODE_OK;
 }
 
 static void
 sil164Mode(I2CDevPtr d, DisplayModePtr mode)
 {
-    SIL164Ptr sil = SILPTR(d);
-
     sil164Power(d, TRUE);
     sil164PrintRegs(d);
 
diff-tree d75490701cdbf2ab6eab82eaa078790a5fe0aea0 (from 426d26ea446d646fa8f561ea0e03c8e4a2c0c315)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:21:04 2006 -0700

    Hook up SiI164 mode setting (just a matter of turning the chip on).
    
    Also adds register dumping in case this turns out to not be enough, and fixes
    a couple of prototypes.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7b96b3a..e8c8509 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /*
  * Copyright © 2006 Intel Corporation
  *
@@ -843,8 +844,14 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].sdvo_drv)
-	    I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
+	struct _I830OutputRec *output = &pI830->output[i];
+
+	if (output->sdvo_drv)
+	    I830SDVOPreSetMode(output->sdvo_drv, pMode);
+
+	if (output->i2c_drv != NULL)
+	    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv,
+					   pMode);
     }
 
     if (pI830->planeEnabled[0]) {
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 77a7a00..93640ae 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -37,8 +37,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "sil164.h"
 #include "sil164_reg.h"
 
+static void
+sil164PrintRegs(I2CDevPtr d);
+static void
+sil164Power(I2CDevPtr d, Bool On);
+
 static Bool
-sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch)
 {
     if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
 	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
@@ -50,7 +55,7 @@ sil164ReadByte(SIL164Ptr sil, int addr, 
 }
 
 static Bool
-sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+sil164WriteByte(SIL164Ptr sil, int addr, CARD8 ch)
 {
     if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
 	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
@@ -138,6 +143,15 @@ sil164Mode(I2CDevPtr d, DisplayModePtr m
 {
     SIL164Ptr sil = SILPTR(d);
 
+    sil164Power(d, TRUE);
+    sil164PrintRegs(d);
+
+    /* recommended programming sequence from doc */
+    /*sil164WriteByte(sil, 0x08, 0x30);
+      sil164WriteByte(sil, 0x09, 0x00);
+      sil164WriteByte(sil, 0x0a, 0x90);
+      sil164WriteByte(sil, 0x0c, 0x89);
+      sil164WriteByte(sil, 0x08, 0x31);*/
     /* don't do much */
     return;
 }
@@ -168,6 +182,20 @@ static void
 sil164PrintRegs(I2CDevPtr d)
 {
     SIL164Ptr sil = SILPTR(d);
+    CARD8 val;
+
+    sil164ReadByte(sil, SIL164_FREQ_LO, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n",
+	       val);
+    sil164ReadByte(sil, SIL164_FREQ_HI, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n",
+	       val);
+    sil164ReadByte(sil, SIL164_REG8, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val);
+    sil164ReadByte(sil, SIL164_REG9, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val);
+    sil164ReadByte(sil, SIL164_REGC, &val);
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val);
 }
 
 static void
diff-tree 426d26ea446d646fa8f561ea0e03c8e4a2c0c315 (from 8d7987d00242020d29a2574ac0c8b6e55cc22112)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 18:19:51 2006 -0700

    Fix prototype for SaveRegs.

diff --git a/src/i2c_vid.h b/src/i2c_vid.h
index fbf7284..5a743d2 100644
--- a/src/i2c_vid.h
+++ b/src/i2c_vid.h
@@ -9,7 +9,7 @@ typedef struct _I830I2CVidOutputRec {
   void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
   void (*Power)(I2CDevPtr d, Bool On);
   void (*PrintRegs)(I2CDevPtr d);
-  void (*SaveRegs)(void *d);
+  void (*SaveRegs)(I2CDevPtr d);
   void (*RestoreRegs)(I2CDevPtr d);
 } I830I2CVidOutputRec, *I830I2CVidOutputPtr;
 
diff-tree 8d7987d00242020d29a2574ac0c8b6e55cc22112 (from f5a01a2ef02125611d5fb74c20d53d52e544701a)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:34:57 2006 -0700

    Move to 4-space indents in sil164.

diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
index 5e35323..77a7a00 100644
--- a/src/sil164/sil164.c
+++ b/src/sil164/sil164.c
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /**************************************************************************
 
 Copyright © 2006 Dave Airlie
@@ -36,157 +37,169 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "sil164.h"
 #include "sil164_reg.h"
 
-static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+static Bool
+sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
 {
-  if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
-}
-
-static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
-{
-  if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    return FALSE;
-  }
-  return TRUE;
+    if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to read from %s Slave %d.\n",
+		   sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
+sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+{
+    if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "Unable to write to %s Slave %d.\n",
+		   sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	return FALSE;
+    }
+    return TRUE;
 }
 
 /* Silicon Image 164 driver for chip on i2c bus */
-static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
+static void *
+sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
 {
-  /* this will detect the SIL164 chip on the specified i2c bus */
-  SIL164Ptr sil;
-  unsigned char ch;
-
-  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
-  
-  sil = xcalloc(1, sizeof(SIL164Rec));
-  if (sil == NULL)
-    return NULL;
-
-  sil->d.DevName = "SIL164 TMDS Controller";
-  sil->d.SlaveAddr = addr;
-  sil->d.pI2CBus = b;
-  sil->d.StartTimeout = b->StartTimeout;
-  sil->d.BitTimeout = b->BitTimeout;
-  sil->d.AcknTimeout = b->AcknTimeout;
-  sil->d.ByteTimeout = b->ByteTimeout;
-  sil->d.DriverPrivate.ptr = sil;
-
-  if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
-    goto out;
-
-  if (ch!=(SIL164_VID & 0xFF))
-  {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    goto out;
-  }
-
+    /* this will detect the SIL164 chip on the specified i2c bus */
+    SIL164Ptr sil;
+    unsigned char ch;
+
+    xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
+
+    sil = xcalloc(1, sizeof(SIL164Rec));
+    if (sil == NULL)
+	return NULL;
+
+    sil->d.DevName = "SIL164 TMDS Controller";
+    sil->d.SlaveAddr = addr;
+    sil->d.pI2CBus = b;
+    sil->d.StartTimeout = b->StartTimeout;
+    sil->d.BitTimeout = b->BitTimeout;
+    sil->d.AcknTimeout = b->AcknTimeout;
+    sil->d.ByteTimeout = b->ByteTimeout;
+    sil->d.DriverPrivate.ptr = sil;
+
+    if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
+	goto out;
+
+    if (ch!=(SIL164_VID & 0xFF)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "sil164 not detected got %d: from %s Slave %d.\n",
+		   ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	goto out;
+    }
+
+    if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
+	goto out;
+
+    if (ch!=(SIL164_DID & 0xFF)) {
+	xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+		   "sil164 not detected got %d: from %s Slave %d.\n",
+		   ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+	goto out;
+    }
+
+    if (!xf86I2CDevInit(&(sil->d))) {
+	goto out;
+    }
 
-  if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
-    goto out;
+    return sil;
 
-  if (ch!=(SIL164_DID & 0xFF))
-  {
-    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
-    goto out;
-  }
-
-
-  if (!xf86I2CDevInit(&(sil->d)))
-  {
-    goto out;
-  }
-
-  return sil;
-  
- out:
-  xfree(sil);
-  return NULL;
+out:
+    xfree(sil);
+    return NULL;
 }
 
 
-static Bool sil164Init(I2CDevPtr d)
+static Bool
+sil164Init(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 
-  /* not much to do */
-  return TRUE;
+    /* not much to do */
+    return TRUE;
 }
 
-static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
+static ModeStatus
+sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
 {
-  SIL164Ptr sil = SILPTR(d);
-  
-  return MODE_OK;
+    SIL164Ptr sil = SILPTR(d);
+
+    return MODE_OK;
 }
 
-static void sil164Mode(I2CDevPtr d, DisplayModePtr mode)
+static void
+sil164Mode(I2CDevPtr d, DisplayModePtr mode)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 
-  /* don't do much */
-  return;
+    /* don't do much */
+    return;
 }
 
 /* set the SIL164 power state */
-static void sil164Power(I2CDevPtr d, Bool On)
+static void
+sil164Power(I2CDevPtr d, Bool On)
 {
-  SIL164Ptr sil = SILPTR(d);
-  int ret;
-  unsigned char ch;
-  
-  ret = sil164ReadByte(sil, SIL164_REG8, &ch);
-  if (ret == FALSE)
-    return;
+    SIL164Ptr sil = SILPTR(d);
+    int ret;
+    unsigned char ch;
+
+    ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+    if (ret == FALSE)
+	return;
+
+    if (On)
+	ch |= SIL164_8_PD;
+    else
+	ch &= ~SIL164_8_PD;
 
-  if (On)
-    ch |= SIL164_8_PD;
-  else
-    ch &= ~SIL164_8_PD;
+    sil164WriteByte(sil, SIL164_REG8, ch);
 
-  sil164WriteByte(sil, SIL164_REG8, ch);
-  return;
+    return;
 }
 
-static void sil164PrintRegs(I2CDevPtr d)
+static void
+sil164PrintRegs(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
+    SIL164Ptr sil = SILPTR(d);
 }
 
-static void sil164SaveRegs(I2CDevPtr d)
+static void
+sil164SaveRegs(I2CDevPtr d)
 {
-  SIL164Ptr sil = SILPTR(d);
-  
-  if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
-      return;
+    SIL164Ptr sil = SILPTR(d);
 
-  if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
-      return;
+    if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
+	return;
 
-  if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
-    return;
-  
-  if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
-    return;
+    if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
+	return;
 
-  if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
-    return;
-  
-  return;
+    if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
+	return;
+
+    if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
+	return;
 
+    if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
+	return;
+
+    return;
 }
 
 I830I2CVidOutputRec SIL164VidOutput = {
-  sil164Detect,
-  sil164Init,
-  sil164ModeValid,
-  sil164Mode,
-  sil164Power,
-  sil164PrintRegs,
-  sil164SaveRegs,
-  NULL,
+    sil164Detect,
+    sil164Init,
+    sil164ModeValid,
+    sil164Mode,
+    sil164Power,
+    sil164PrintRegs,
+    sil164SaveRegs,
+    NULL,
 };
diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c
index 6778e6a..d3bda81 100644
--- a/src/sil164/sil164_module.c
+++ b/src/sil164/sil164_module.c
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 4 -*- */
+
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
@@ -10,8 +12,7 @@
 
 static MODULESETUPPROTO(sil164Setup);
 
-static XF86ModuleVersionInfo sil164VersRec = 
-  {
+static XF86ModuleVersionInfo sil164VersRec = {
     "sil164",
     MODULEVENDORSTRING,
     MODINFOSTRING1,
@@ -22,15 +23,16 @@ static XF86ModuleVersionInfo sil164VersR
     ABI_VIDEODRV_VERSION,
     MOD_CLASS_NONE,
     { 0,0,0,0 }
-  };
+};
 
 _X_EXPORT XF86ModuleData sil164ModuleData = {
-  &sil164VersRec,
-  sil164Setup,
-  NULL
+    &sil164VersRec,
+    sil164Setup,
+    NULL
 };
 
 static pointer
-sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
-  return (pointer)1;
+sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    return (pointer)1;
 }
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
index 879363c..dc2abba 100644
--- a/src/sil164/sil164_reg.h
+++ b/src/sil164/sil164_reg.h
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 4 -*- */
 /**************************************************************************
 
  Copyright 2006 Dave Airlie <airlied at linux.ie>
@@ -57,17 +58,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SIL164_REGC 0x0c
 
 typedef struct _Sil164SaveRec {
-  CARD8 freq_lo;
-  CARD8 freq_hi;
-  CARD8 reg8;
-  CARD8 reg9;
-  CARD8 regc;
+    CARD8 freq_lo;
+    CARD8 freq_hi;
+    CARD8 reg8;
+    CARD8 reg9;
+    CARD8 regc;
 } SIL164SaveRec;
 
 typedef struct {
-  I2CDevRec d;
-  SIL164SaveRec SavedReg;
-  SIL164SaveRec ModeReg;
+    I2CDevRec d;
+    SIL164SaveRec SavedReg;
+    SIL164SaveRec ModeReg;
 } SIL164Rec, *SIL164Ptr;
 
 #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
diff-tree f5a01a2ef02125611d5fb74c20d53d52e544701a (from 23a0ee73bce12f9e0b881af420413aeec4c0517f)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:17:51 2006 -0700

    Make DVO code light up my sil164-based DVI output, when already set up by BIOS.

diff --git a/src/i830_display.c b/src/i830_display.c
index b26c09f..7b96b3a 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -482,8 +482,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	dpll |= DPLL_DVO_HIGH_SPEED;
 
 	/* Save the data order, since I don't know what it should be set to. */
-	dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
-	dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE;
+	dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
+	dvo |= DVO_ENABLE;
+	dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
 
 	if (pipe == 1)
 	    dvo |= DVO_PIPE_B_SELECT;
@@ -493,10 +494,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	if (pMode->Flags & V_PVSYNC)
 	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
 
-	if (IS_I865G(pI830))
-	    dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS;
-
-	OUTREG(DVOB, dvo & ~DVO_ENABLE);
+	OUTREG(DVOC, dvo & ~DVO_ENABLE);
     }
 
     if (is_sdvo) {
@@ -683,12 +681,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(ADPA, adpa);
 
     if (is_dvo) {
-	OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+	OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
 	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
-	/* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
-	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */
-	OUTREG(DVOB, dvo);
-	/* OUTREG(DVOC, dvoc); */
+	/*OUTREG(DVOB, dvo);*/
+	OUTREG(DVOC, dvo);
     }
 
     if (is_sdvo) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0f472b1..7815c57 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1087,18 +1087,12 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
       I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
 
-      /* if we are on an i2C bus > 0 and we see a monitor - try to
-       * find a controller chip
-       */
-      if (pI830->output[i].MonInfo) {
-	int ret;
-	ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-					  &pI830->output[i].i2c_drv);
-	if (ret==TRUE) {
-	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-		     pI830->output[i].i2c_drv->modulename,
-		     pI830->output[i].pI2CBus->DriverPrivate.uval);
-	}
+      ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+					&pI830->output[i].i2c_drv);
+      if (ret == TRUE) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
+		    pI830->output[i].i2c_drv->modulename,
+		    pI830->output[i].pI2CBus->DriverPrivate.uval);
       }
 
       i++;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index e1d8570..1a572d1 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -729,6 +729,11 @@ I830ReprobePipeModeList(ScrnInfoPtr pScr
 		output_index = i;
 	    }
 	    break;
+	case I830_OUTPUT_DVO:
+	    if (outputs & PIPE_DFP && pI830->output[i].i2c_drv != NULL) {
+		output_index = i;
+	    }
+	    break;
 	case I830_OUTPUT_SDVO:
 	    if (outputs & PIPE_DFP &&
 		pI830->output[i].sdvo_drv != NULL)
diff-tree 23a0ee73bce12f9e0b881af420413aeec4c0517f (from 48ba9273ddfb36d3525e19238b94b18c56667c4d)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 17:16:18 2006 -0700

    Fix modelist with a configured monitor to not begin with all unvalidated modes.

diff --git a/src/i830_modes.c b/src/i830_modes.c
index bb097b8..e1d8570 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1,3 +1,4 @@
+
 #define DEBUG_VERB 2
 /*
  * Copyright © 2002 David Dawes
@@ -659,7 +660,6 @@ static MonPtr
 i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
 {
     MonPtr mon;
-    DisplayModePtr userModes;
 
     mon = xnfcalloc(1, sizeof(*mon));
     memcpy(mon, pScrn->monitor, sizeof(*mon));
@@ -671,15 +671,12 @@ i830GetConfiguredMonitor(ScrnInfoPtr pSc
     if (pScrn->monitor->model != NULL)
 	mon->model = xnfstrdup(pScrn->monitor->model);
 
-    /* Add in VESA standard and user modelines, and do additional validation
+    /* Use VESA standard and user modelines, and do additional validation
      * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
      */
-    userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
-    i830xf86ValidateModesSync(pScrn, userModes, mon);
-    i830xf86PruneInvalidModes(pScrn, &userModes, FALSE);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "prune 1\n");
-    i830AppendModes(pScrn, &mon->Modes, userModes);
-
+    mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
+    i830xf86ValidateModesSync(pScrn, mon->Modes, mon);
+    i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE);
     mon->Last = i830GetModeListTail(mon->Modes);
 
     return mon;
diff-tree 48ba9273ddfb36d3525e19238b94b18c56667c4d (from 3924ffb7d7b71cb9c6ab9eeb12d0f1b2c26244c0)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 15:01:51 2006 -0700

    Fix validation when the first mode is thrown out, and print hsync in modelines.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 09f6b34..4c5de4d 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -249,11 +249,12 @@ PrintModeline(int scrnIndex,DisplayModeP
     if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
 #endif
     xf86DrvMsg(scrnIndex, X_ERROR,
-		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s\n",
+		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s "
+		   "(%.01f kHz)\n",
 		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
 		   mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
 		   mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
-		   mode->VTotal, flags);
+		   mode->VTotal, flags, i830xf86ModeHSync(mode));
     xfree(flags);
 }
 
@@ -400,7 +401,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pS
     DisplayModePtr mode;
 
     for (mode = *modeList; mode != NULL;) {
-	DisplayModePtr next = mode->next;
+	DisplayModePtr next = mode->next, first = *modeList;
 
 	if (mode->status != MODE_OK) {
 	    if (verbose) {
@@ -416,7 +417,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pS
 	    xf86DeleteMode(modeList, mode);
 	}
 
-	if (next == *modeList)
+	if (next == first)
 	    break;
 	mode = next;
     }
diff-tree 3924ffb7d7b71cb9c6ab9eeb12d0f1b2c26244c0 (from parents)
Merge: 5a8f6a486d79f50d2d659e615283289d59f9caa4 f76f94a743505da16e121992eb789c1f74eb7673
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 12:12:38 2006 -0700

    Merge branch 'dvo-merge' into modesetting
    
    Conflicts:
    
    	src/i830_driver.c

diff --cc src/i830_driver.c
index 5615f4b,501580d..0f472b1
@@@ -1080,12 -1104,7 +1081,27 @@@
        pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus;
        I830SDVOInit(pScrn, i, SDVOC);
        i++;
 -      break;
 +   } else {
 +      /* set up DVO */
 +      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");
++
++      /* if we are on an i2C bus > 0 and we see a monitor - try to
++       * find a controller chip
++       */
++      if (pI830->output[i].MonInfo) {
++	int ret;
++	ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
++					  &pI830->output[i].i2c_drv);
++	if (ret==TRUE) {
++	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
++		     pI830->output[i].i2c_drv->modulename,
++		     pI830->output[i].pI2CBus->DriverPrivate.uval);
++	}
++      }
++
 +      i++;
     }
     pI830->num_outputs = i;
  }
diff-tree f76f94a743505da16e121992eb789c1f74eb7673 (from df333cc9a848bc2299a52a7613fe4ffdff8038a2)
Author: Eric Anholt <anholt at FreeBSD.org>
Date:   Mon Jul 10 12:04:09 2006 -0700

    Supply proper NULL-terminated symbol lists to avoid crashing.

diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h
index 5ae0ab8..679c531 100644
--- a/src/ch7xxx/ch7xxx.h
+++ b/src/ch7xxx/ch7xxx.h
@@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define CH7xxx_ADDR_1 0x76
 
-#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput"
-
 #endif
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index b82eaee..242e3dd 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -35,10 +35,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "ch7xxx/ch7xxx.h"
 
 static const char *SIL164Symbols[] = {
-    SIL164_SYMBOL_LIST
+    "Sil164VidOutput",
+    NULL
 };
 static const char *CH7xxxSymbols[] = {
-    CH7xxx_SYMBOL_LIST
+    "CH7xxxVidOutput",
+    NULL
 };
 
 /* driver list */
diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h
index ea5c4c9..9f823d6 100644
--- a/src/sil164/sil164.h
+++ b/src/sil164/sil164.h
@@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define SIL164_ADDR_1 0x38
 
-#define SIL164_SYMBOL_LIST "SIL164VidOutput"
-
 #endif
diff-tree df333cc9a848bc2299a52a7613fe4ffdff8038a2 (from e1064f52b0ff69ea7937897b8c951cc3e32cd752)
Author: Eric Anholt <anholt at leguin.anholt.net>
Date:   Fri Jul 7 13:41:33 2006 -0700

    Initial add of DVO support code.  Probes my sil164.
    
    This is a mostly-untested merge of airlied's work.  The I2C modules are intended
    to be moved into the core server or a separate driver module when they're
    functional and we're happy with the API.

diff --git a/configure.ac b/configure.ac
index deb99c2..5c9291b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,5 +125,7 @@ AC_OUTPUT([
 	src/Makefile
 	src/xvmc/Makefile
 	src/bios_reader/Makefile
+	src/ch7xxx/Makefile
+	src/sil164/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index f8aaad1..50d0ad1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 #  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.
 
-SUBDIRS = xvmc bios_reader
+SUBDIRS = xvmc bios_reader ch7xxx sil164
 # this is obnoxious:
 # -module lets us name the module exactly how we want
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
@@ -54,6 +54,7 @@ i810_drv_la_SOURCES = \
 	 i830_display.c \
 	 i830_display.h \
          i830_driver.c \
+	 i830_dvo.c \
          i830.h \
          i830_gtf.c \
          i830_i2c.c \
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
new file mode 100644
index 0000000..645ac69
--- /dev/null
+++ b/src/ch7xxx/Makefile.am
@@ -0,0 +1,16 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ch7xxx_la_LTLIBRARIES = ch7xxx.la
+ch7xxx_la_LDFLAGS = -module -avoid-version
+ch7xxx_ladir = @moduledir@/drivers
+
+ch7xxx_la_SOURCES = \
+	ch7xxx.c \
+	ch7xxx_module.c \
+	ch7xxx.h \
+	ch7xxx_reg.h
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
new file mode 100644
index 0000000..77c49b5
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.c
@@ -0,0 +1,272 @@
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+All Rights Reserved.
+
+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, 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 AUTHOR 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_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+
+#include <string.h>
+
+#include "../i2c_vid.h"
+#include "ch7xxx.h"
+#include "ch7xxx_reg.h"
+
+static void ch7xxxSaveRegs(void *d);
+
+static CARD8 ch7xxxFreqRegs[][7] =
+  { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
+    { 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
+    { 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
+
+
+static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
+{
+  if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
+{
+  if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/* Ch7xxxicon Image 164 driver for chip on i2c bus */
+static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
+{
+  /* this will detect the CH7xxx chip on the specified i2c bus */
+  CH7xxxPtr ch7xxx;
+  unsigned char ch;
+
+  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
+  
+  ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
+  if (ch7xxx == NULL)
+    return NULL;
+
+  ch7xxx->d.DevName = "CH7xxx TMDS Controller";
+  ch7xxx->d.SlaveAddr = addr;
+  ch7xxx->d.pI2CBus = b;
+  ch7xxx->d.StartTimeout = b->StartTimeout;
+  ch7xxx->d.BitTimeout = b->BitTimeout;
+  ch7xxx->d.AcknTimeout = b->AcknTimeout;
+  ch7xxx->d.ByteTimeout = b->ByteTimeout;
+  ch7xxx->d.DriverPrivate.ptr = ch7xxx;
+
+  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
+    goto out;
+
+  ErrorF("VID is %02X", ch);
+  if (ch!=(CH7xxx_VID & 0xFF))
+  {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
+    goto out;
+
+  ErrorF("DID is %02X", ch);
+  if (ch!=(CH7xxx_DID & 0xFF))
+  {
+    xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!xf86I2CDevInit(&(ch7xxx->d)))
+  {
+    goto out;
+  }
+
+  return ch7xxx;
+  
+ out:
+  xfree(ch7xxx);
+  return NULL;
+}
+
+
+static Bool ch7xxxInit(I2CDevPtr d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+
+  /* not much to do */
+  return TRUE;
+}
+
+static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  
+  return MODE_OK;
+}
+
+static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int ret;
+  unsigned char pm, idf;
+  unsigned char tpcp, tpd, tpf, cm;
+  CARD8 *freq_regs;
+  int i;
+  ErrorF("Clock is %d\n", mode->Clock);
+
+  if (mode->Clock < 75000)
+    freq_regs = ch7xxxFreqRegs[0];
+  else if (mode->Clock < 125000)
+    freq_regs = ch7xxxFreqRegs[1];
+  else
+    freq_regs = ch7xxxFreqRegs[2];
+
+  for (i = 0x31; i < 0x37; i++) {
+    ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
+    ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
+  }
+    
+#if 0
+
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf);
+
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm);
+
+  if (mode->Clock < 65000) {
+    tpcp = 0x08;
+    tpd = 0x16;
+    tpf = 0x60;
+  } else {
+    tpcp = 0x06;
+    tpd = 0x26;
+    tpf = 0xa0;
+  }
+
+  idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
+  if (mode->Flags & V_PHSYNC)
+    idf |= CH7xxx_IDF_HSP;
+
+  if (mode->Flags & V_PVSYNC)
+    idf |= CH7xxx_IDF_HSP;
+  
+  /* setup PM Registers */
+  pm &= ~CH7xxx_PM_FPD;
+  pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
+
+  //  cm |= 1;
+
+  ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
+  ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
+
+#endif
+  /* don't do much */
+  return;
+}
+
+/* set the CH7xxx power state */
+static void ch7xxxPower(I2CDevPtr d, Bool On)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int ret;
+  unsigned char ch;
+
+
+  ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
+  if (ret == FALSE)
+    return;
+  
+  xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch);
+  
+#if 0  
+  ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
+  if (ret)
+    return;
+
+  if (On)
+    ch |= CH7xxx_8_PD;
+  else
+    ch &= ~CH7xxx_8_PD;
+
+  ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
+#endif
+  return;
+}
+
+static void ch7xxxPrintRegs(I2CDevPtr d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(d);
+  int i;
+
+  ch7xxxSaveRegs(d);
+
+  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+    if (( i % 8 ) == 0 )
+      ErrorF("\n %02X: ", i);
+    ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
+
+  }
+}
+
+static void ch7xxxSaveRegs(void *d)
+{
+  CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d));
+  int ret;
+  int i;
+
+  for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+    ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
+    if (ret == FALSE)
+      break;
+  }
+
+  memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
+
+  return;
+}
+
+I830I2CVidOutputRec CH7xxxVidOutput = {
+  ch7xxxDetect,
+  ch7xxxInit,
+  ch7xxxModeValid,
+  ch7xxxMode,
+  ch7xxxPower,
+  ch7xxxPrintRegs,
+  ch7xxxSaveRegs,
+  NULL,
+};
diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h
new file mode 100644
index 0000000..5ae0ab8
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+ 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.
+
+**************************************************************************/
+
+#ifndef CH7xxx_H
+#define CH7xxx_H
+
+#define CH7xxx_ADDR_1 0x76
+
+#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput"
+
+#endif
diff --git a/src/ch7xxx/ch7xxx_module.c b/src/ch7xxx/ch7xxx_module.c
new file mode 100644
index 0000000..19dc6cd
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ch7xxxSetup);
+
+static XF86ModuleVersionInfo ch7xxxVersRec = 
+  {
+    "ch7xxx",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+  };
+
+_X_EXPORT XF86ModuleData ch7xxxModuleData = {
+  &ch7xxxVersRec,
+  ch7xxxSetup,
+  NULL
+};
+
+static pointer
+ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
+  return (pointer)1;
+}
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
new file mode 100644
index 0000000..59de13b
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+
+ 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.
+
+**************************************************************************/
+
+#ifndef CH7xxx_REG_H
+#define CH7xxx_REG_H
+
+#define CH7xxx_REG_VID 0x4a
+#define CH7xxx_REG_DID 0x4b
+
+
+#define CH7011_VID 0x83
+#define CH7009A_VID 0x84
+#define CH7009B_VID 0x85
+#define CH7301_VID 0x95
+
+#define CH7xxx_VID 0x84
+#define CH7xxx_DID 0x17
+
+#define CH7xxx_NUM_REGS 0x4c
+
+typedef struct _CH7xxxSaveRec {
+  CARD8 regs[CH7xxx_NUM_REGS];
+} CH7xxxSaveRec;
+
+typedef struct {
+  I2CDevRec d;
+  CH7xxxSaveRec SavedReg;
+  CH7xxxSaveRec ModeReg;
+} CH7xxxRec, *CH7xxxPtr;
+
+#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
+
+#define CH7xxx_CM 0x1C
+#define CH7xxx_CM_XCM (1<<0)
+#define CH7xxx_CM_MCP (1<<2)
+#define CH7xxx_INPUT_CLOCK 0x1D
+#define CH7xxx_GPIO 0x1E
+#define CH7xxx_IDF 0x1F
+
+#define CH7xxx_IDF_HSP (1<<3)
+#define CH7xxx_IDF_VSP (1<<4)
+
+#define CH7301_CONNECTION_DETECT 0x20
+#define CH7301_DAC_CNTL 0x21
+#define CH7301_HOTPLUG 0x23
+#define CH7xxx_TCTL 0x31
+#define CH7xxx_TPCP 0x33
+#define CH7xxx_TPD 0x34
+#define CH7xxx_TPVT 0x35
+#define CH7xxx_TPF 0x36
+#define CH7301_TCT 0x37
+#define CH7301_TEST_PATTERN 0x48
+#define CH7xxx_PM 0x49
+
+#define CH7xxx_PM_FPD (1<<0)
+#define CH7301_PM_DACPD0 (1<<1)
+#define CH7301_PM_DACPD1 (1<<2)
+#define CH7301_PM_DACPD2 (1<<3)
+#define CH7xxx_PM_DVIL (1<<6)
+#define CH7xxx_PM_DVIP (1<<7)
+
+#define CH7301_SYNC_POLARITY 0x56
+
+#define CH7301_SYNC_RGB_YUV (1<<0)
+#define CH7301_SYNC_POL_DVI (1<<5)
+
+
+
+#endif
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
new file mode 100644
index 0000000..fbf7284
--- /dev/null
+++ b/src/i2c_vid.h
@@ -0,0 +1,16 @@
+/* this needs to go in the server */
+#ifndef I2C_VID_H
+#define I2C_VID_H
+
+typedef struct _I830I2CVidOutputRec {
+  void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr);
+  Bool (*Init)(I2CDevPtr d);
+  ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode);
+  void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
+  void (*Power)(I2CDevPtr d, Bool On);
+  void (*PrintRegs)(I2CDevPtr d);
+  void (*SaveRegs)(void *d);
+  void (*RestoreRegs)(I2CDevPtr d);
+} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
+
+#endif
diff --git a/src/i810_reg.h b/src/i810_reg.h
index e8462f9..275d858 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -823,11 +823,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DVOA			0x61120
 #define DVOB			0x61140
 #define DVOC			0x61160
-#define DVO_ENABLE		(1<<31)
+#define DVO_ENABLE			(1 << 31)
+#define DVO_PIPE_B_SELECT		(1 << 30)
+#define DVO_PIPE_STALL_UNUSED		(0 << 28)
+#define DVO_PIPE_STALL			(1 << 28)
+#define DVO_PIPE_STALL_TV		(2 << 28)
+#define DVO_USE_VGA_SYNC		(1 << 15)
+#define DVO_DATA_ORDER_I740		(0 << 14)
+#define DVO_DATA_ORDER_FP		(1 << 14)
+#define DVO_VSYNC_DISABLE		(1 << 11)
+#define DVO_HSYNC_DISABLE		(1 << 10)
+#define DVO_VSYNC_TRISTATE		(1 << 9)
+#define DVO_HSYNC_TRISTATE		(1 << 8)
+#define DVO_BORDER_ENABLE		(1 << 7)
+#define DVO_DATA_ORDER_GBRG		(1 << 6)
+#define DVO_DATA_ORDER_RGGB		(0 << 6)
+#define DVO_DATA_ORDER_GBRG_ERRATA	(0 << 6)
+#define DVO_DATA_ORDER_RGGB_ERRATA	(1 << 6)
+#define DVO_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define DVO_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define DVO_BLANK_ACTIVE_HIGH		(1 << 2)
+#define DVO_OUTPUT_CSTATE_PIXELS	(1 << 1)	/* SDG only */
+#define DVO_OUTPUT_SOURCE_SIZE_PIXELS	(1 << 0)	/* SDG only */
+#define DVO_PRESERVE_MASK	(0x7<<24)
 
 #define DVOA_SRCDIM		0x61124
 #define DVOB_SRCDIM		0x61144
 #define DVOC_SRCDIM		0x61164
+#define DVO_SRCDIM_HORIZONTAL_SHIFT	12
+#define DVO_SRCDIM_VERTICAL_SHIFT	0
 
 #define LVDS			0x61180
 # define LVDS_PORT_EN			(1 << 31)
diff --git a/src/i830.h b/src/i830.h
index f1b9774..1123001 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include "common.h"
 #include "i830_sdvo.h"
+#include "i2c_vid.h"
 
 /* I830 Video BIOS support */
 
@@ -182,10 +183,8 @@ struct _I830DVODriver {
    char *fntablename;
    int address;
    const char **symbols;
-#if 0
    I830I2CVidOutputRec *vid_rec;
-#endif
-   void *devpriv;
+   void *dev_priv;
    pointer modhandle;
 };
 
@@ -593,6 +592,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* i830_dvo.c */
+Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
+				 struct _I830DVODriver **retdrv);
+
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_display.c b/src/i830_display.c
index d31c100..b26c09f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -258,8 +258,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     CARD32 dpll = 0, fp = 0, temp;
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
     CARD32 pipesrc, dspsize, adpa;
-    CARD32 sdvob = 0, sdvoc= 0;
-    Bool ok, is_sdvo;
+    CARD32 sdvob = 0, sdvoc = 0, dvo = 0;
+    Bool ok, is_sdvo, is_dvo;
     int refclk, pixel_clock, sdvo_pixel_multiply;
     int outputs;
     DisplayModePtr pMasterMode = pMode;
@@ -359,9 +359,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	/* 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;
+	if (IS_I9XX(pI830)) {
+	    is_sdvo = TRUE;
+	    is_dvo = FALSE;
+	} else {
+	    is_dvo = TRUE;
+	    is_sdvo = FALSE;
+	}
     } else {
 	is_sdvo = FALSE;
+	is_dvo = FALSE;
     }
 
     htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
@@ -471,6 +478,27 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
+    if (is_dvo) {
+	dpll |= DPLL_DVO_HIGH_SPEED;
+
+	/* Save the data order, since I don't know what it should be set to. */
+	dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
+	dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE;
+
+	if (pipe == 1)
+	    dvo |= DVO_PIPE_B_SELECT;
+
+	if (pMode->Flags & V_PHSYNC)
+	    dvo |= DVO_HSYNC_ACTIVE_HIGH;
+	if (pMode->Flags & V_PVSYNC)
+	    dvo |= DVO_VSYNC_ACTIVE_HIGH;
+
+	if (IS_I865G(pI830))
+	    dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS;
+
+	OUTREG(DVOB, dvo & ~DVO_ENABLE);
+    }
+
     if (is_sdvo) {
 	dpll |= DPLL_DVO_HIGH_SPEED;
 
@@ -654,6 +682,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     if (outputs & PIPE_CRT_ACTIVE)
 	OUTREG(ADPA, adpa);
 
+    if (is_dvo) {
+	OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+	/* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+	    (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */
+	OUTREG(DVOB, dvo);
+	/* OUTREG(DVOC, dvoc); */
+    }
+
     if (is_sdvo) {
 	OUTREG(SDVOB, sdvob);
 	OUTREG(SDVOC, sdvoc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ca87951..501580d 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1053,6 +1053,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i = 0;
+   Bool ret;
 
    /* everyone has at least a single analog output */
    pI830->output[i].type = I830_OUTPUT_ANALOG;
@@ -1073,6 +1074,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
       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");
+      ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
+					&pI830->output[i].i2c_drv);
+      if (ret) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
+		    pI830->output[i].i2c_drv->modulename,
+		    pI830->output[i].pI2CBus->DriverPrivate.uval);
+      }
       i++;
       break;
    case PCI_CHIP_E7221_G:
@@ -1158,22 +1166,6 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
 	 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 we are on an i2C bus > 0 and we see a monitor - try to
-	  * find a controller chip
-	  */
-	 if (pI830->output[i].MonInfo) {
-	    int ret;
-	    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-					      &pI830->output[i].i2c_drv);
-	    if (ret==TRUE) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-			  pI830->output[i].i2c_drv->modulename,
-			  pI830->output[i].pI2CBus->DriverPrivate.uval);
-	    }
-	 }
-#endif
       break;
       case I830_OUTPUT_SDVO:
 	 if (pI830->output[i].sdvo_drv != NULL) {
@@ -2769,6 +2761,12 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->saveSWF[16] = INREG(SWF32);
 
    for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_DVO &&
+	  pI830->output[i].i2c_drv != NULL)
+      {
+	 pI830->output[i].i2c_drv->vid_rec->SaveRegs(
+	    pI830->output[i].i2c_drv->dev_priv);
+      }
       if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 	  pI830->output[i].sdvo_drv != NULL)
       {
@@ -2888,6 +2886,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
 
    for (i = 0; i < pI830->num_outputs; i++) {
+      if (pI830->output[i].type == I830_OUTPUT_DVO &&
+	  pI830->output[i].i2c_drv != NULL)
+      {
+	 pI830->output[i].i2c_drv->vid_rec->RestoreRegs(
+	    pI830->output[i].i2c_drv->dev_priv);
+      }
       if (pI830->output[i].type == I830_OUTPUT_SDVO &&
 	  pI830->output[i].sdvo_drv != NULL)
       {
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
new file mode 100644
index 0000000..b82eaee
--- /dev/null
+++ b/src/i830_dvo.c
@@ -0,0 +1,84 @@
+/**************************************************************************
+
+Copyright 2006 Dave Airlie <airlied at linux.ie>
+
+All Rights Reserved.
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+#include "sil164/sil164.h"
+#include "ch7xxx/ch7xxx.h"
+
+static const char *SIL164Symbols[] = {
+    SIL164_SYMBOL_LIST
+};
+static const char *CH7xxxSymbols[] = {
+    CH7xxx_SYMBOL_LIST
+};
+
+/* driver list */
+struct _I830DVODriver i830_dvo_drivers[] =
+{
+	{ I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+		(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
+	{ I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+		(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
+};
+
+#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
+
+Bool
+I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
+			    struct _I830DVODriver **retdrv)
+{
+    int i;
+    void *ret_ptr;
+    struct _I830DVODriver *drv;
+
+    for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
+	drv = &i830_dvo_drivers[i];
+	drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+	if (drv->modhandle == NULL)
+	    continue;
+
+	xf86LoaderReqSymLists(drv->symbols, NULL);
+
+	ret_ptr = NULL;
+	drv->vid_rec = LoaderSymbol(drv->fntablename);
+	if (drv->vid_rec != NULL)
+	    ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address);
+
+	if (ret_ptr != NULL) {
+	    drv->dev_priv = ret_ptr;
+	    *retdrv = drv;
+	    return TRUE;
+	}
+	xf86UnloadSubModule(drv->modhandle);
+    }
+    return FALSE;
+}
diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am
new file mode 100644
index 0000000..bb84d03
--- /dev/null
+++ b/src/sil164/Makefile.am
@@ -0,0 +1,16 @@
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
+
+sil164_la_LTLIBRARIES = sil164.la
+sil164_la_LDFLAGS = -module -avoid-version
+sil164_ladir = @moduledir@/drivers
+
+sil164_la_SOURCES = \
+	sil164.c \
+	sil164_module.c \
+	sil164.h \
+	sil164_reg.h
diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c
new file mode 100644
index 0000000..5e35323
--- /dev/null
+++ b/src/sil164/sil164.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+All Rights Reserved.
+
+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, 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 AUTHOR 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_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+
+#include "../i2c_vid.h"
+#include "sil164.h"
+#include "sil164_reg.h"
+
+static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
+{
+  if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
+{
+  if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/* Silicon Image 164 driver for chip on i2c bus */
+static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
+{
+  /* this will detect the SIL164 chip on the specified i2c bus */
+  SIL164Ptr sil;
+  unsigned char ch;
+
+  xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
+  
+  sil = xcalloc(1, sizeof(SIL164Rec));
+  if (sil == NULL)
+    return NULL;
+
+  sil->d.DevName = "SIL164 TMDS Controller";
+  sil->d.SlaveAddr = addr;
+  sil->d.pI2CBus = b;
+  sil->d.StartTimeout = b->StartTimeout;
+  sil->d.BitTimeout = b->BitTimeout;
+  sil->d.AcknTimeout = b->AcknTimeout;
+  sil->d.ByteTimeout = b->ByteTimeout;
+  sil->d.DriverPrivate.ptr = sil;
+
+  if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
+    goto out;
+
+  if (ch!=(SIL164_VID & 0xFF))
+  {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
+    goto out;
+
+  if (ch!=(SIL164_DID & 0xFF))
+  {
+    xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+    goto out;
+  }
+
+
+  if (!xf86I2CDevInit(&(sil->d)))
+  {
+    goto out;
+  }
+
+  return sil;
+  
+ out:
+  xfree(sil);
+  return NULL;
+}
+
+
+static Bool sil164Init(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+
+  /* not much to do */
+  return TRUE;
+}
+
+static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
+{
+  SIL164Ptr sil = SILPTR(d);
+  
+  return MODE_OK;
+}
+
+static void sil164Mode(I2CDevPtr d, DisplayModePtr mode)
+{
+  SIL164Ptr sil = SILPTR(d);
+
+  /* don't do much */
+  return;
+}
+
+/* set the SIL164 power state */
+static void sil164Power(I2CDevPtr d, Bool On)
+{
+  SIL164Ptr sil = SILPTR(d);
+  int ret;
+  unsigned char ch;
+  
+  ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+  if (ret == FALSE)
+    return;
+
+  if (On)
+    ch |= SIL164_8_PD;
+  else
+    ch &= ~SIL164_8_PD;
+
+  sil164WriteByte(sil, SIL164_REG8, ch);
+  return;
+}
+
+static void sil164PrintRegs(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+}
+
+static void sil164SaveRegs(I2CDevPtr d)
+{
+  SIL164Ptr sil = SILPTR(d);
+  
+  if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
+      return;
+
+  if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
+      return;
+
+  if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
+    return;
+  
+  if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
+    return;
+
+  if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
+    return;
+  
+  return;
+
+}
+
+I830I2CVidOutputRec SIL164VidOutput = {
+  sil164Detect,
+  sil164Init,
+  sil164ModeValid,
+  sil164Mode,
+  sil164Power,
+  sil164PrintRegs,
+  sil164SaveRegs,
+  NULL,
+};
diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h
new file mode 100644
index 0000000..ea5c4c9
--- /dev/null
+++ b/src/sil164/sil164.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+ 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.
+
+**************************************************************************/
+
+#ifndef SIL164_H
+#define SIL164_H
+
+#define SIL164_ADDR_1 0x38
+
+#define SIL164_SYMBOL_LIST "SIL164VidOutput"
+
+#endif
diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c
new file mode 100644
index 0000000..6778e6a
--- /dev/null
+++ b/src/sil164/sil164_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(sil164Setup);
+
+static XF86ModuleVersionInfo sil164VersRec = 
+  {
+    "sil164",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    1, 0, 0,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_NONE,
+    { 0,0,0,0 }
+  };
+
+_X_EXPORT XF86ModuleData sil164ModuleData = {
+  &sil164VersRec,
+  sil164Setup,
+  NULL
+};
+
+static pointer
+sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
+  return (pointer)1;
+}
diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h
new file mode 100644
index 0000000..879363c
--- /dev/null
+++ b/src/sil164/sil164_reg.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+
+ 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.
+
+**************************************************************************/
+
+#ifndef SIL164_REG_H
+#define SIL164_REG_H
+
+#define SIL164_VID 0x0001
+#define SIL164_DID 0x0006
+
+#define SIL164_VID_LO 0x00
+#define SIL164_VID_HI 0x01
+#define SIL164_DID_LO 0x02
+#define SIL164_DID_HI 0x03
+#define SIL164_REV    0x04
+#define SIL164_RSVD   0x05
+#define SIL164_FREQ_LO 0x06
+#define SIL164_FREQ_HI 0x07
+
+#define SIL164_REG8 0x08
+#define SIL164_8_VEN (1<<5)
+#define SIL164_8_HEN (1<<4)
+#define SIL164_8_DSEL (1<<3)
+#define SIL164_8_BSEL (1<<2)
+#define SIL164_8_EDGE (1<<1)
+#define SIL164_8_PD   (1<<0)
+
+#define SIL164_REG9 0x09
+#define SIL164_9_VLOW (1<<7)
+#define SIL164_9_MSEL_MASK (0x7<<4)
+#define SIL164_9_TSEL (1<<3)
+#define SIL164_9_RSEN (1<<2)
+#define SIL164_9_HTPLG (1<<1)
+#define SIL164_9_MDI (1<<0)
+
+#define SIL164_REGC 0x0c
+
+typedef struct _Sil164SaveRec {
+  CARD8 freq_lo;
+  CARD8 freq_hi;
+  CARD8 reg8;
+  CARD8 reg9;
+  CARD8 regc;
+} SIL164SaveRec;
+
+typedef struct {
+  I2CDevRec d;
+  SIL164SaveRec SavedReg;
+  SIL164SaveRec ModeReg;
+} SIL164Rec, *SIL164Ptr;
+
+#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
+
+#endif



More information about the xorg-commit mailing list