~ubuntu-branches/ubuntu/precise/xserver-xorg-video-geode-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/geode_ddc.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:59:48 UTC
  • Revision ID: package-import@ubuntu.com-20121130205948-8p83molp6tff7m8o
Tags: upstream-2.11.13+git20120726
ImportĀ upstreamĀ versionĀ 2.11.13+git20120726

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "xf86.h"
 
31
#include "xf86Modes.h"
 
32
#include "compiler.h"
 
33
#include "geode.h"
 
34
 
 
35
#ifdef XSERVER_LIBPCIACCESS
 
36
#include <pciaccess.h>
 
37
#endif
 
38
 
 
39
/* GPIO Register defines from the CS5536 datasheet */
 
40
 
 
41
#define GPIO_OUT        0x00
 
42
#define GPIO_OUT_ENABLE 0x04
 
43
#define GPIO_OUT_AUX1   0x10
 
44
#define GPIO_IN_ENABLE  0x20
 
45
#define GPIO_IN         0x30
 
46
#define GPIO_IN_AUX1    0x34
 
47
 
 
48
/* The DDC pins are defined to be on GPIO pins 3 and 4 */
 
49
#define DDC_SCL_PIN  (1 << 3)
 
50
#define DDC_SDA_PIN  (1 << 4)
 
51
 
 
52
#define DDC_DATA_HIGH    DDC_SDA_PIN
 
53
#define DDC_DATA_LOW     (DDC_SDA_PIN << 16)
 
54
 
 
55
#define DDC_CLK_HIGH     DDC_SCL_PIN
 
56
#define DDC_CLK_LOW      (DDC_SCL_PIN << 16)
 
57
 
 
58
#define CS5536_ISA_DEVICE 0x20901022
 
59
#define CS5535_ISA_DEVICE 0x002b100b
 
60
 
 
61
static unsigned short
 
62
geode_gpio_iobase(void)
 
63
{
 
64
#ifdef XSERVER_LIBPCIACCESS
 
65
    struct pci_device *pci;
 
66
 
 
67
    /* The CS5536 GPIO device is always in the same slot: 00:0f.0 */
 
68
    /* The CS5535 device should be in same slot as well */
 
69
 
 
70
    pci = pci_device_find_by_slot(0, 0, 0xF, 0x0);
 
71
 
 
72
    if (pci == NULL)
 
73
        return 0;
 
74
 
 
75
    if (pci_device_probe(pci) != 0)
 
76
        return 0;
 
77
 
 
78
    /* The GPIO I/O address is in resource 1 */
 
79
    return (unsigned short) pci->regions[1].base_addr;
 
80
#else
 
81
    PCITAG Tag;
 
82
 
 
83
    Tag = pciFindFirst(CS5536_ISA_DEVICE, 0xFFFFFFFF);
 
84
 
 
85
    if (Tag == PCI_NOT_FOUND) {
 
86
        Tag = pciFindFirst(CS5535_ISA_DEVICE, 0xFFFFFFFF);
 
87
 
 
88
        if (Tag == PCI_NOT_FOUND)
 
89
            return 0;
 
90
    }
 
91
 
 
92
    /* The GPIO I/O address is in resource 1 */
 
93
    return (unsigned short) (pciReadLong(Tag, 0x14) & ~1);
 
94
#endif
 
95
}
 
96
 
 
97
static void
 
98
geode_ddc_putbits(I2CBusPtr b, int scl, int sda)
 
99
{
 
100
    unsigned long iobase = (unsigned long) b->DriverPrivate.ptr;
 
101
    unsigned long dat;
 
102
 
 
103
    dat = scl ? DDC_CLK_HIGH : DDC_CLK_LOW;
 
104
    dat |= sda ? DDC_DATA_HIGH : DDC_DATA_LOW;
 
105
 
 
106
    outl(iobase + GPIO_OUT, dat);
 
107
}
 
108
 
 
109
static void
 
110
geode_ddc_getbits(I2CBusPtr b, int *scl, int *sda)
 
