xf86-video-ati: Branch 'master' - 3 commits

Alex Deucher agd5f at kemper.freedesktop.org
Mon Sep 17 20:29:36 PDT 2007


 configure.ac               |    1 
 src/Makefile.am            |    2 
 src/i2c_vid.h              |  132 ++++++++++++++++++++++++
 src/radeon.h               |    6 -
 src/radeon_bios.c          |   53 +++++++++
 src/radeon_display.c       |    2 
 src/radeon_driver.c        |    3 
 src/radeon_output.c        |  198 +++++++++++++++++++++++++++++++++++-
 src/radeon_probe.h         |   17 +++
 src/radeon_reg.h           |    2 
 src/sil164/Makefile.am     |   16 ++
 src/sil164/sil164.c        |  246 +++++++++++++++++++++++++++++++++++++++++++++
 src/sil164/sil164.h        |   31 +++++
 src/sil164/sil164_module.c |   38 ++++++
 src/sil164/sil164_reg.h    |   74 +++++++++++++
 15 files changed, 816 insertions(+), 5 deletions(-)

New commits:
diff-tree c3ab53159d42157985a25e9125eaa5362273b73d (from 1fafa970fa78ddea29a8804b6cd0aea52e4fa2e1)
Author: Alex Deucher <alex at botch2.(none)>
Date:   Mon Sep 17 23:28:51 2007 -0400

    RADEON: XPRESS connector tables are crap
    
    besides specifying the pimary DAC (which they don't have),
    most seem to specify DDC_CRT2 for DDC, which does not seem
    to ever work.  Some have reported success with DDC_MONID so
    lets give that a try.

diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index af98cf7..1ca9e7e 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -244,6 +244,18 @@ static Bool RADEONGetLegacyConnectorInfo
 	    info->BiosConnector[i].DACType = tmp & 0x1;
 	    info->BiosConnector[i].TMDSType = tmp & 0x10;
 
+	    /* most XPRESS chips seem to specify DDC_CRT2 for their 
+	     * VGA DDC port, however DDC never seems to work on that
+	     * port.  Some have reported success on DDC_MONID, so 
+	     * lets see what happens with that.
+	     */
+	    if (info->ChipFamily == CHIP_FAMILY_RS400 &&
+		info->BiosConnector[i].ConnectorType == CONNECTOR_CRT &&
+		info->BiosConnector[i].DDCType == DDC_CRT2) {
+		info->BiosConnector[i].DDCType = DDC_MONID;
+	    }
+
+
 	}
     } else {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n");
diff-tree 1fafa970fa78ddea29a8804b6cd0aea52e4fa2e1 (from 4000a710c93dd2d82891e4082bc7fa922ba9c5f4)
Author: Alex Deucher <alex at botch2.(none)>
Date:   Mon Sep 17 23:10:13 2007 -0400

    RADEON: ignore edid digital bit on analog ports
    
    Some monitors have this bit set even on analog ports

diff --git a/src/radeon_output.c b/src/radeon_output.c
index 7d838ed..44bc0ef 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -432,7 +432,8 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pS
 	} else if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) ||
 		 (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D)) {
 	    MonType = MT_DFP;
-	} else if ((*MonInfo)->rawData[0x14] & 0x80) {	/* if it's digital */
+	} else if (radeon_output->type == OUTPUT_DVI &&
+		   ((*MonInfo)->rawData[0x14] & 0x80)) { /* if it's digital and DVI */
 	    MonType = MT_DFP;
 	} else {
 	    MonType = MT_CRT;
diff-tree 4000a710c93dd2d82891e4082bc7fa922ba9c5f4 (from 38515d402555eaa61c686d42973e59f659b07466)
Author: Alex Deucher <alex at botch2.(none)>
Date:   Mon Sep 17 23:04:17 2007 -0400

    RADEON: initial pass at external TMDS support
    
    - Based on Dave Airlie's initial work and the dvo support
    in the intel driver.
    - Only sil164 is supported at the moment.
    - Once we get some testing and such, we ought to move the dvo
    drivers out of the drivers so they can be shared among all drivers
    - Doesn't seem to work on my card (r4xx ATOM) card ATM
    - Legacy bios table programming sequence not implemented yet

diff --git a/configure.ac b/configure.ac
index 0c413c8..50c382b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -222,5 +222,6 @@ XORG_CHECK_LINUXDOC
 AC_OUTPUT([
 	Makefile
 	src/Makefile
+        src/sil164/Makefile
 	man/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 709b98c..309caf6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,7 +19,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 = 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
diff --git a/src/i2c_vid.h b/src/i2c_vid.h
new file mode 100644
index 0000000..2ba8829
--- /dev/null
+++ b/src/i2c_vid.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2006 Eric Anholt
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef I2C_VID_H
+#define I2C_VID_H
+#include <randrstr.h>
+#include "xf86Crtc.h"
+
+typedef struct _XF86I2CVidOutputRec {
+    /**
+     * Initialize the device at startup time.
+     * Returns NULL if the device does not exist.
+     */
+    void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
+
+    /**
+     * Called to allow the output a chance to create properties after the
+     * RandR objects have been created.
+     */
+    void
+    (*create_resources)(I2CDevPtr d);
+
+    /**
+     * Turns the output on/off, or sets intermediate power levels if available.
+     *
+     * Unsupported intermediate modes drop to the lower power setting.  If the
+     * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
+     * disabled afterwards.
+     */
+    void (*dpms)(I2CDevPtr d, int mode);
+    
+    /**
+     * Saves the output's state for restoration on VT switch.
+     */
+    void (*save)(I2CDevPtr d);
+
+    /**
+     * Restore's the output's state at VT switch.
+     */
+    void (*restore)(I2CDevPtr d);
+
+    /**
+     * Callback for testing a video mode for a given output.
+     *
+     * This function should only check for cases where a mode can't be supported
+     * on the output specifically, and not represent generic CRTC limitations.
+     *
+     * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+     */
+    int (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
+
+    /**
+     * Callback to adjust the mode to be set in the CRTC.
+     *
+     * This allows an output to adjust the clock or even the entire set of
+     * timings, which is used for panels with fixed timings or for
+     * buses with clock limitations.
+     */
+    Bool (*mode_fixup)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+    /**
+     * Callback for preparing mode changes on an output
+     */
+    void (*prepare)(I2CDevPtr d);
+
+    /**
+     * Callback for committing mode changes on an output
+     */
+    void (*commit)(I2CDevPtr d);
+    
+    /**
+     * Callback for setting up a video mode after fixups have been made.
+     *
+     * This is only called while the output is disabled.  The dpms callback
+     * must be all that's necessary for the output, to turn the output on
+     * after this function is called.
+     */
+    void (*mode_set)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+    
+    /**
+     * Probe for a connected output, and return detect_status.
+     */
+    xf86OutputStatus (*detect)(I2CDevPtr d);
+
+    /**
+     * Query the device for the modes it provides.
+     *
+     * This function may also update MonInfo, mm_width, and mm_height.
+     *
+     * \return singly-linked list of modes or NULL if no modes found.
+     */
+    DisplayModePtr
+    (*get_modes)(I2CDevPtr d);
+    
+    /**
+     * Callback when an output's property has changed.
+     */
+    Bool
+    (*set_property)(I2CDevPtr d, Atom property, RRPropertyValuePtr value);
+
+    /**
+     * Clean up driver-specific bits of the output
+     */
+    void (*destroy) (I2CDevPtr d);
+
+    /**
+     * Debugging hook to dump device registers to log file
+     */
+    void (*dump_regs)(I2CDevPtr d);
+} XF86I2CVidOutputRec, *XF86I2CVidOutputPtr;
+
+
+#endif
diff --git a/src/radeon.h b/src/radeon.h
index 4c99511..a1e7395 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -144,7 +144,6 @@ typedef enum {
 #endif
     OPTION_SHOWCACHE,
     OPTION_DYNAMIC_CLOCKS,
-    OPTION_BIOS_HOTKEYS,
     OPTION_VGA_ACCESS,
     OPTION_REVERSE_DDC,
     OPTION_LVDS_PROBE_PLL,
@@ -896,6 +895,8 @@ extern Bool        RADEONGetLVDSInfoFrom
 extern Bool        RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output);
 extern Bool        RADEONGetTVInfoFromBIOS (xf86OutputPtr output);
 extern Bool        RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output);
+extern Bool        RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output);
+
 
 extern void        RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
 						RADEONSavePtr restore);
@@ -946,6 +947,9 @@ extern int RADEONValidateDDCModes(ScrnIn
 extern int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList);
 extern void RADEONSetPitch (ScrnInfoPtr pScrn);
 extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode);
