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