ddc.c revision 6747b715
1/* xf86DDC.c 2 * 3 * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> 4 */ 5 6/* 7 * A note on terminology. DDC1 is the original dumb serial protocol, and 8 * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and 9 * introduces extension blocks. EDID is the old display identification 10 * block, DisplayID is the new one. 11 */ 12 13#ifdef HAVE_XORG_CONFIG_H 14#include <xorg-config.h> 15#endif 16 17#include "misc.h" 18#include "xf86.h" 19#include "xf86_OSproc.h" 20#include "xf86DDC.h" 21#include <string.h> 22 23#define RETRIES 4 24 25typedef enum { 26 DDCOPT_NODDC1, 27 DDCOPT_NODDC2, 28 DDCOPT_NODDC 29} DDCOpts; 30 31static const OptionInfoRec DDCOptions[] = { 32 { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, 33 { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, 34 { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, 35 { -1, NULL, OPTV_NONE, {0}, FALSE }, 36}; 37 38/* DDC1 */ 39 40static int 41find_start(unsigned int *ptr) 42{ 43 unsigned int comp[9], test[9]; 44 int i,j; 45 46 for (i=0;i<9;i++){ 47 comp[i] = *(ptr++); 48 test[i] = 1; 49 } 50 for (i=0;i<127;i++){ 51 for (j=0;j<9;j++){ 52 test[j] = test[j] & !(comp[j] ^ *(ptr++)); 53 } 54 } 55 for (i=0;i<9;i++) 56 if (test[i]) return i+1; 57 return -1; 58} 59 60static unsigned char * 61find_header(unsigned char *block) 62{ 63 unsigned char *ptr, *head_ptr, *end; 64 unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; 65 66 ptr = block; 67 end = block + EDID1_LEN; 68 while (ptr<end) { 69 int i; 70 head_ptr = ptr; 71 for (i=0;i<8;i++){ 72 if (header[i] != *(head_ptr++)) break; 73 if (head_ptr == end) head_ptr = block; 74 } 75 if (i==8) break; 76 ptr++; 77 } 78 if (ptr == end) return NULL; 79 return ptr; 80} 81 82static unsigned char * 83resort(unsigned char *s_block) 84{ 85 unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; 86 unsigned char tmp; 87 88 s_end = s_block + EDID1_LEN; 89 d_new = malloc(EDID1_LEN); 90 if (!d_new) return NULL; 91 d_end = d_new + EDID1_LEN; 92 93 s_ptr = find_header(s_block); 94 if (!s_ptr) return NULL; 95 for (d_ptr=d_new;d_ptr<d_end;d_ptr++){ 96 tmp = *(s_ptr++); 97 *d_ptr = tmp; 98 if (s_ptr == s_end) s_ptr = s_block; 99 } 100 free(s_block); 101 return d_new; 102} 103 104static int 105DDC_checksum(const unsigned char *block, int len) 106{ 107 int i, result = 0; 108 int not_null = 0; 109 110 for (i=0;i<len;i++) { 111 not_null |= block[i]; 112 result += block[i]; 113 } 114 115#ifdef DEBUG 116 if (result & 0xFF) ErrorF("DDC checksum not correct\n"); 117 if (!not_null) ErrorF("DDC read all Null\n"); 118#endif 119 120 /* catch the trivial case where all bytes are 0 */ 121 if (!not_null) return 1; 122 123 return result&0xFF; 124} 125 126static unsigned char * 127GetEDID_DDC1(unsigned int *s_ptr) 128{ 129 unsigned char *d_block, *d_pos; 130 unsigned int *s_pos, *s_end; 131 int s_start; 132 int i,j; 133 s_start = find_start(s_ptr); 134 if (s_start==-1) return NULL; 135 s_end = s_ptr + NUM; 136 s_pos = s_ptr + s_start; 137 d_block=malloc(EDID1_LEN); 138 if (!d_block) return NULL; 139 d_pos = d_block; 140 for (i=0;i<EDID1_LEN;i++) { 141 for (j=0;j<8;j++) { 142 *d_pos <<= 1; 143 if (*s_pos) { 144 *d_pos |= 0x01; 145 } 146 s_pos++; if (s_pos == s_end) s_pos=s_ptr; 147 }; 148 s_pos++; if (s_pos == s_end) s_pos=s_ptr; 149 d_pos++; 150 } 151 free(s_ptr); 152 if (d_block && DDC_checksum(d_block,EDID1_LEN)) { 153 free(d_block); 154 return NULL; 155 } 156 return (resort(d_block)); 157} 158 159/* fetch entire EDID record; DDC bit needs to be masked */ 160static unsigned int * 161FetchEDID_DDC1(register ScrnInfoPtr pScrn, 162 register unsigned int (*read_DDC)(ScrnInfoPtr)) 163{ 164 int count = NUM; 165 unsigned int *ptr, *xp; 166 167 ptr=xp=malloc(sizeof(int)*NUM); 168 169 if (!ptr) return NULL; 170 do { 171 /* wait for next retrace */ 172 *xp = read_DDC(pScrn); 173 xp++; 174 } while(--count); 175 return ptr; 176} 177 178/* test if DDC1 return 0 if not */ 179static Bool 180TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr)) 181{ 182 int old, count; 183 184 old = read_DDC(pScrn); 185 count = HEADER * BITS_PER_BYTE; 186 do { 187 /* wait for next retrace */ 188 if (old != read_DDC(pScrn)) break; 189 } while(count--); 190 return count; 191} 192 193/* 194 * read EDID record , pass it to callback function to interpret. 195 * callback function will store it for further use by calling 196 * function; it will also decide if we need to reread it 197 */ 198static unsigned char * 199EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, 200 unsigned int (*read_DDC)(ScrnInfoPtr)) 201{ 202 unsigned char *EDID_block = NULL; 203 int count = RETRIES; 204 205 if (!read_DDC) { 206 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 207 "chipset doesn't support DDC1\n"); 208 return NULL; 209 }; 210 211 if (TestDDC1(pScrn,read_DDC)==-1) { 212 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); 213 return NULL; 214 }; 215 216 if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); 217 do { 218 EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); 219 count --; 220 } while (!EDID_block && count); 221 if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); 222 223 return EDID_block; 224} 225 226/** 227 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are 228 * unset. EDID information blocks are interpreted and the results returned in 229 * an xf86MonPtr. 230 * 231 * This function does not affect the list of modes used by drivers -- it is up 232 * to the driver to decide policy on what to do with EDID information. 233 * 234 * @return pointer to a new xf86MonPtr containing the EDID information. 235 * @return NULL if no monitor attached or failure to interpret the EDID. 236 */ 237xf86MonPtr 238xf86DoEDID_DDC1( 239 int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, 240 unsigned int (*DDC1Read)(ScrnInfoPtr) 241) 242{ 243 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 244 unsigned char *EDID_block = NULL; 245 xf86MonPtr tmp = NULL; 246 int sigio; 247 /* Default DDC and DDC1 to enabled. */ 248 Bool noddc = FALSE, noddc1 = FALSE; 249 OptionInfoPtr options; 250 251 options = xnfalloc(sizeof(DDCOptions)); 252 (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); 253 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 254 255 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 256 xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); 257 free(options); 258 259 if (noddc || noddc1) 260 return NULL; 261 262 sigio = xf86BlockSIGIO(); 263 EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); 264 xf86UnblockSIGIO(sigio); 265 266 if (EDID_block){ 267 tmp = xf86InterpretEDID(scrnIndex,EDID_block); 268 } 269#ifdef DEBUG 270 else ErrorF("No EDID block returned\n"); 271 if (!tmp) 272 ErrorF("Cannot interpret EDID block\n"); 273#endif 274 return tmp; 275} 276 277/* DDC2 */ 278 279static I2CDevPtr 280DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) 281{ 282 I2CDevPtr dev = NULL; 283 284 if (!(dev = xf86I2CFindDev(pBus, address))) { 285 dev = xf86CreateI2CDevRec(); 286 dev->DevName = name; 287 dev->SlaveAddr = address; 288 dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ 289 dev->StartTimeout = 550; 290 dev->BitTimeout = 40; 291 dev->AcknTimeout = 40; 292 293 dev->pI2CBus = pBus; 294 if (!xf86I2CDevInit(dev)) { 295 xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); 296 return NULL; 297 } 298 } 299 300 return dev; 301} 302 303static I2CDevPtr 304DDC2Init(int scrnIndex, I2CBusPtr pBus) 305{ 306 I2CDevPtr dev = NULL; 307 308 /* 309 * Slow down the bus so that older monitors don't 310 * miss things. 311 */ 312 pBus->RiseFallTime = 20; 313 314 dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); 315 if (xf86I2CProbeAddress(pBus, 0x0060)) 316 DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); 317 if (xf86I2CProbeAddress(pBus, 0x0062)) 318 DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface"); 319 if (xf86I2CProbeAddress(pBus, 0x006E)) 320 DDC2MakeDevice(pBus, 0x006E, "DDC control interface"); 321 322 return dev; 323} 324 325/* Mmmm, smell the hacks */ 326static void 327EEDIDStop(I2CDevPtr d) 328{ 329} 330 331/* block is the EDID block number. a segment is two blocks. */ 332static Bool 333DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) 334{ 335 unsigned char W_Buffer[1]; 336 int i, segment; 337 I2CDevPtr seg; 338 void (*stop)(I2CDevPtr); 339 340 for (i = 0; i < RETRIES; i++) { 341 /* Stop bits reset the segment pointer to 0, so be careful here. */ 342 segment = block >> 1; 343 if (segment) { 344 Bool b; 345 346 if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) 347 return FALSE; 348 349 W_Buffer[0] = segment; 350 351 stop = dev->pI2CBus->I2CStop; 352 dev->pI2CBus->I2CStop = EEDIDStop; 353 354 b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); 355 356 dev->pI2CBus->I2CStop = stop; 357 if (!b) { 358 dev->pI2CBus->I2CStop(dev); 359 continue; 360 } 361 } 362 363 W_Buffer[0] = (block & 0x01) * EDID1_LEN; 364 365 if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { 366 if (!DDC_checksum(R_Buffer, EDID1_LEN)) 367 return TRUE; 368 } 369 } 370 371 return FALSE; 372} 373 374/** 375 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 376 * unset. EDID information blocks are interpreted and the results returned in 377 * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return 378 * the complete EDID data, including all extension blocks, if the 'complete' 379 * parameter is TRUE; 380 * 381 * This function does not affect the list of modes used by drivers -- it is up 382 * to the driver to decide policy on what to do with EDID information. 383 * 384 * @return pointer to a new xf86MonPtr containing the EDID information. 385 * @return NULL if no monitor attached or failure to interpret the EDID. 386 */ 387xf86MonPtr 388xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) 389{ 390 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 391 unsigned char *EDID_block = NULL; 392 xf86MonPtr tmp = NULL; 393 I2CDevPtr dev = NULL; 394 /* Default DDC and DDC2 to enabled. */ 395 Bool noddc = FALSE, noddc2 = FALSE; 396 OptionInfoPtr options; 397 398 options = malloc(sizeof(DDCOptions)); 399 if (!options) 400 return NULL; 401 memcpy(options, DDCOptions, sizeof(DDCOptions)); 402 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 403 404 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 405 xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); 406 free(options); 407 408 if (noddc || noddc2) 409 return NULL; 410 411 if (!(dev = DDC2Init(scrnIndex, pBus))) 412 return NULL; 413 414 EDID_block = calloc(1, EDID1_LEN); 415 if (!EDID_block) 416 return NULL; 417 418 if (DDC2Read(dev, 0, EDID_block)) { 419 int i, n = EDID_block[0x7e]; 420 421 if (complete && n) { 422 EDID_block = realloc(EDID_block, EDID1_LEN * (1+n)); 423 424 for (i = 0; i < n; i++) 425 DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); 426 } 427 428 tmp = xf86InterpretEEDID(scrnIndex, EDID_block); 429 } 430 431 if (tmp && complete) 432 tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 433 434 return tmp; 435} 436 437/** 438 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 439 * unset. EDID information blocks are interpreted and the results returned in 440 * an xf86MonPtr. 441 * 442 * This function does not affect the list of modes used by drivers -- it is up 443 * to the driver to decide policy on what to do with EDID information. 444 * 445 * @return pointer to a new xf86MonPtr containing the EDID information. 446 * @return NULL if no monitor attached or failure to interpret the EDID. 447 */ 448xf86MonPtr 449xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) 450{ 451 return xf86DoEEDID(scrnIndex, pBus, FALSE); 452} 453 454/* XXX write me */ 455static void * 456DDC2ReadDisplayID(void) 457{ 458 return FALSE; 459} 460 461/** 462 * Attempts to probe the monitor for DisplayID information, if NoDDC and 463 * NoDDC2 are unset. DisplayID blocks are interpreted and the results 464 * returned in an xf86MonPtr. 465 * 466 * This function does not affect the list of modes used by drivers -- it is up 467 * to the driver to decide policy on what to do with DisplayID information. 468 * 469 * @return pointer to a new xf86MonPtr containing the DisplayID information. 470 * @return NULL if no monitor attached or failure to interpret the DisplayID. 471 */ 472xf86MonPtr 473xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) 474{ 475 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 476 unsigned char *did = NULL; 477 xf86MonPtr tmp = NULL; 478 I2CDevPtr dev = NULL; 479 /* Default DDC and DDC2 to enabled. */ 480 Bool noddc = FALSE, noddc2 = FALSE; 481 OptionInfoPtr options; 482 483 options = malloc(sizeof(DDCOptions)); 484 if (!options) 485 return NULL; 486 memcpy(options, DDCOptions, sizeof(DDCOptions)); 487 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 488 489 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 490 xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); 491 free(options); 492 493 if (noddc || noddc2) 494 return NULL; 495 496 if (!(dev = DDC2Init(scrnIndex, pBus))) 497 return NULL; 498 499 if ((did = DDC2ReadDisplayID())) { 500 tmp = calloc(1, sizeof(*tmp)); 501 if (!tmp) 502 return NULL; 503 504 tmp->scrnIndex = scrnIndex; 505 tmp->flags |= MONITOR_DISPLAYID; 506 tmp->rawData = did; 507 } 508 509 return tmp; 510} 511