+extern void RADEONSaveExtChipRegisters(ScrnInfoPtr pScrn);
+extern void RADEONRestoreExtChipRegisters(ScrnInfoPtr pScrn);
+extern void RADEONDVOPowerSet(ScrnInfoPtr pScrn, xf86OutputPtr output, int mode);
 
 DisplayModePtr
 RADEONProbeOutputModes(xf86OutputPtr output);
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index b24c481..af98cf7 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -884,6 +884,47 @@ Bool RADEONGetTMDSInfoFromBIOS (xf86Outp
     return FALSE;
 }
 
+Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int offset, table_start, max_freq, gpio_reg, flags;
+
+    if (!info->VBIOS) return FALSE;
+
+    if (info->IsAtomBios) {
+	return FALSE;
+    } else {
+	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58);
+	if (offset) {
+	    table_start = offset + 4;
+	    max_freq = RADEON_BIOS16(table_start);
+	    radeon_output->dvo_slave_addr = RADEON_BIOS8(table_start+2);
+	    gpio_reg = RADEON_BIOS8(table_start+3);
+	    if (gpio_reg == 1)
+		radeon_output->dvo_i2c_reg = RADEON_GPIO_MONID;
+	    else if (gpio_reg == 2)
+		radeon_output->dvo_i2c_reg = RADEON_GPIO_DVI_DDC;
+	    else if (gpio_reg == 3)
+		radeon_output->dvo_i2c_reg = RADEON_GPIO_VGA_DDC;
+	    else if (gpio_reg == 4)
+		radeon_output->dvo_i2c_reg = RADEON_GPIO_CRT2_DDC;
+	    /*else if (gpio_reg == 5)
+	      radeon_output->dvo_i2c_reg = RADEON_GPIO_MM;*/
+	    else {
+		ErrorF("unknown gpio reg: %d\n", gpio_reg);
+		return FALSE;
+	    }
+	    flags = RADEON_BIOS8(table_start+5);
+	    /* XXX: init command list */
+	    return TRUE;
+	}
+    }
+
+    return FALSE;
+}
+
 /* support for init from bios tables
  *
  * Based heavily on the netbsd radeonfb driver
diff --git a/src/radeon_display.c b/src/radeon_display.c
index fa80e10..ff19717 100644
--- a/src/radeon_display.c
+++ b/src/radeon_display.c
@@ -358,6 +358,7 @@ void RADEONEnableDisplay(xf86OutputPtr o
                 tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
                 OUTREG(RADEON_FP2_GEN_CNTL, tmp);
                 save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		RADEONDVOPowerSet(pScrn, output, DPMSModeOn);
             }
         } else if (radeon_output->MonType == MT_LCD) {
             tmp = INREG(RADEON_LVDS_GEN_CNTL);
@@ -409,6 +410,7 @@ void RADEONEnableDisplay(xf86OutputPtr o
                 tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
                 OUTREG(RADEON_FP2_GEN_CNTL, tmp);
                 save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		RADEONDVOPowerSet(pScrn, output, DPMSModeOff);
             }
         } else if (radeon_output->MonType == MT_LCD) {
 	    unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 3f9a8fb..d66400d 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -5271,6 +5271,7 @@ static void RADEONSaveMode(ScrnInfoPtr p
     if (info->InternalTVOut)
 	RADEONSaveTVRegisters(pScrn, save);
     /*RADEONSavePalette(pScrn, save);*/
