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