135c4bbdfSmrg/* xf86DDC.c 235c4bbdfSmrg * 36747b715Smrg * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> 46747b715Smrg */ 56747b715Smrg 66747b715Smrg/* 76747b715Smrg * A note on terminology. DDC1 is the original dumb serial protocol, and 86747b715Smrg * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and 96747b715Smrg * introduces extension blocks. EDID is the old display identification 106747b715Smrg * block, DisplayID is the new one. 116747b715Smrg */ 126747b715Smrg 136747b715Smrg#ifdef HAVE_XORG_CONFIG_H 146747b715Smrg#include <xorg-config.h> 156747b715Smrg#endif 166747b715Smrg 176747b715Smrg#include "misc.h" 186747b715Smrg#include "xf86.h" 196747b715Smrg#include "xf86_OSproc.h" 206747b715Smrg#include "xf86DDC.h" 216747b715Smrg#include <string.h> 226747b715Smrg 236747b715Smrg#define RETRIES 4 246747b715Smrg 256747b715Smrgtypedef enum { 266747b715Smrg DDCOPT_NODDC1, 276747b715Smrg DDCOPT_NODDC2, 286747b715Smrg DDCOPT_NODDC 296747b715Smrg} DDCOpts; 306747b715Smrg 316747b715Smrgstatic const OptionInfoRec DDCOptions[] = { 3235c4bbdfSmrg {DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE}, 3335c4bbdfSmrg {DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE}, 3435c4bbdfSmrg {DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, 3535c4bbdfSmrg {-1, NULL, OPTV_NONE, {0}, FALSE}, 366747b715Smrg}; 376747b715Smrg 386747b715Smrg/* DDC1 */ 396747b715Smrg 406747b715Smrgstatic int 416747b715Smrgfind_start(unsigned int *ptr) 426747b715Smrg{ 436747b715Smrg unsigned int comp[9], test[9]; 4435c4bbdfSmrg int i, j; 4535c4bbdfSmrg 4635c4bbdfSmrg for (i = 0; i < 9; i++) { 4735c4bbdfSmrg comp[i] = *(ptr++); 4835c4bbdfSmrg test[i] = 1; 496747b715Smrg } 5035c4bbdfSmrg for (i = 0; i < 127; i++) { 5135c4bbdfSmrg for (j = 0; j < 9; j++) { 5235c4bbdfSmrg test[j] = test[j] & !(comp[j] ^ *(ptr++)); 5335c4bbdfSmrg } 546747b715Smrg } 5535c4bbdfSmrg for (i = 0; i < 9; i++) 5635c4bbdfSmrg if (test[i]) 5735c4bbdfSmrg return i + 1; 586747b715Smrg return -1; 596747b715Smrg} 606747b715Smrg 616747b715Smrgstatic unsigned char * 626747b715Smrgfind_header(unsigned char *block) 636747b715Smrg{ 646747b715Smrg unsigned char *ptr, *head_ptr, *end; 6535c4bbdfSmrg unsigned char header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; 6635c4bbdfSmrg 676747b715Smrg ptr = block; 686747b715Smrg end = block + EDID1_LEN; 6935c4bbdfSmrg while (ptr < end) { 7035c4bbdfSmrg int i; 7135c4bbdfSmrg 7235c4bbdfSmrg head_ptr = ptr; 7335c4bbdfSmrg for (i = 0; i < 8; i++) { 7435c4bbdfSmrg if (header[i] != *(head_ptr++)) 7535c4bbdfSmrg break; 7635c4bbdfSmrg if (head_ptr == end) 7735c4bbdfSmrg head_ptr = block; 7835c4bbdfSmrg } 7935c4bbdfSmrg if (i == 8) 8035c4bbdfSmrg break; 8135c4bbdfSmrg ptr++; 826747b715Smrg } 8335c4bbdfSmrg if (ptr == end) 8435c4bbdfSmrg return NULL; 856747b715Smrg return ptr; 866747b715Smrg} 876747b715Smrg 886747b715Smrgstatic unsigned char * 896747b715Smrgresort(unsigned char *s_block) 906747b715Smrg{ 916747b715Smrg unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; 926747b715Smrg unsigned char tmp; 936747b715Smrg 9435c4bbdfSmrg s_ptr = find_header(s_block); 9535c4bbdfSmrg if (!s_ptr) 9635c4bbdfSmrg return NULL; 976747b715Smrg s_end = s_block + EDID1_LEN; 9835c4bbdfSmrg 996747b715Smrg d_new = malloc(EDID1_LEN); 10035c4bbdfSmrg if (!d_new) 10135c4bbdfSmrg return NULL; 1026747b715Smrg d_end = d_new + EDID1_LEN; 1036747b715Smrg 10435c4bbdfSmrg for (d_ptr = d_new; d_ptr < d_end; d_ptr++) { 10535c4bbdfSmrg tmp = *(s_ptr++); 10635c4bbdfSmrg *d_ptr = tmp; 10735c4bbdfSmrg if (s_ptr == s_end) 10835c4bbdfSmrg s_ptr = s_block; 1096747b715Smrg } 1106747b715Smrg free(s_block); 1116747b715Smrg return d_new; 1126747b715Smrg} 1136747b715Smrg 1146747b715Smrgstatic int 1156747b715SmrgDDC_checksum(const unsigned char *block, int len) 1166747b715Smrg{ 1176747b715Smrg int i, result = 0; 1186747b715Smrg int not_null = 0; 11935c4bbdfSmrg 12035c4bbdfSmrg for (i = 0; i < len; i++) { 12135c4bbdfSmrg not_null |= block[i]; 12235c4bbdfSmrg result += block[i]; 1236747b715Smrg } 12435c4bbdfSmrg 1256747b715Smrg#ifdef DEBUG 12635c4bbdfSmrg if (result & 0xFF) 12735c4bbdfSmrg ErrorF("DDC checksum not correct\n"); 12835c4bbdfSmrg if (!not_null) 12935c4bbdfSmrg ErrorF("DDC read all Null\n"); 1306747b715Smrg#endif 1316747b715Smrg 1326747b715Smrg /* catch the trivial case where all bytes are 0 */ 13335c4bbdfSmrg if (!not_null) 13435c4bbdfSmrg return 1; 1356747b715Smrg 13635c4bbdfSmrg return result & 0xFF; 1376747b715Smrg} 1386747b715Smrg 1396747b715Smrgstatic unsigned char * 1406747b715SmrgGetEDID_DDC1(unsigned int *s_ptr) 1416747b715Smrg{ 1426747b715Smrg unsigned char *d_block, *d_pos; 1436747b715Smrg unsigned int *s_pos, *s_end; 1446747b715Smrg int s_start; 14535c4bbdfSmrg int i, j; 14635c4bbdfSmrg 1476747b715Smrg s_start = find_start(s_ptr); 14835c4bbdfSmrg if (s_start == -1) 14935c4bbdfSmrg return NULL; 1506747b715Smrg s_end = s_ptr + NUM; 1516747b715Smrg s_pos = s_ptr + s_start; 1521b5d61b8Smrg d_block = calloc(1, EDID1_LEN); 15335c4bbdfSmrg if (!d_block) 15435c4bbdfSmrg return NULL; 1556747b715Smrg d_pos = d_block; 15635c4bbdfSmrg for (i = 0; i < EDID1_LEN; i++) { 15735c4bbdfSmrg for (j = 0; j < 8; j++) { 15835c4bbdfSmrg *d_pos <<= 1; 15935c4bbdfSmrg if (*s_pos) { 16035c4bbdfSmrg *d_pos |= 0x01; 16135c4bbdfSmrg } 16235c4bbdfSmrg s_pos++; 16335c4bbdfSmrg if (s_pos == s_end) 16435c4bbdfSmrg s_pos = s_ptr; 16535c4bbdfSmrg }; 16635c4bbdfSmrg s_pos++; 16735c4bbdfSmrg if (s_pos == s_end) 16835c4bbdfSmrg s_pos = s_ptr; 16935c4bbdfSmrg d_pos++; 1706747b715Smrg } 1716747b715Smrg free(s_ptr); 17235c4bbdfSmrg if (d_block && DDC_checksum(d_block, EDID1_LEN)) { 17335c4bbdfSmrg free(d_block); 17435c4bbdfSmrg return NULL; 1756747b715Smrg } 1766747b715Smrg return (resort(d_block)); 1776747b715Smrg} 1786747b715Smrg 1796747b715Smrg/* fetch entire EDID record; DDC bit needs to be masked */ 18035c4bbdfSmrgstatic unsigned int * 1816747b715SmrgFetchEDID_DDC1(register ScrnInfoPtr pScrn, 18235c4bbdfSmrg register unsigned int (*read_DDC) (ScrnInfoPtr)) 1836747b715Smrg{ 1846747b715Smrg int count = NUM; 1856747b715Smrg unsigned int *ptr, *xp; 1866747b715Smrg 18735c4bbdfSmrg ptr = xp = malloc(sizeof(int) * NUM); 1886747b715Smrg 18935c4bbdfSmrg if (!ptr) 19035c4bbdfSmrg return NULL; 1916747b715Smrg do { 19235c4bbdfSmrg /* wait for next retrace */ 19335c4bbdfSmrg *xp = read_DDC(pScrn); 19435c4bbdfSmrg xp++; 19535c4bbdfSmrg } while (--count); 1966747b715Smrg return ptr; 1976747b715Smrg} 1986747b715Smrg 1996747b715Smrg/* test if DDC1 return 0 if not */ 2006747b715Smrgstatic Bool 20135c4bbdfSmrgTestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC) (ScrnInfoPtr)) 2026747b715Smrg{ 2036747b715Smrg int old, count; 2046747b715Smrg 2056747b715Smrg old = read_DDC(pScrn); 2066747b715Smrg count = HEADER * BITS_PER_BYTE; 2076747b715Smrg do { 20835c4bbdfSmrg /* wait for next retrace */ 20935c4bbdfSmrg if (old != read_DDC(pScrn)) 21035c4bbdfSmrg break; 21135c4bbdfSmrg } while (count--); 2126747b715Smrg return count; 2136747b715Smrg} 2146747b715Smrg 21535c4bbdfSmrg/* 2166747b715Smrg * read EDID record , pass it to callback function to interpret. 2176747b715Smrg * callback function will store it for further use by calling 21835c4bbdfSmrg * function; it will also decide if we need to reread it 2196747b715Smrg */ 2206747b715Smrgstatic unsigned char * 22135c4bbdfSmrgEDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, 22235c4bbdfSmrg unsigned int (*read_DDC) (ScrnInfoPtr)) 2236747b715Smrg{ 2246747b715Smrg unsigned char *EDID_block = NULL; 2256747b715Smrg int count = RETRIES; 2266747b715Smrg 22735c4bbdfSmrg if (!read_DDC) { 22835c4bbdfSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 22935c4bbdfSmrg "chipset doesn't support DDC1\n"); 23035c4bbdfSmrg return NULL; 2316747b715Smrg }; 2326747b715Smrg 23335c4bbdfSmrg if (TestDDC1(pScrn, read_DDC) == -1) { 23435c4bbdfSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); 23535c4bbdfSmrg return NULL; 2366747b715Smrg }; 2376747b715Smrg 23835c4bbdfSmrg if (DDCSpeed) 23935c4bbdfSmrg DDCSpeed(pScrn, DDC_FAST); 2406747b715Smrg do { 24135c4bbdfSmrg EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn, read_DDC)); 24235c4bbdfSmrg count--; 2436747b715Smrg } while (!EDID_block && count); 24435c4bbdfSmrg if (DDCSpeed) 24535c4bbdfSmrg DDCSpeed(pScrn, DDC_SLOW); 2466747b715Smrg 2476747b715Smrg return EDID_block; 2486747b715Smrg} 2496747b715Smrg 2506747b715Smrg/** 2516747b715Smrg * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are 2526747b715Smrg * unset. EDID information blocks are interpreted and the results returned in 2536747b715Smrg * an xf86MonPtr. 2546747b715Smrg * 2556747b715Smrg * This function does not affect the list of modes used by drivers -- it is up 2566747b715Smrg * to the driver to decide policy on what to do with EDID information. 2576747b715Smrg * 2586747b715Smrg * @return pointer to a new xf86MonPtr containing the EDID information. 2596747b715Smrg * @return NULL if no monitor attached or failure to interpret the EDID. 2606747b715Smrg */ 2616747b715Smrgxf86MonPtr 26235c4bbdfSmrgxf86DoEDID_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDC1SetSpeed, 26335c4bbdfSmrg unsigned int (*DDC1Read) (ScrnInfoPtr)) 2646747b715Smrg{ 2656747b715Smrg unsigned char *EDID_block = NULL; 2666747b715Smrg xf86MonPtr tmp = NULL; 26735c4bbdfSmrg 2686747b715Smrg /* Default DDC and DDC1 to enabled. */ 2696747b715Smrg Bool noddc = FALSE, noddc1 = FALSE; 2706747b715Smrg OptionInfoPtr options; 2716747b715Smrg 2726747b715Smrg options = xnfalloc(sizeof(DDCOptions)); 27335c4bbdfSmrg (void) memcpy(options, DDCOptions, sizeof(DDCOptions)); 2746747b715Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 2756747b715Smrg 2766747b715Smrg xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 2776747b715Smrg xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); 2786747b715Smrg free(options); 27935c4bbdfSmrg 2806747b715Smrg if (noddc || noddc1) 28135c4bbdfSmrg return NULL; 28235c4bbdfSmrg 2839ace9065Smrg OsBlockSignals(); 28435c4bbdfSmrg EDID_block = EDIDRead_DDC1(pScrn, DDC1SetSpeed, DDC1Read); 2859ace9065Smrg OsReleaseSignals(); 2866747b715Smrg 28735c4bbdfSmrg if (EDID_block) { 28835c4bbdfSmrg tmp = xf86InterpretEDID(pScrn->scrnIndex, EDID_block); 2896747b715Smrg } 2906747b715Smrg#ifdef DEBUG 29135c4bbdfSmrg else 29235c4bbdfSmrg ErrorF("No EDID block returned\n"); 2936747b715Smrg if (!tmp) 29435c4bbdfSmrg ErrorF("Cannot interpret EDID block\n"); 2956747b715Smrg#endif 29635c4bbdfSmrg return tmp; 2976747b715Smrg} 2986747b715Smrg 2996747b715Smrg/* DDC2 */ 3006747b715Smrg 3016747b715Smrgstatic I2CDevPtr 30235c4bbdfSmrgDDC2MakeDevice(I2CBusPtr pBus, int address, const char *name) 3036747b715Smrg{ 3046747b715Smrg I2CDevPtr dev = NULL; 3056747b715Smrg 3066747b715Smrg if (!(dev = xf86I2CFindDev(pBus, address))) { 30735c4bbdfSmrg dev = xf86CreateI2CDevRec(); 30835c4bbdfSmrg dev->DevName = name; 30935c4bbdfSmrg dev->SlaveAddr = address; 31035c4bbdfSmrg dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ 31135c4bbdfSmrg dev->StartTimeout = 550; 31235c4bbdfSmrg dev->BitTimeout = 40; 31335c4bbdfSmrg dev->AcknTimeout = 40; 31435c4bbdfSmrg 31535c4bbdfSmrg dev->pI2CBus = pBus; 31635c4bbdfSmrg if (!xf86I2CDevInit(dev)) { 31735c4bbdfSmrg xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); 31835c4bbdfSmrg return NULL; 31935c4bbdfSmrg } 3206747b715Smrg } 3216747b715Smrg 3226747b715Smrg return dev; 3236747b715Smrg} 3246747b715Smrg 3256747b715Smrgstatic I2CDevPtr 32635c4bbdfSmrgDDC2Init(I2CBusPtr pBus) 3276747b715Smrg{ 3286747b715Smrg I2CDevPtr dev = NULL; 3296747b715Smrg 3306747b715Smrg /* 33135c4bbdfSmrg * Slow down the bus so that older monitors don't 3326747b715Smrg * miss things. 3336747b715Smrg */ 3346747b715Smrg pBus->RiseFallTime = 20; 33535c4bbdfSmrg 3366747b715Smrg dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); 3376747b715Smrg if (xf86I2CProbeAddress(pBus, 0x0060)) 33835c4bbdfSmrg DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); 3396747b715Smrg 3406747b715Smrg return dev; 3416747b715Smrg} 3426747b715Smrg 3436747b715Smrg/* Mmmm, smell the hacks */ 3446747b715Smrgstatic void 3456747b715SmrgEEDIDStop(I2CDevPtr d) 3466747b715Smrg{ 3476747b715Smrg} 3486747b715Smrg 3496747b715Smrg/* block is the EDID block number. a segment is two blocks. */ 3506747b715Smrgstatic Bool 3516747b715SmrgDDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) 3526747b715Smrg{ 3536747b715Smrg unsigned char W_Buffer[1]; 3546747b715Smrg int i, segment; 3556747b715Smrg I2CDevPtr seg; 35635c4bbdfSmrg void (*stop) (I2CDevPtr); 3576747b715Smrg 3586747b715Smrg for (i = 0; i < RETRIES; i++) { 35935c4bbdfSmrg /* Stop bits reset the segment pointer to 0, so be careful here. */ 36035c4bbdfSmrg segment = block >> 1; 36135c4bbdfSmrg if (segment) { 36235c4bbdfSmrg Bool b; 36335c4bbdfSmrg 36435c4bbdfSmrg if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) 36535c4bbdfSmrg return FALSE; 36635c4bbdfSmrg 36735c4bbdfSmrg W_Buffer[0] = segment; 36835c4bbdfSmrg 36935c4bbdfSmrg stop = dev->pI2CBus->I2CStop; 37035c4bbdfSmrg dev->pI2CBus->I2CStop = EEDIDStop; 37135c4bbdfSmrg 37235c4bbdfSmrg b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); 37335c4bbdfSmrg 37435c4bbdfSmrg dev->pI2CBus->I2CStop = stop; 37535c4bbdfSmrg if (!b) { 37635c4bbdfSmrg dev->pI2CBus->I2CStop(dev); 37735c4bbdfSmrg continue; 37835c4bbdfSmrg } 37935c4bbdfSmrg } 38035c4bbdfSmrg 38135c4bbdfSmrg W_Buffer[0] = (block & 0x01) * EDID1_LEN; 38235c4bbdfSmrg 38335c4bbdfSmrg if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { 38435c4bbdfSmrg if (!DDC_checksum(R_Buffer, EDID1_LEN)) 38535c4bbdfSmrg return TRUE; 38635c4bbdfSmrg } 3876747b715Smrg } 38835c4bbdfSmrg 3896747b715Smrg return FALSE; 3906747b715Smrg} 3916747b715Smrg 3926747b715Smrg/** 3936747b715Smrg * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 3946747b715Smrg * unset. EDID information blocks are interpreted and the results returned in 3956747b715Smrg * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return 3966747b715Smrg * the complete EDID data, including all extension blocks, if the 'complete' 3976747b715Smrg * parameter is TRUE; 3986747b715Smrg * 3996747b715Smrg * This function does not affect the list of modes used by drivers -- it is up 4006747b715Smrg * to the driver to decide policy on what to do with EDID information. 4016747b715Smrg * 4026747b715Smrg * @return pointer to a new xf86MonPtr containing the EDID information. 4036747b715Smrg * @return NULL if no monitor attached or failure to interpret the EDID. 4046747b715Smrg */ 4056747b715Smrgxf86MonPtr 40635c4bbdfSmrgxf86DoEEDID(ScrnInfoPtr pScrn, I2CBusPtr pBus, Bool complete) 4076747b715Smrg{ 4086747b715Smrg unsigned char *EDID_block = NULL; 4096747b715Smrg xf86MonPtr tmp = NULL; 4106747b715Smrg I2CDevPtr dev = NULL; 41135c4bbdfSmrg 4126747b715Smrg /* Default DDC and DDC2 to enabled. */ 4136747b715Smrg Bool noddc = FALSE, noddc2 = FALSE; 4146747b715Smrg OptionInfoPtr options; 4156747b715Smrg 4166747b715Smrg options = malloc(sizeof(DDCOptions)); 4176747b715Smrg if (!options) 41835c4bbdfSmrg return NULL; 4196747b715Smrg memcpy(options, DDCOptions, sizeof(DDCOptions)); 4206747b715Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 4216747b715Smrg 4226747b715Smrg xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); 4236747b715Smrg xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); 4246747b715Smrg free(options); 4256747b715Smrg 4266747b715Smrg if (noddc || noddc2) 42735c4bbdfSmrg return NULL; 4286747b715Smrg 42935c4bbdfSmrg if (!(dev = DDC2Init(pBus))) 43035c4bbdfSmrg return NULL; 4316747b715Smrg 4326747b715Smrg EDID_block = calloc(1, EDID1_LEN); 4336747b715Smrg if (!EDID_block) 43435c4bbdfSmrg return NULL; 4356747b715Smrg 4366747b715Smrg if (DDC2Read(dev, 0, EDID_block)) { 43735c4bbdfSmrg int i, n = EDID_block[0x7e]; 4386747b715Smrg 43935c4bbdfSmrg if (complete && n) { 44035c4bbdfSmrg EDID_block = reallocarray(EDID_block, 1 + n, EDID1_LEN); 4416747b715Smrg 44235c4bbdfSmrg for (i = 0; i < n; i++) 44335c4bbdfSmrg DDC2Read(dev, i + 1, EDID_block + (EDID1_LEN * (1 + i))); 44435c4bbdfSmrg } 4456747b715Smrg 44635c4bbdfSmrg tmp = xf86InterpretEEDID(pScrn->scrnIndex, EDID_block); 4476747b715Smrg } 4486747b715Smrg 4496747b715Smrg if (tmp && complete) 45035c4bbdfSmrg tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 4516747b715Smrg 4526747b715Smrg return tmp; 4536747b715Smrg} 4546747b715Smrg 4556747b715Smrg/** 4566747b715Smrg * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are 4576747b715Smrg * unset. EDID information blocks are interpreted and the results returned in 4586747b715Smrg * an xf86MonPtr. 4596747b715Smrg * 4606747b715Smrg * This function does not affect the list of modes used by drivers -- it is up 4616747b715Smrg * to the driver to decide policy on what to do with EDID information. 4626747b715Smrg * 4636747b715Smrg * @return pointer to a new xf86MonPtr containing the EDID information. 4646747b715Smrg * @return NULL if no monitor attached or failure to interpret the EDID. 4656747b715Smrg */ 4666747b715Smrgxf86MonPtr 46735c4bbdfSmrgxf86DoEDID_DDC2(ScrnInfoPtr pScrn, I2CBusPtr pBus) 4686747b715Smrg{ 46935c4bbdfSmrg return xf86DoEEDID(pScrn, pBus, FALSE); 4706747b715Smrg} 471