+    RADEONSaveExtChipRegisters(pScrn);
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONSaveMode returns %p\n", save);
@@ -5368,6 +5369,8 @@ void RADEONRestore(ScrnInfoPtr pScrn)
     if (info->InternalTVOut)
 	RADEONRestoreTVRegisters(pScrn, restore);
 
+    RADEONRestoreExtChipRegisters(pScrn);
+
     RADEONRestoreSurfaces(pScrn, restore);
 
 #if 1
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 40d8873..7d838ed 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -47,6 +47,8 @@
 #include "radeon_version.h"
 #include "radeon_tv.h"
 
+#include "i2c_vid.h"
+#include "sil164/sil164.h"
 
 const char *MonTypeName[7] = {
   "AUTO",
@@ -146,6 +148,17 @@ static const RADEONTMDSPll default_tmds_
     {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */
 };
 
+static const char *SIL164Symbols[] = {
+    "Sil164VidOutput",
+    NULL
+};
+
+RADEONDVORec radeon_dvo_drivers[] = 
+    { { 0, "sil164", "SIL164VidOutput", SIL164Symbols, NULL, NULL, NULL} };
+
+#define RADEON_NUM_DVO_DRIVERS (sizeof(radeon_dvo_drivers)/sizeof(RADEONDVORec))
+
+
 static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output);
 static void RADEONUpdatePanelSize(xf86OutputPtr output);
 static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
