summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am3
-rw-r--r--src/common.h1
-rw-r--r--src/i810_driver.c8
-rw-r--r--src/i810_reg.h4
-rw-r--r--src/i830.h4
-rw-r--r--src/i830_driver.c49
-rw-r--r--src/i830_i2c.c116
-rw-r--r--src/i830_raw.c1
8 files changed, 184 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e0ffd09..40c53f0c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,7 +55,8 @@ i810_drv_la_SOURCES = \
i830_video.c \
i830_rotate.c \
i830_randr.c \
- i830_raw.c
+ i830_raw.c \
+ i830_i2c.c
if DRI
i810_drv_la_SOURCES += \
diff --git a/src/common.h b/src/common.h
index d5c810f0..10267360 100644
--- a/src/common.h
+++ b/src/common.h
@@ -81,6 +81,7 @@ extern const char *I810fbSymbols[];
extern const char *I810xaaSymbols[];
extern const char *I810shadowFBSymbols[];
extern const char *I810shadowSymbols[];
+extern const char *I810i2cSymbols[];
#ifdef XF86DRI
extern const char *I810driSymbols[];
extern const char *I810drmSymbols[];
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 7d854df2..4d1f50dd 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -335,6 +335,14 @@ const char *I810shadowSymbols[] = {
NULL
};
+
+const char *I810i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+
#ifndef I810_DEBUG
int I810_DEBUG = (0
/* | DEBUG_ALWAYS_SYNC */
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 0e2a627a..fabc7ff0 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -263,7 +263,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define HSYNC_ON 0x00
#define HSYNC_OFF 0x02
-
+#define GPIOA 0x5010
+#define GPIOB 0x5014
+#define GPIOC 0x501C
/* p317, 319
*/
diff --git a/src/i830.h b/src/i830.h
index 063d969f..e01284f0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -441,6 +441,10 @@ typedef struct _I830Rec {
OsTimerPtr devicesTimer;
Bool rawmode;
int MaxClock;
+ Bool ddc2;
+ I2CBusPtr pI2CBus;
+ CARD32 DDCReg;
+
} I830Rec;
#define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9f35d850..41bdd3ac 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2085,6 +2085,52 @@ I830UseDDC(ScrnInfoPtr pScrn)
return mon_range->max_clock;
}
+void
+I830PreInitDDC(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (!xf86LoadSubModule(pScrn, "ddc")) {
+ pI830->ddc2 = FALSE;
+ } else {
+ xf86LoaderReqSymLists(I810ddcSymbols, NULL);
+ pI830->ddc2 = TRUE;
+ }
+
+ /* DDC can use I2C bus */
+ /* Load I2C if we have the code to use it */
+ if (pI830->ddc2) {
+ if (xf86LoadSubModule(pScrn, "i2c")) {
+ xf86LoaderReqSymLists(I810i2cSymbols,NULL);
+ pI830->ddc2 = I830I2cInit(pScrn);
+ }
+ else pI830->ddc2 = FALSE;
+ }
+
+}
+
+void I830DetectMonitors(ScrnInfoPtr pScrn)
+{
+ volatile xf86MonPtr MonInfo[3];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ int DDCReg[] = {GPIOA, GPIOB, GPIOC};
+
+ for (i=0; i<3; i++)
+ {
+ pI830->DDCReg = DDCReg[i];
+
+ MonInfo[i] = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->pI2CBus);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "doing monitor %d\n", i);
+ xf86PrintEDID(MonInfo[i]);
+
+ }
+
+ return;
+
+}
+
static void
PreInitCleanup(ScrnInfoPtr pScrn)
{
@@ -2570,6 +2616,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
pI830->fixedPipe = 1;
}
+ I830PreInitDDC(pScrn);
+
+ I830DetectMonitors(pScrn);
pI830->MonType1 = PIPE_NONE;
pI830->MonType2 = PIPE_NONE;
pI830->specifiedMonitor = FALSE;
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
new file mode 100644
index 00000000..9cb65251
--- /dev/null
+++ b/src/i830_i2c.c
@@ -0,0 +1,116 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@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 "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+#include "compiler.h"
+#include "mibstore.h"
+#include "vgaHW.h"
+#include "mipointer.h"
+#include "micmap.h"
+#include "shadowfb.h"
+#include <X11/extensions/randr.h>
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "shadow.h"
+#include "i830.h"
+
+/* bit locations in the registers */
+#define SCL_DIR_MASK 0x0001
+#define SCL_DIR 0x0002
+#define SCL_VAL_MASK 0x0004
+#define SCL_VAL_OUT 0x0008
+#define SCL_VAL_IN 0x0010
+#define SDA_DIR_MASK 0x0100
+#define SDA_DIR 0x0200
+#define SDA_VAL_MASK 0x0400
+#define SDA_VAL_OUT 0x0800
+#define SDA_VAL_IN 0x1000
+
+static void I830I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long val;
+
+ OUTREG(pI830->DDCReg, (SCL_DIR_MASK));
+ OUTREG(pI830->DDCReg, 0);
+ val = INREG(pI830->DDCReg);
+
+ *clock = (val & SCL_VAL_IN) != 0;
+
+ OUTREG(pI830->DDCReg, (SDA_DIR_MASK));
+ OUTREG(pI830->DDCReg, 0);
+ val = INREG(pI830->DDCReg);
+
+ *data = (val & SDA_VAL_IN) != 0;
+}
+
+static void I830I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long val;
+
+ /* do this in two passes */
+ OUTREG(pI830->DDCReg, (clock ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+ val = INREG(pI830->DDCReg);
+
+ OUTREG(pI830->DDCReg, (data ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+ val = INREG(pI830->DDCReg);
+}
+
+Bool
+I830I2cInit(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->pI2CBus = xf86CreateI2CBusRec();
+
+ if (!pI830->pI2CBus) return FALSE;
+
+ pI830->pI2CBus->BusName = "DDC";
+ pI830->pI2CBus->scrnIndex = pScrn->scrnIndex;
+ pI830->pI2CBus->I2CPutBits = I830I2CPutBits;
+ pI830->pI2CBus->I2CGetBits = I830I2CGetBits;
+ pI830->pI2CBus->AcknTimeout = 10;
+
+ if (!xf86I2CBusInit(pI830->pI2CBus)) return FALSE;
+
+ return TRUE;
+
+}
diff --git a/src/i830_raw.c b/src/i830_raw.c
index e2260547..480edf7c 100644
--- a/src/i830_raw.c
+++ b/src/i830_raw.c
@@ -674,3 +674,4 @@ I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
return ret;
}
+