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