ddc.c revision 8223e2f2
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 318 return dev; 319} 320 321/* Mmmm, smell the hacks */ 322static void 323EEDIDStop(I2CDevPtr d) 324{ 325} 326 327/* block is the EDID block number. a segment is two blocks. */ 328static Bool 329DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) 330{ 331 unsigned char W_Buffer[1]; 332 int i, segment; 333 I2CDevPtr seg; 334 void (*stop)(I2CDevPtr); 335 336 for (i = 0; i < RETRIES; i++) { 337 /* Stop bits reset the segment pointer to 0, so be careful here. */ 338 segment = block >> 1; 339 if (segment) { 340 Bool b; 341 342 if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) 343 return FALSE; 344 345 W_Buffer[0] = segment; 346 347 stop = dev->pI2CBus->I2CStop; 348 dev->pI2CBus->I2CStop = EEDIDStop; 349 350 b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); 351 352 dev->pI2CBus->I2CStop = stop; 353 if (!b) { 354 dev->pI2CBus->I2CStop(dev); 355 continue; 356 } 357 } 358 359 W_Buffer[0] = (block & 0x01) * EDID1_LEN; 360 361 if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { 362 if (!DDC_checksum(R_Buffer, EDID1_LEN)) 363 return TRUE; 364 } 365 } 366 367 return FALSE; 368} 369 370/** 371 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 372 * unset. EDID information blocks are interpreted and the results returned in 373 * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return 374 * the complete EDID data, including all extension blocks, if the 'complete' 375 * parameter is TRUE; 376 * 377 * This function does not affect the list of modes used by drivers -- it is up 378 * to the driver to decide policy on what to do with EDID information. 379 * 380 * @return pointer to a new xf86MonPtr containing the EDID information. 381 * @return NULL if no monitor attached or failure to interpret the EDID. 382 */ 383xf86MonPtr 384xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) 385{ 386 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 387 unsigned char *EDID_block = NULL; 388 xf86MonPtr tmp = NULL; 389 I2CDevPtr dev = NULL; 390 /* Default DDC and DDC2 to enabled. */ 391 Bool noddc = FALSE, noddc2 = FALSE; 392 OptionInfoPtr options; 393 394 options = malloc(sizeof(DDCOptions)); 395 if (!options) 396 return NULL; 397 memcpy(options, DDCOptions, sizeof(DDCOptions)); 398 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 399 400 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 401 xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); 402 free(options); 403 404 if (noddc || noddc2) 405 return NULL; 406 407 if (!(dev = DDC2Init(scrnIndex, pBus))) 408 return NULL; 409 410 EDID_block = calloc(1, EDID1_LEN); 411 if (!EDID_block) 412 return NULL; 413 414 if (DDC2Read(dev, 0, EDID_block)) { 415 int i, n = EDID_block[0x7e]; 416 417 if (complete && n) { 418 EDID_block = realloc(EDID_block, EDID1_LEN * (1+n)); 419 420 for (i = 0; i < n; i++) 421 DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); 422 } 423 424 tmp = xf86InterpretEEDID(scrnIndex, EDID_block); 425 } 426 427 if (tmp && complete) 428 tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 429 430 return tmp; 431} 432 433/** 434 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 435 * unset. EDID information blocks are interpreted and the results returned in 436 * an xf86MonPtr. 437 * 438 * This function does not affect the list of modes used by drivers -- it is up 439 * to the driver to decide policy on what to do with EDID information. 440 * 441 * @return pointer to a new xf86MonPtr containing the EDID information. 442 * @return NULL if no monitor attached or failure to interpret the EDID. 443 */ 444xf86MonPtr 445xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) 446{ 447 return xf86DoEEDID(scrnIndex, pBus, FALSE); 448} 449 450/* XXX write me */ 451static void * 452DDC2ReadDisplayID(void) 453{ 454 return FALSE; 455} 456 457/** 458 * Attempts to probe the monitor for DisplayID information, if NoDDC and 459 * NoDDC2 are unset. DisplayID blocks are interpreted and the results 460 * returned in an xf86MonPtr. 461 * 462 * This function does not affect the list of modes used by drivers -- it is up 463 * to the driver to decide policy on what to do with DisplayID information. 464 * 465 * @return pointer to a new xf86MonPtr containing the DisplayID information. 466 * @return NULL if no monitor attached or failure to interpret the DisplayID. 467 */ 468xf86MonPtr 469xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) 470{ 471 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 472 unsigned char *did = NULL; 473 xf86MonPtr tmp = NULL; 474 I2CDevPtr dev = NULL; 475 /* Default DDC and DDC2 to enabled. */ 476 Bool noddc = FALSE, noddc2 = FALSE; 477 OptionInfoPtr options; 478 479 options = malloc(sizeof(DDCOptions)); 480 if (!options) 481 return NULL; 482 memcpy(options, DDCOptions, sizeof(DDCOptions)); 483 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 484 485 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 486 xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); 487 free(options); 488 489 if (noddc || noddc2) 490 return NULL; 491 492 if (!(dev = DDC2Init(scrnIndex, pBus))) 493 return NULL; 494 495 if ((did = DDC2ReadDisplayID())) { 496 tmp = calloc(1, sizeof(*tmp)); 497 if (!tmp) 498 return NULL; 499 500 tmp->scrnIndex = scrnIndex; 501 tmp->flags |= MONITOR_DISPLAYID; 502 tmp->rawData = did; 503 } 504 505 return tmp; 506} 507