ct_ddc.c revision 7a5ec427
1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6/* All drivers should typically include these */ 7#include "xf86.h" 8#include "xf86_OSproc.h" 9 10/* Everything using inb/outb, etc needs "compiler.h" */ 11#include "compiler.h" 12 13/* Drivers that need to access the PCI config space directly need this */ 14#include "xf86Pci.h" 15 16#include "ct_driver.h" 17 18static Bool chips_TestI2C(int scrnIndex); 19static Bool chips_setI2CBits(I2CBusPtr I2CPtr, ScrnInfoPtr pScrn); 20 21static unsigned int 22chips_ddc1Read(ScrnInfoPtr pScrn) 23{ 24 unsigned char ddc_mask = ((CHIPSPtr)pScrn->driverPrivate)->ddc_mask; 25 CHIPSPtr cPtr = CHIPSPTR(pScrn); 26 vgaHWPtr hwp = VGAHWPTR(pScrn); 27 28 register unsigned int tmp; 29 30 while ((hwp->readST01(hwp)) & 0x08){}; 31 while (!((hwp->readST01(hwp)) & 0x08)){}; 32 tmp = cPtr->readXR(cPtr, 0x63); 33 return (tmp & ddc_mask); 34} 35 36static void 37chips_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) 38{ 39 vgaHWddc1SetSpeed(pScrn, speed); 40} 41 42void 43chips_ddc1(ScrnInfoPtr pScrn) 44{ 45 unsigned char FR0B, FR0C, XR62; 46 unsigned char mask_c = 0x00; 47 unsigned char val, tmp_val = 0; 48 int i; 49 CHIPSPtr cPtr = CHIPSPTR(pScrn); 50 51 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for DDC1\n"); 52 53 FR0C = cPtr->readFR(cPtr, 0x0C); 54 XR62 = cPtr->readXR(cPtr, 0x62); 55 switch (cPtr->Chipset) { 56 case CHIPS_CT65550: 57 cPtr->ddc_mask = 0x1F; /* GPIO 0-4 */ 58 FR0B = cPtr->readFR(cPtr, 0x0B); 59 if (!(FR0B & 0x10)) /* GPIO 2 is used as 32 kHz input */ 60 cPtr->ddc_mask &= 0xFB; 61 if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */ 62 cPtr->ddc_mask &= 0x07; 63 break; 64 case CHIPS_CT65554: 65 case CHIPS_CT65555: 66 case CHIPS_CT68554: 67 cPtr->ddc_mask = 0x0F; /* GPIO 0-3 */ 68 break; 69 case CHIPS_CT69000: 70 case CHIPS_CT69030: 71 cPtr->ddc_mask = 0x9F; /* GPIO 0-4,7? */ 72 break; 73 default: 74 cPtr->ddc_mask = 0x0C; /* GPIO 2,3 */ 75 break; 76 } 77 if (!(FR0C & 0x80)) { /* GPIO 1 is not available */ 78 mask_c |= 0xC0; 79 cPtr->ddc_mask &= 0xFE; 80 } 81 if (!(FR0C & 0x10)) { /* GPIO 0 is not available */ 82 mask_c |= 0x18; 83 cPtr->ddc_mask &= 0xFD; 84 } 85 86 /* set GPIO 0,1 to read if available */ 87 cPtr->writeFR(cPtr, 0x0C, (FR0C & mask_c) | (~mask_c & 0x90)); 88 /* set remaining GPIO to read */ 89 cPtr->writeXR(cPtr, 0x62, 0x00); 90 91 val = chips_ddc1Read(pScrn); 92 for (i = 0; i < 70; i++) { 93 tmp_val = chips_ddc1Read(pScrn); 94 if (tmp_val != val) 95 break; 96 } 97 cPtr->ddc_mask = val ^ tmp_val; 98 if (cPtr->ddc_mask) 99 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC1 found\n"); 100 else return; 101 102 xf86PrintEDID(xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn), chips_ddc1SetSpeed, 103 chips_ddc1Read)); 104 105 /* restore */ 106 cPtr->writeFR(cPtr, 0x0C, FR0C); 107 cPtr->writeXR(cPtr, 0x62, XR62); 108} 109 110static void 111chips_I2CGetBits(I2CBusPtr b, int *clock, int *data) 112{ 113 CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); 114 unsigned char FR0C, XR62, val; 115 116 FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C); 117 if (pI2C_c->i2cDataBit & 0x01 || pI2C_c->i2cClockBit & 0x01) 118 FR0C = (FR0C & 0xE7) | 0x10; 119 if (pI2C_c->i2cDataBit & 0x02 || pI2C_c->i2cClockBit & 0x02) 120 FR0C = (FR0C & 0x3F) | 0x80; 121 XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62); 122 XR62 &= (~pI2C_c->i2cDataBit) & (~pI2C_c->i2cClockBit); 123 pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C); 124 pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62); 125 val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63); 126 *clock = (val & pI2C_c->i2cClockBit) != 0; 127 *data = (val & pI2C_c->i2cDataBit) != 0; 128} 129 130static void 131chips_I2CPutBits(I2CBusPtr b, int clock, int data) 132{ 133 CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); 134 unsigned char FR0C, XR62, val; 135 136 FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C); 137 if (((pI2C_c->i2cDataBit & 0x01) && data) 138 || ((pI2C_c->i2cClockBit & 0x01) && clock)) 139 FR0C |= 0x18; 140 else if ((pI2C_c->i2cDataBit & 0x01) 141 || (pI2C_c->i2cClockBit & 0x01)) 142 FR0C |= 0x10; 143 if (((pI2C_c->i2cDataBit & 0x02) && data) 144 || ((pI2C_c->i2cClockBit & 0x02) && clock)) 145 FR0C |= 0xC0; 146 else if ((pI2C_c->i2cDataBit & 0x02) 147 || (pI2C_c->i2cClockBit & 0x02)) 148 FR0C |= 0x80; 149 XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62); 150 XR62 = (XR62 & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0); 151 XR62 = (XR62 & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0); 152 pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C); 153 pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62); 154 val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63); 155 val = (val & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0); 156 val = (val & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0); 157 pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x63, val); 158} 159 160 161Bool 162chips_i2cInit(ScrnInfoPtr pScrn) 163{ 164 CHIPSPtr cPtr = CHIPSPTR(pScrn); 165 I2CBusPtr I2CPtr; 166 167 I2CPtr = xf86CreateI2CBusRec(); 168 if(!I2CPtr) return FALSE; 169 170 cPtr->I2C = I2CPtr; 171 172 I2CPtr->BusName = "DDC"; 173 I2CPtr->scrnIndex = pScrn->scrnIndex; 174 I2CPtr->I2CPutBits = chips_I2CPutBits; 175 I2CPtr->I2CGetBits = chips_I2CGetBits; 176 I2CPtr->DriverPrivate.ptr = malloc(sizeof(CHIPSI2CRec)); 177 ((CHIPSI2CPtr)(I2CPtr->DriverPrivate.ptr))->cPtr = cPtr; 178 179 if (!xf86I2CBusInit(I2CPtr)) 180 return FALSE; 181 182 if (!chips_setI2CBits(I2CPtr, pScrn)) 183 return FALSE; 184 185 return TRUE; 186} 187 188static Bool 189chips_setI2CBits(I2CBusPtr b, ScrnInfoPtr pScrn) 190{ 191 CHIPSPtr cPtr = CHIPSPTR(pScrn); 192 CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); 193 unsigned char FR0B, FR0C; 194 unsigned char bits, data_bits, clock_bits; 195 int i,j; 196 197 FR0C = cPtr->readFR(cPtr, 0x0C); 198 switch (cPtr->Chipset) { 199 case CHIPS_CT65550: 200 bits = 0x1F; /* GPIO 0-4 */ 201 FR0B = cPtr->readFR(cPtr, 0x0B); 202 if (!(FR0B & 0x10)) /* GPIO 2 is used as 32 kHz input */ 203 bits &= 0xFB; 204 pI2C_c->i2cDataBit = 0x01; 205 pI2C_c->i2cClockBit = 0x02; 206 if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */ 207 bits &= 0x07; 208 break; 209 case CHIPS_CT65554: 210 case CHIPS_CT65555: 211 case CHIPS_CT68554: 212 bits = 0x0F; /* GPIO 0-3 */ 213 pI2C_c->i2cDataBit = 0x04; 214 pI2C_c->i2cClockBit = 0x08; 215 break; 216 case CHIPS_CT69000: 217 case CHIPS_CT69030: 218 bits = 0x9F; /* GPIO 0-4,7? */ 219 pI2C_c->i2cDataBit = 0x04; 220 pI2C_c->i2cClockBit = 0x08; 221 break; 222 default: 223 bits = 0x0C; /* GPIO 2,3 */ 224 pI2C_c->i2cDataBit = 0x04; 225 pI2C_c->i2cClockBit = 0x08; 226 break; 227 } 228 if (!(FR0C & 0x80)) { /* GPIO 1 is not available */ 229 bits &= 0xFE; 230 } 231 if (!(FR0C & 0x10)) { /* GPIO 0 is not available */ 232 bits &= 0xFD; 233 } 234 pI2C_c->i2cClockBit &= bits; 235 pI2C_c->i2cDataBit &= bits; 236 /* 237 * first we test out the "favorite" GPIO bits ie. the ones suggested 238 * by the data book; if we don't succeed test all other combinations 239 * of possible GPIO pins as data/clock lines as the manufacturer might 240 * have its own ideas. 241 */ 242 if (chips_TestI2C(pScrn->scrnIndex)) return TRUE; 243 244 data_bits = bits; 245 pI2C_c->i2cDataBit = 0x01; 246 for (i = 0; i<8; i++) { 247 if (data_bits & 0x01) { 248 clock_bits = bits; 249 pI2C_c->i2cClockBit = 0x01; 250 for (j = 0; j<8; j++) { 251 if (clock_bits & 0x01) 252 if (chips_TestI2C(pScrn->scrnIndex)) return TRUE; 253 clock_bits >>= 1; 254 pI2C_c->i2cClockBit <<= 1; 255 } 256 } 257 data_bits >>= 1; 258 pI2C_c->i2cDataBit <<= 1; 259 } 260 /* 261 * We haven't found a valid clock/data line combination - that 262 * doesn't mean there aren't any. We just haven't received an 263 * answer from the relevant DDC I2C addresses. We'll have to wait 264 * and see, if this is too restrictive (eg one wants to use I2C 265 * for something else than DDC we might have to probe more addresses 266 * or just fall back to the "favorite" GPIO lines. 267 */ 268 return FALSE; 269} 270 271static Bool 272chips_TestI2C(int scrnIndex) 273{ 274 int i; 275 I2CBusPtr b; 276 277 b = xf86I2CFindBus(scrnIndex, "DDC"); 278 if (b == NULL) return FALSE; 279 else { 280 for(i = 0xA0; i < 0xA8; i += 2) 281 if(xf86I2CProbeAddress(b, i)) 282 return TRUE; 283 } 284 return FALSE; 285} 286 287 288