geode_ddc.c revision 04007eba
1f29dbc25Smrg/* Copyright (c) 2003-2007 Advanced Micro Devices, Inc. 2f29dbc25Smrg * 3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to 5f29dbc25Smrg * deal in the Software without restriction, including without limitation the 6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is 8f29dbc25Smrg * furnished to do so, subject to the following conditions: 9f29dbc25Smrg * 10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 11f29dbc25Smrg * all copies or substantial portions of the Software. 12f29dbc25Smrg * 13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19f29dbc25Smrg * IN THE SOFTWARE. 20f29dbc25Smrg * 21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 23f29dbc25Smrg * software without specific prior written permission. 24f29dbc25Smrg * */ 25f29dbc25Smrg 26f29dbc25Smrg#ifdef HAVE_CONFIG_H 27f29dbc25Smrg#include "config.h" 28f29dbc25Smrg#endif 29f29dbc25Smrg 30f29dbc25Smrg#include "xf86.h" 31f29dbc25Smrg#include "xf86Modes.h" 32f29dbc25Smrg#include "compiler.h" 33f29dbc25Smrg#include "geode.h" 34f29dbc25Smrg 35f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS 36f29dbc25Smrg#include <pciaccess.h> 37f29dbc25Smrg#endif 38f29dbc25Smrg 39f29dbc25Smrg/* GPIO Register defines from the CS5536 datasheet */ 40f29dbc25Smrg 41f29dbc25Smrg#define GPIO_OUT 0x00 42f29dbc25Smrg#define GPIO_OUT_ENABLE 0x04 43f29dbc25Smrg#define GPIO_OUT_AUX1 0x10 44f29dbc25Smrg#define GPIO_IN_ENABLE 0x20 45f29dbc25Smrg#define GPIO_IN 0x30 46f29dbc25Smrg#define GPIO_IN_AUX1 0x34 47f29dbc25Smrg 48f29dbc25Smrg/* The DDC pins are defined to be on GPIO pins 3 and 4 */ 49f29dbc25Smrg#define DDC_SCL_PIN (1 << 3) 50f29dbc25Smrg#define DDC_SDA_PIN (1 << 4) 51f29dbc25Smrg 52f29dbc25Smrg#define DDC_DATA_HIGH DDC_SDA_PIN 53f29dbc25Smrg#define DDC_DATA_LOW (DDC_SDA_PIN << 16) 54f29dbc25Smrg 55f29dbc25Smrg#define DDC_CLK_HIGH DDC_SCL_PIN 56f29dbc25Smrg#define DDC_CLK_LOW (DDC_SCL_PIN << 16) 57f29dbc25Smrg 58f29dbc25Smrg#define CS5536_ISA_DEVICE 0x20901022 59f29dbc25Smrg#define CS5535_ISA_DEVICE 0x002b100b 60f29dbc25Smrg 61f29dbc25Smrgstatic unsigned short 62f29dbc25Smrggeode_gpio_iobase(void) 63f29dbc25Smrg{ 64f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS 65f29dbc25Smrg struct pci_device *pci; 66f29dbc25Smrg 67f29dbc25Smrg /* The CS5536 GPIO device is always in the same slot: 00:0f.0 */ 68f29dbc25Smrg /* The CS5535 device should be in same slot as well */ 69f29dbc25Smrg 70f29dbc25Smrg pci = pci_device_find_by_slot(0, 0, 0xF, 0x0); 71f29dbc25Smrg 72f29dbc25Smrg if (pci == NULL) 7304007ebaSmrg return 0; 74f29dbc25Smrg 75f29dbc25Smrg if (pci_device_probe(pci) != 0) 76f29dbc25Smrg return 0; 77f29dbc25Smrg 78f29dbc25Smrg /* The GPIO I/O address is in resource 1 */ 7904007ebaSmrg return (unsigned short) pci->regions[1].base_addr; 80f29dbc25Smrg#else 81f29dbc25Smrg PCITAG Tag; 82f29dbc25Smrg 83f29dbc25Smrg Tag = pciFindFirst(CS5536_ISA_DEVICE, 0xFFFFFFFF); 84f29dbc25Smrg 85f29dbc25Smrg if (Tag == PCI_NOT_FOUND) { 86f29dbc25Smrg Tag = pciFindFirst(CS5535_ISA_DEVICE, 0xFFFFFFFF); 87f29dbc25Smrg 88f29dbc25Smrg if (Tag == PCI_NOT_FOUND) 8904007ebaSmrg return 0; 90f29dbc25Smrg } 91f29dbc25Smrg 92f29dbc25Smrg /* The GPIO I/O address is in resource 1 */ 9304007ebaSmrg return (unsigned short) (pciReadLong(Tag, 0x14) & ~1); 94f29dbc25Smrg#endif 95f29dbc25Smrg} 96f29dbc25Smrg 97f29dbc25Smrgstatic void 98f29dbc25Smrggeode_ddc_putbits(I2CBusPtr b, int scl, int sda) 99f29dbc25Smrg{ 10004007ebaSmrg unsigned long iobase = (unsigned long) b->DriverPrivate.ptr; 101f29dbc25Smrg unsigned long dat; 102f29dbc25Smrg 103f29dbc25Smrg dat = scl ? DDC_CLK_HIGH : DDC_CLK_LOW; 104f29dbc25Smrg dat |= sda ? DDC_DATA_HIGH : DDC_DATA_LOW; 105f29dbc25Smrg 106f29dbc25Smrg outl(iobase + GPIO_OUT, dat); 107f29dbc25Smrg} 108f29dbc25Smrg 109f29dbc25Smrgstatic void 110f29dbc25Smrggeode_ddc_getbits(I2CBusPtr b, int *scl, int *sda) 111f29dbc25Smrg{ 11204007ebaSmrg unsigned long iobase = (unsigned long) b->DriverPrivate.ptr; 113f29dbc25Smrg unsigned long dat = inl(iobase + GPIO_IN); 114f29dbc25Smrg 115f29dbc25Smrg *scl = (dat & DDC_CLK_HIGH) ? 1 : 0; 116f29dbc25Smrg *sda = (dat & DDC_DATA_HIGH) ? 1 : 0; 117f29dbc25Smrg} 118f29dbc25Smrg 119f29dbc25SmrgBool 120f29dbc25SmrgGeodeI2CInit(ScrnInfoPtr pScrni, I2CBusPtr * ptr, char *name) 121f29dbc25Smrg{ 122f29dbc25Smrg I2CBusPtr bus; 123f29dbc25Smrg unsigned int ddciobase; 124f29dbc25Smrg 125f29dbc25Smrg ddciobase = geode_gpio_iobase(); 126f29dbc25Smrg 127f29dbc25Smrg if (ddciobase == 0) { 12804007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 12904007ebaSmrg "Could not find the GPIO I/O base\n"); 13004007ebaSmrg return FALSE; 131f29dbc25Smrg } 132f29dbc25Smrg 133f29dbc25Smrg /* The GPIO pins for DDC are multiplexed with a 134f29dbc25Smrg * serial port. If that serial port is enabled, then 135f29dbc25Smrg * assume that there is no DDC on the board 136f29dbc25Smrg */ 137f29dbc25Smrg 138f29dbc25Smrg if ((inl(ddciobase + GPIO_IN_AUX1) & DDC_CLK_HIGH) || 13904007ebaSmrg (inl(ddciobase + GPIO_OUT_AUX1) & DDC_DATA_HIGH)) { 14004007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 14104007ebaSmrg "GPIO pins are in serial mode. Assuming no DDC\n"); 14204007ebaSmrg return FALSE; 143f29dbc25Smrg } 144f29dbc25Smrg 145f29dbc25Smrg outl(ddciobase + GPIO_OUT_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH); 146f29dbc25Smrg outl(ddciobase + GPIO_IN_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH); 147f29dbc25Smrg 148f29dbc25Smrg bus = xf86CreateI2CBusRec(); 149f29dbc25Smrg 150f29dbc25Smrg if (!bus) 15104007ebaSmrg return FALSE; 152f29dbc25Smrg 153f29dbc25Smrg bus->BusName = name; 154f29dbc25Smrg bus->scrnIndex = pScrni->scrnIndex; 155f29dbc25Smrg 156f29dbc25Smrg bus->I2CGetBits = geode_ddc_getbits; 157f29dbc25Smrg bus->I2CPutBits = geode_ddc_putbits; 15804007ebaSmrg bus->DriverPrivate.ptr = (void *) (unsigned long) (ddciobase); 159f29dbc25Smrg 160f29dbc25Smrg if (!xf86I2CBusInit(bus)) 16104007ebaSmrg return FALSE; 162f29dbc25Smrg 163f29dbc25Smrg *ptr = bus; 164f29dbc25Smrg return TRUE; 165f29dbc25Smrg} 166f29dbc25Smrg 167f29dbc25Smrgstatic xf86MonPtr 168f29dbc25SmrgGeodeGetDDC(ScrnInfoPtr pScrni) 169f29dbc25Smrg{ 170f29dbc25Smrg xf86MonPtr mon = NULL; 171f29dbc25Smrg I2CBusPtr bus; 172f29dbc25Smrg 173f29dbc25Smrg if (!GeodeI2CInit(pScrni, &bus, "CS5536 DDC BUS")) 17404007ebaSmrg return NULL; 175f29dbc25Smrg 17604007ebaSmrg mon = xf86DoEDID_DDC2(DDC_CALL(pScrni), bus); 177f29dbc25Smrg 178f29dbc25Smrg#if (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,0,0)) 179f29dbc25Smrg if (mon) 18004007ebaSmrg xf86DDCApplyQuirks(pScrni->scrnIndex, mon); 181f29dbc25Smrg#endif 182f29dbc25Smrg 183f29dbc25Smrg xf86DestroyI2CBusRec(bus, FALSE, FALSE); 184f29dbc25Smrg 185f29dbc25Smrg return mon; 186f29dbc25Smrg} 187f29dbc25Smrg 188f29dbc25Smrgvoid 189f29dbc25SmrgGeodeProbeDDC(ScrnInfoPtr pScrni, int index) 190f29dbc25Smrg{ 191f29dbc25Smrg ConfiguredMonitor = GeodeGetDDC(pScrni); 192f29dbc25Smrg} 193f29dbc25Smrg 194f29dbc25Smrgxf86MonPtr 195f29dbc25SmrgGeodeDoDDC(ScrnInfoPtr pScrni, int index) 196f29dbc25Smrg{ 197f29dbc25Smrg xf86MonPtr info = NULL; 198f29dbc25Smrg 199f29dbc25Smrg info = GeodeGetDDC(pScrni); 200f29dbc25Smrg xf86PrintEDID(info); 201f29dbc25Smrg xf86SetDDCproperties(pScrni, info); 202f29dbc25Smrg return info; 203f29dbc25Smrg} 204