@@ -154,6 +167,159 @@ static RADEONMonitorType radeon_detect_t
 static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
 static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output);
 
+Bool RADEONFindDVOController(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONDVOPtr drv;
+    void *ret_ptr;
+    int i;
+
+    for (i = 0; i < RADEON_NUM_DVO_DRIVERS; i++) {
+	drv = &radeon_dvo_drivers[i];
+	drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+
+	if (!drv->modhandle)
+	    continue;
+
+	xf86LoaderReqSymLists(drv->symbols, NULL);
+
+	radeon_output->ExtChip = NULL;
+	ret_ptr = NULL;
+	drv->vid_rec = LoaderSymbol(drv->fntablename);
+
+	ErrorF("dvo i2c reg: 0x%02x\n", radeon_output->dvo_i2c_reg);
+
+	OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	       (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+
+	if (drv->vid_rec)
+	    ret_ptr = drv->vid_rec->init(radeon_output->pDVOBus, radeon_output->dvo_slave_addr);
+
+	if (ret_ptr) {
+	    drv->devpriv = ret_ptr;
+	    radeon_output->ExtChip = drv;
+	    return TRUE;
+	}
+	xf86UnloadSubModule(drv->modhandle);
+    }
+
+    ErrorF("dvo chip detect failed\n");
+    return FALSE;
+}
+
+void RADEONDVOPowerSet(ScrnInfoPtr pScrn, xf86OutputPtr output, int mode)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->ExtChip)
+	return;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+    radeon_output->ExtChip->vid_rec->dump_regs(radeon_output->ExtChip->devpriv);
+    radeon_output->ExtChip->vid_rec->dpms(radeon_output->ExtChip->devpriv, mode);
+
+}
+
+static void RADEONDVOSaveRegisters(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->ExtChip)
+	return;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+    radeon_output->ExtChip->vid_rec->dump_regs(radeon_output->ExtChip->devpriv);
+    radeon_output->ExtChip->vid_rec->save(radeon_output->ExtChip->devpriv);
+
+}
+
+static void RADEONDVOProgramRegisters(ScrnInfoPtr pScrn, xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->ExtChip)
+	return;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+    radeon_output->ExtChip->vid_rec->dump_regs(radeon_output->ExtChip->devpriv);
+    radeon_output->ExtChip->vid_rec->mode_set(radeon_output->ExtChip->devpriv, mode, adjusted_mode);
+
+}
+
+static void RADEONDVORestoreRegisters(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->ExtChip)
+	return;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+    radeon_output->ExtChip->vid_rec->dump_regs(radeon_output->ExtChip->devpriv);
+    radeon_output->ExtChip->vid_rec->restore(radeon_output->ExtChip->devpriv);
+
+}
+
+static ModeStatus RADEONDVOModeValid(ScrnInfoPtr pScrn, xf86OutputPtr output, DisplayModePtr mode)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (!radeon_output->ExtChip)
+	return MODE_OK;
+
+    OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) &
+	   (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+    radeon_output->ExtChip->vid_rec->dump_regs(radeon_output->ExtChip->devpriv);
+    return radeon_output->ExtChip->vid_rec->mode_valid(radeon_output->ExtChip->devpriv, mode);
+
+}
+
+void RADEONSaveExtChipRegisters(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output;
+    xf86OutputPtr output;
+    int o;
+
+    for (o = 0; o < xf86_config->num_output; o++) {
+	output = xf86_config->output[o];
+	radeon_output = output->driver_private;
+	if (radeon_output->TMDSType == TMDS_EXT)
+	    RADEONDVOSaveRegisters(pScrn, output);
+    }
+}
+
+void RADEONRestoreExtChipRegisters(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output;
+    xf86OutputPtr output;
+    int o;
+
+    for (o = 0; o < xf86_config->num_output; o++) {
+	output = xf86_config->output[o];
+	radeon_output = output->driver_private;
+	if (radeon_output->TMDSType == TMDS_EXT)
+	    RADEONDVORestoreRegisters(pScrn, output);
+    }
+
+}
+
 void RADEONPrintPortMap(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr info       = RADEONPTR(pScrn);
@@ -637,6 +803,7 @@ static int
 radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr pScrn = output->scrn;
 
     if (radeon_output->type == OUTPUT_STV ||
 	radeon_output->type == OUTPUT_CTV) {
@@ -647,6 +814,10 @@ radeon_mode_valid(xf86OutputPtr output, 
 	    return MODE_CLOCK_RANGE;
     }
 
+    if (radeon_output->MonType == MT_DFP &&
+	radeon_output->TMDSType == TMDS_EXT)
+	return RADEONDVOModeValid(pScrn, output, pMode);
+
     if (radeon_output->type != OUTPUT_LVDS)
 	return MODE_OK;
 
@@ -777,6 +948,12 @@ static void RADEONInitFP2Registers(xf86O
 
     save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
 
+    /* XXX: these may be chip specific */
+    save->fp2_gen_cntl |= (1 << 22) | R200_FP2_DVO_CLOCK_MODE_SINGLE;
+
+    if (mode->Clock > 165000)
+	save->fp2_gen_cntl |= R200_FP2_DVO_DUAL_CHANNEL_EN;
+
     if (IsPrimary) {
         if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
             save->fp2_gen_cntl   &= ~(R200_FP2_SOURCE_SEL_MASK | 
@@ -1034,6 +1211,7 @@ radeon_mode_set(xf86OutputPtr output, Di
 	    RADEONRestoreFPRegisters(pScrn, &info->ModeReg);
 	} else {
 	    ErrorF("restore FP2\n");
+	    RADEONDVOProgramRegisters(pScrn, output, mode, adjusted_mode);
 	    RADEONRestoreFP2Registers(pScrn, &info->ModeReg);
 	}
 	break;
@@ -2458,7 +2636,21 @@ void RADEONInitConnector(xf86OutputPtr o
     }
 
     if (radeon_output->type == OUTPUT_DVI) {
-	RADEONGetTMDSInfo(output);
+	if (radeon_output->TMDSType == TMDS_EXT) {
+#if defined(__powerpc__)
+	    radeon_output->dvo_i2c_reg = RADEON_GPIO_MONID;
+	    radeon_output->dvo_slave_addr = 0x70;
+#else
+	    if (!RADEONGetExtTMDSInfoFromBIOS(output)) {
+		radeon_output->dvo_i2c_reg = RADEON_GPIO_CRT2_DDC;
+		radeon_output->dvo_slave_addr = 0x70;
+	    }
+#endif
+	    RADEONI2CInit(pScrn, &radeon_output->pDVOBus, radeon_output->dvo_i2c_reg, "DVO");
+	    /* probe dvo chips */
+	    RADEONFindDVOController(pScrn, output);
+	} else
+	    RADEONGetTMDSInfo(output);
     }
 
     if (radeon_output->type == OUTPUT_STV ||
@@ -2478,7 +2670,6 @@ static Bool RADEONSetupAppleConnectors(S
 {
     RADEONInfoPtr info       = RADEONPTR(pScrn);
 
-
     switch (info->MacModel) {
     case RADEON_MAC_IBOOK:
 	info->BiosConnector[0].DDCType = DDC_DVI;
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index bc6f0b9..257e196 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -40,6 +40,7 @@
 #include "xf86DDC.h"
 #include "randrstr.h"
 
+#include "i2c_vid.h"
 #define _XF86MISC_SERVER_
 #include <X11/extensions/xf86misc.h>
 
@@ -148,6 +149,17 @@ typedef enum
     TV_STD_SCART_PAL = 32,
 } TVStd;
 
+typedef struct
+{
+    int type;
+    char *modulename;
+    char *fntablename;
+    const char **symbols;
+    XF86I2CVidOutputPtr vid_rec;
+    void *devpriv;
+    pointer modhandle;
+} RADEONDVORec, *RADEONDVOPtr;
+
 typedef struct _RADEONCrtcPrivateRec {
 #ifdef USE_XAA
     FBLinearPtr rotate_mem_xaa;
@@ -196,6 +208,11 @@ typedef struct _RADEONOutputPrivateRec {
     int               PanelPwrDly;
     int               DotClock;
     RADEONTMDSPll     tmds_pll[4];
+    /* DVO */
+    RADEONDVOPtr      ExtChip;
+    int               dvo_i2c_reg;
+    int               dvo_slave_addr;
+    I2CBusPtr         pDVOBus;
     /* TV out */
     TVStd             default_tvStd;
     TVStd             tvStd;
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index af62a69..a39898a 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -796,6 +796,8 @@
 #       define RADEON_FP2_DVO_EN               (1 << 25)
 #       define RADEON_FP2_DVO_RATE_SEL_SDR     (1 << 26)
 #       define R200_FP2_DVO_RATE_SEL_SDR       (1 << 27)
+#       define R200_FP2_DVO_CLOCK_MODE_SINGLE  (1 << 28)
+#       define R200_FP2_DVO_DUAL_CHANNEL_EN    (1 << 29)
 #define RADEON_FP_H_SYNC_STRT_WID           0x02c4
 #define RADEON_FP_H2_SYNC_STRT_WID          0x03c4
 #define RADEON_FP_HORZ_STRETCH              0x028c
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..d15b964
--- /dev/null
+++ b/src/sil164/sil164.c
@@ -0,0 +1,246 @@
+/* -*- c-basic-offset: 4 -*- */
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "sil164.h"
+#include "sil164_reg.h"
+
+static Bool
+sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *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, CARD8 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 *
+sil164_init(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 xf86OutputStatus
+sil164_detect(I2CDevPtr d)
+{
+    SIL164Ptr sil = SILPTR(d);
+    CARD8 reg9;
+
+    sil164ReadByte(sil, SIL164_REG9, &reg9);
+
+    if (reg9 & SIL164_9_HTPLG)
+	return XF86OutputStatusConnected;
+    else
+	return XF86OutputStatusDisconnected;
+}
+
+static ModeStatus
+sil164_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+    return MODE_OK;
+}
+
+static void
+sil164_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    SIL164Ptr sil = SILPTR(d);
+    /* As long as the basics are set up, since we don't have clock dependencies
+     * in the mode setup, we can just leave the registers alone and everything
+     * will work fine.
+     */
+    /* recommended programming sequence from doc */
+    sil164WriteByte(sil, 0x08, 0x30);
+    sil164WriteByte(sil, 0x09, 0x00);
+    sil164WriteByte(sil, 0x0a, 0x90);
+    sil164WriteByte(sil, 0x0c, 0x89);
+    sil164WriteByte(sil, 0x08, 0x3b /*0x31*/);
+    /* don't do much */
+    return;
+}
+
+/* set the SIL164 power state */
+static void
+sil164_dpms(I2CDevPtr d, int mode)
+{
+    SIL164Ptr sil = SILPTR(d);
+    int ret;
+    unsigned char ch;
+
+    ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+    if (ret == FALSE)
+	return;
+
+    if (mode == DPMSModeOn)
+	ch |= SIL164_8_PD;
+    else
+	ch &= ~SIL164_8_PD;
+
+    sil164WriteByte(sil, SIL164_REG8, ch);
+
+    return;
+}
+
+static void
+sil164_dump_regs(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
+sil164_save(I2CDevPtr d)
+{
+    SIL164Ptr sil = SILPTR(d);
+
+    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;
+}
+
+static void
+sil164_restore(I2CDevPtr d)
+{
+    SIL164Ptr sil = SILPTR(d);
+
+    /* Restore it powered down initially */
+    sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1);
+
+    sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9);
+    sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc);
+    sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8);
+}
+
+
+XF86I2CVidOutputRec SIL164VidOutput = {
+    .init = sil164_init,
+    .detect = sil164_detect,
+    .mode_valid = sil164_mode_valid,
+    .mode_set = sil164_mode_set,
+    .dpms = sil164_dpms,
+    .dump_regs = sil164_dump_regs,
+    .save = sil164_save,
+    .restore = sil164_restore,
+};
diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h
new file mode 100644
index 0000000..9f823d6
--- /dev/null
+++ b/src/sil164/sil164.h
@@ -0,0 +1,31 @@
+/**************************************************************************
+
+ 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
+
+#endif
diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c
new file mode 100644
index 0000000..d3bda81
--- /dev/null
+++ b/src/sil164/sil164_module.c
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 4 -*- */
+
+#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..ebfcb8c
--- /dev/null
+++ b/src/sil164/sil164_reg.h
@@ -0,0 +1,74 @@
+/* -*- c-basic-offset: 4 -*- */
+/**************************************************************************
+
+ 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 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