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