diff --git a/configure.ac b/configure.ac index 591ba66..5a4787d 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-geode], - 2.8.0, + 2.9.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver%2Fgeode], xf86-video-geode) diff --git a/src/Makefile.am b/src/Makefile.am index 410aa70..15c9f66 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ geode_drv_la_SOURCES = \ geode_driver.c \ geode_common.c \ geode_dcon.c \ + geode_ddc.c \ geode_msr.c \ gx_driver.c\ gx_accel.c \ diff --git a/src/geode_ddc.c b/src/geode_ddc.c new file mode 100644 index 0000000..419c93b --- /dev/null +++ b/src/geode_ddc.c @@ -0,0 +1,188 @@ +/* Copyright (c) 2003-2007 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86Modes.h" +#include "compiler.h" +#include "geode.h" + +#ifdef XSERVER_LIBPCIACCESS +#include +#endif + +/* GPIO Register defines from the CS5536 datasheet */ + +#define GPIO_OUT 0x00 +#define GPIO_OUT_ENABLE 0x04 +#define GPIO_OUT_AUX1 0x10 +#define GPIO_IN_ENABLE 0x20 +#define GPIO_IN 0x30 +#define GPIO_IN_AUX1 0x34 + +/* The DDC pins are defined to be on GPIO pins 3 and 4 */ +#define DDC_SCL_PIN (1 << 3) +#define DDC_SDA_PIN (1 << 4) + +#define DDC_DATA_HIGH DDC_SDA_PIN +#define DDC_DATA_LOW (DDC_SDA_PIN << 16) + +#define DDC_CLK_HIGH DDC_SCL_PIN +#define DDC_CLK_LOW (DDC_SCL_PIN << 16) + +#define CS5536_ISA_DEVICE 0x20901022 + +static unsigned short +geode_gpio_iobase(void) +{ +#ifdef XSERVER_LIBPCIACCESS + struct pci_device *pci; + + /* The CS5536 GPIO device is always in the same slot: 00:0f.0 */ + pci = pci_device_find_by_slot(0, 0, 0xF, 0x0); + + if (pci == NULL) + return 0; + + /* The GPIO I/O address is in resource 1 */ + return (unsigned short)pci->regions[1].base_addr; +#else + PCITAG Tag; + + Tag = pciFindFirst(CS5536_ISA_DEVICE, 0xFFFFFFFF); + + if (Tag == PCI_NOT_FOUND) + return 0; + + /* The GPIO I/O address is in resource 1 */ + return (unsigned short)(pciReadLong(Tag, 0x14) & ~1); +#endif +} + +static void +geode_ddc_putbits(I2CBusPtr b, int scl, int sda) +{ + unsigned long iobase = (unsigned long)b->DriverPrivate.ptr; + unsigned long dat; + + dat = scl ? DDC_CLK_HIGH : DDC_CLK_LOW; + dat |= sda ? DDC_DATA_HIGH : DDC_DATA_LOW; + + outl(iobase + GPIO_OUT, dat); +} + +static void +geode_ddc_getbits(I2CBusPtr b, int *scl, int *sda) +{ + unsigned long iobase = (unsigned long)b->DriverPrivate.ptr; + unsigned long dat = inl(iobase + GPIO_IN); + + *scl = (dat & DDC_CLK_HIGH) ? 1 : 0; + *sda = (dat & DDC_DATA_HIGH) ? 1 : 0; +} + +static xf86MonPtr +GeodeGetDDC(ScrnInfoPtr pScrni) +{ + xf86MonPtr mon = NULL; + I2CBusPtr bus; + unsigned long ddciobase; + + ddciobase = geode_gpio_iobase(); + + if (ddciobase == 0) { + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "Could not find the GPIO I/O base\n"); + return NULL; + } + + /* The GPIO pins for DDC are multiplexed with a + * serial port. If that serial port is enabled, then + * assume that there is no DDC on the board + */ + + if ((inl(ddciobase + GPIO_IN_AUX1) & DDC_CLK_HIGH) || + (inl(ddciobase + GPIO_OUT_AUX1) & DDC_DATA_HIGH)) { + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "GPIO pins are in serial mode. Assuming no DDC\n"); + return NULL; + } + + /* Set up the pins */ + + outl(ddciobase + GPIO_OUT_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH); + outl(ddciobase + GPIO_IN_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH); + + bus = xf86CreateI2CBusRec(); + + if (bus == NULL) { + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "Could not create the I2C structre\n"); + goto err; + } + + bus->BusName = "CS5536 DDC BUS"; + bus->scrnIndex = pScrni->scrnIndex; + bus->I2CGetBits = geode_ddc_getbits; + bus->I2CPutBits = geode_ddc_putbits; + bus->DriverPrivate.ptr = (void *)(ddciobase); + + if (xf86I2CBusInit(bus)) { + mon = xf86DoEDID_DDC2(pScrni->scrnIndex, bus); + +#if (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,0,0)) + if (mon) + xf86DDCApplyQuirks(pScrni->scrnIndex, mon); +#endif + } + + xf86DestroyI2CBusRec(bus, FALSE, FALSE); + + err: + outl(ddciobase + GPIO_OUT_ENABLE, DDC_DATA_LOW | DDC_CLK_LOW); + outl(ddciobase + GPIO_IN_ENABLE, DDC_DATA_LOW | DDC_CLK_LOW); + + return mon; +} + +void +GeodeProbeDDC(ScrnInfoPtr pScrni, int index) +{ + ConfiguredMonitor = GeodeGetDDC(pScrni); +} + +xf86MonPtr +GeodeDoDDC(ScrnInfoPtr pScrni, int index) +{ + xf86MonPtr info = NULL; + + info = GeodeGetDDC(pScrni); + xf86PrintEDID(info); + xf86SetDDCproperties(pScrni, info); + return info; +} diff --git a/src/gx_driver.c b/src/gx_driver.c index 66aa31c..928a59a 100644 --- a/src/gx_driver.c +++ b/src/gx_driver.c @@ -436,8 +436,7 @@ GXPreInit(ScrnInfoPtr pScrni, int flags) useVGA = GXCheckVGA(pScrni); if (flags & PROBE_DETECT) { - if (useVGA) - GeodeProbeDDC(pScrni, pEnt->index); + GeodeProbeDDC(pScrni, pEnt->index); return TRUE; } @@ -664,10 +663,7 @@ GXPreInit(ScrnInfoPtr pScrni, int flags) GeodeClockRange->interlaceAllowed = TRUE; GeodeClockRange->doubleScanAllowed = FALSE; - if (pGeode->useVGA) - pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); - else - pScrni->monitor->DDC = NULL; + pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); /* I'm still not 100% sure this uses the right values */ @@ -1540,37 +1536,6 @@ GeodePointerMoved(int index, int x, int y) (*pGeode->PointerMoved) (index, newX, newY); } -void -GeodeProbeDDC(ScrnInfoPtr pScrni, int index) -{ - vbeInfoPtr pVbe; - - if (xf86LoadSubModule(pScrni, "vbe")) { - pVbe = VBEInit(NULL, index); - ConfiguredMonitor = vbeDoEDID(pVbe, NULL); - vbeFree(pVbe); - } -} - -xf86MonPtr -GeodeDoDDC(ScrnInfoPtr pScrni, int index) -{ - vbeInfoPtr pVbe; - xf86MonPtr info = NULL; - - if (xf86LoadSubModule(pScrni, "vbe") && (pVbe = VBEInit(NULL, index))) { - xf86LoaderReqSymLists(amdVbeSymbols, NULL); - info = vbeDoEDID(pVbe, NULL); - xf86PrintEDID(info); - xf86SetDDCproperties(pScrni, info); - vbeFree(pVbe); - } else - xf86DrvMsg(pScrni->scrnIndex, X_INFO, - "We cannot do DDC without VBE.\n"); - - return info; -} - int GeodeGetFPGeometry(const char *str, int *width, int *height) { diff --git a/src/lx_driver.c b/src/lx_driver.c index 973d54d..48aff44 100644 --- a/src/lx_driver.c +++ b/src/lx_driver.c @@ -519,7 +519,6 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) rgb defaultWeight = { 0, 0, 0 }; int modecnt; char *s, *panelgeo = NULL; - Bool useVGA; if (pScrni->numEntities != 1) return FALSE; @@ -529,12 +528,8 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) if (pEnt->resources) return FALSE; - useVGA = LXCheckVGA(pScrni); - if (flags & PROBE_DETECT) { - if (useVGA) - GeodeProbeDDC(pScrni, pEnt->index); - + GeodeProbeDDC(pScrni, pEnt->index); return TRUE; } @@ -543,7 +538,7 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) if (pGeode == NULL) return FALSE; - pGeode->useVGA = useVGA; + pGeode->useVGA = LXCheckVGA(pScrni); pGeode->VGAActive = FALSE; pGeode->pEnt = pEnt; @@ -769,7 +764,7 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) GeodeClockRange->interlaceAllowed = TRUE; GeodeClockRange->doubleScanAllowed = FALSE; - if (pGeode->useVGA && (pGeode->Output & OUTPUT_CRT)) + if (pGeode->Output & OUTPUT_CRT) pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); else pScrni->monitor->DDC = NULL;