111
{
 
112
    unsigned long iobase = (unsigned long) b->DriverPrivate.ptr;
 
113
    unsigned long dat = inl(iobase + GPIO_IN);
 
114
 
 
115
    *scl = (dat & DDC_CLK_HIGH) ? 1 : 0;
 
116
    *sda = (dat & DDC_DATA_HIGH) ? 1 : 0;
 
117
}
 
118
 
 
119
Bool
 
120
GeodeI2CInit(ScrnInfoPtr pScrni, I2CBusPtr * ptr, char *name)
 
121
{
 
122
    I2CBusPtr bus;
 
123
    unsigned int ddciobase;
 
124
 
 
125
    ddciobase = geode_gpio_iobase();
 
126
 
 
127
    if (ddciobase == 0) {
 
128
        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
 
129
                   "Could not find the GPIO I/O base\n");
 
130
        return FALSE;
 
131
    }
 
132
 
 
133
    /* The GPIO pins for DDC are multiplexed with a
 
134
     * serial port.  If that serial port is enabled, then
 
135
     * assume that there is no DDC on the board
 
136
     */
 
137
 
 
138
    if ((inl(ddciobase + GPIO_IN_AUX1) & DDC_CLK_HIGH) ||
 
139
        (inl(ddciobase + GPIO_OUT_AUX1) & DDC_DATA_HIGH)) {
 
140
        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
 
141
                   "GPIO pins are in serial mode.  Assuming no DDC\n");
 
142
        return FALSE;
 
143
    }
 
144
 
 
145
    outl(ddciobase + GPIO_OUT_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH);
 
146
    outl(ddciobase + GPIO_IN_ENABLE, DDC_DATA_HIGH | DDC_CLK_HIGH);
 
147
 
 
148
    bus = xf86CreateI2CBusRec();
 
149
 
 
150
    if (!bus)
 
151
        return FALSE;
 
152
 
 
153
    bus->BusName = name;
 
154
    bus->scrnIndex = pScrni->scrnIndex;
 
155
 
 
156
    bus->I2CGetBits = geode_ddc_getbits;
 
157
    bus->I2CPutBits = geode_ddc_putbits;
 
158
    bus->DriverPrivate.ptr = (void *) (unsigned long) (ddciobase);
 
159
 
 
160
    if (!xf86I2CBusInit(bus))
 
161
        return FALSE;
 
162
 
 
163
    *ptr = bus;
 
164
    return TRUE;
 
165
}
 
166
 
 
167
static xf86MonPtr
 
168
GeodeGetDDC(ScrnInfoPtr pScrni)
 
169
{
 
170
    xf86MonPtr mon = NULL;
 
171
    I2CBusPtr bus;
 
172
 
 
173
    if (!GeodeI2CInit(pScrni, &bus, "CS5536 DDC BUS"))
 
174
        return NULL;
 
175
 
 
176
    mon = xf86DoEDID_DDC2(DDC_CALL(pScrni), bus);
 
177
 
 
178
#if (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,0,0))
 
179
    if (mon)
 
180
        xf86DDCApplyQuirks(pScrni->scrnIndex, mon);
 
181
#endif
 
182
 
 
183
    xf86DestroyI2CBusRec(bus, FALSE, FALSE);
 
184
 
 
185
    return mon;
 
186
}
 
187
 
 
188
void
 
189
GeodeProbeDDC(ScrnInfoPtr pScrni, int index)
 
190
{
 
191
    ConfiguredMonitor = GeodeGetDDC(pScrni);
 
192
}
 
193
 
 
194
xf86MonPtr
 
195
GeodeDoDDC(ScrnInfoPtr pScrni, int index)
 
196
{
 
197
    xf86MonPtr info = NULL;
 
198
 
 
199
    info = GeodeGetDDC(pScrni);
 
200
    xf86PrintEDID(info);
 
201
    xf86SetDDCproperties(pScrni, info);
 
202
    return info;
 
203
}