From 0b36f68efb1171fcdbe53e93064394f5609b7fb5 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 8 Jun 2009 15:36:15 -0400 Subject: ddc: mv xf86DDC.c ddc.c --- hw/xfree86/ddc/Makefile.am | 2 +- hw/xfree86/ddc/ddc.c | 449 +++++++++++++++++++++++++++++++++++++++++++++ hw/xfree86/ddc/xf86DDC.c | 449 --------------------------------------------- 3 files changed, 450 insertions(+), 450 deletions(-) create mode 100644 hw/xfree86/ddc/ddc.c delete mode 100644 hw/xfree86/ddc/xf86DDC.c diff --git a/hw/xfree86/ddc/Makefile.am b/hw/xfree86/ddc/Makefile.am index 8ffe43377..93ea4a2a5 100644 --- a/hw/xfree86/ddc/Makefile.am +++ b/hw/xfree86/ddc/Makefile.am @@ -2,7 +2,7 @@ sdk_HEADERS = edid.h xf86DDC.h noinst_LTLIBRARIES = libddc.la -libddc_la_SOURCES = xf86DDC.c interpret_edid.c print_edid.c ddcProperty.c +libddc_la_SOURCES = ddc.c interpret_edid.c print_edid.c ddcProperty.c INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c diff --git a/hw/xfree86/ddc/ddc.c b/hw/xfree86/ddc/ddc.c new file mode 100644 index 000000000..33b77fc52 --- /dev/null +++ b/hw/xfree86/ddc/ddc.c @@ -0,0 +1,449 @@ +/* xf86DDC.c + * + * Copyright 1998,1999 by Egbert Eich + */ + +/* + * A note on terminology. DDC1 is the original dumb serial protocol, and + * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and + * introduces extension blocks. EDID is the old display identification + * block, DisplayID is the new one. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" +#include + +#define RETRIES 4 + +typedef enum { + DDCOPT_NODDC1, + DDCOPT_NODDC2, + DDCOPT_NODDC +} DDCOpts; + +static const OptionInfoRec DDCOptions[] = { + { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, + { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, + { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +/* DDC1 */ + +static int +find_start(unsigned int *ptr) +{ + unsigned int comp[9], test[9]; + int i,j; + + for (i=0;i<9;i++){ + comp[i] = *(ptr++); + test[i] = 1; + } + for (i=0;i<127;i++){ + for (j=0;j<9;j++){ + test[j] = test[j] & !(comp[j] ^ *(ptr++)); + } + } + for (i=0;i<9;i++) + if (test[i]) return (i+1); + return (-1); +} + +static unsigned char * +find_header(unsigned char *block) +{ + unsigned char *ptr, *head_ptr, *end; + unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + + ptr = block; + end = block + EDID1_LEN; + while (ptrscrnIndex, X_PROBED, + "chipset doesn't support DDC1\n"); + return NULL; + }; + + if (TestDDC1(pScrn,read_DDC)==-1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); + return NULL; + }; + + if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); + do { + EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); + count --; + } while (!EDID_block && count); + if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); + + return EDID_block; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEDID_DDC1( + int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, + unsigned int (*DDC1Read)(ScrnInfoPtr) +) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + xf86MonPtr tmp = NULL; + int sigio; + /* Default DDC and DDC1 to enabled. */ + Bool noddc = FALSE, noddc1 = FALSE; + OptionInfoPtr options; + + options = xnfalloc(sizeof(DDCOptions)); + (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); + xfree(options); + + if (noddc || noddc1) + return NULL; + + sigio = xf86BlockSIGIO(); + EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); + xf86UnblockSIGIO(sigio); + + if (EDID_block){ + tmp = xf86InterpretEDID(scrnIndex,EDID_block); + } +#ifdef DEBUG + else ErrorF("No EDID block returned\n"); + if (!tmp) + ErrorF("Cannot interpret EDID block\n"); +#endif + return tmp; +} + +/* DDC2 */ + +static I2CDevPtr +DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) +{ + I2CDevPtr dev = NULL; + + if (!(dev = xf86I2CFindDev(pBus, address))) { + dev = xf86CreateI2CDevRec(); + dev->DevName = name; + dev->SlaveAddr = address; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->AcknTimeout = 40; + + dev->pI2CBus = pBus; + if (!xf86I2CDevInit(dev)) { + xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); + return NULL; + } + } + + return dev; +} + +static I2CDevPtr +DDC2Init(int scrnIndex, I2CBusPtr pBus) +{ + I2CDevPtr dev = NULL; + + /* + * Slow down the bus so that older monitors don't + * miss things. + */ + pBus->RiseFallTime = 20; + + dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); + if (xf86I2CProbeAddress(pBus, 0x0060)) + DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); + if (xf86I2CProbeAddress(pBus, 0x0062)) + DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface"); + if (xf86I2CProbeAddress(pBus, 0x006E)) + DDC2MakeDevice(pBus, 0x006E, "DDC control interface"); + + return dev; +} + +/* Mmmm, smell the hacks */ +static void +EEDIDStop(I2CDevPtr d) +{ +} + +/* block is the EDID block number. a segment is two blocks. */ +static Bool +DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) +{ + unsigned char W_Buffer[1]; + int i, segment; + I2CDevPtr seg; + void (*stop)(I2CDevPtr); + + for (i = 0; i < RETRIES; i++) { + /* Stop bits reset the segment pointer to 0, so be careful here. */ + segment = block >> 1; + if (segment) { + Bool b; + + if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) + return FALSE; + + W_Buffer[0] = segment; + + stop = dev->pI2CBus->I2CStop; + dev->pI2CBus->I2CStop = EEDIDStop; + + b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); + + dev->pI2CBus->I2CStop = stop; + if (!b) { + dev->pI2CBus->I2CStop(dev); + continue; + } + } + + W_Buffer[0] = (block & 0x01) * EDID1_LEN; + + if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { + if (!DDC_checksum(R_Buffer, EDID1_LEN)) + return TRUE; + } + } + + return FALSE; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return + * the complete EDID data, including all extension blocks, if the 'complete' + * parameter is TRUE; + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + xf86MonPtr tmp = NULL; + I2CDevPtr dev = NULL; + /* Default DDC and DDC2 to enabled. */ + Bool noddc = FALSE, noddc2 = FALSE; + OptionInfoPtr options; + + options = xalloc(sizeof(DDCOptions)); + if (!options) + return NULL; + memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); + xfree(options); + + if (noddc || noddc2) + return NULL; + + if (!(dev = DDC2Init(scrnIndex, pBus))) + return NULL; + + EDID_block = xcalloc(1, EDID1_LEN); + if (!EDID_block) + return NULL; + + if (DDC2Read(dev, 0, EDID_block)) { + int i, n = EDID_block[0x7e]; + + if (complete && n) { + EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n)); + + for (i = 0; i < n; i++) + DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); + } + + tmp = xf86InterpretEEDID(scrnIndex, EDID_block); + } + + if (tmp && complete) + tmp->flags |= EDID_COMPLETE_RAWDATA; + + return tmp; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) +{ + return xf86DoEEDID(scrnIndex, pBus, FALSE); +} diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c deleted file mode 100644 index 33b77fc52..000000000 --- a/hw/xfree86/ddc/xf86DDC.c +++ /dev/null @@ -1,449 +0,0 @@ -/* xf86DDC.c - * - * Copyright 1998,1999 by Egbert Eich - */ - -/* - * A note on terminology. DDC1 is the original dumb serial protocol, and - * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and - * introduces extension blocks. EDID is the old display identification - * block, DisplayID is the new one. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86DDC.h" -#include - -#define RETRIES 4 - -typedef enum { - DDCOPT_NODDC1, - DDCOPT_NODDC2, - DDCOPT_NODDC -} DDCOpts; - -static const OptionInfoRec DDCOptions[] = { - { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -/* DDC1 */ - -static int -find_start(unsigned int *ptr) -{ - unsigned int comp[9], test[9]; - int i,j; - - for (i=0;i<9;i++){ - comp[i] = *(ptr++); - test[i] = 1; - } - for (i=0;i<127;i++){ - for (j=0;j<9;j++){ - test[j] = test[j] & !(comp[j] ^ *(ptr++)); - } - } - for (i=0;i<9;i++) - if (test[i]) return (i+1); - return (-1); -} - -static unsigned char * -find_header(unsigned char *block) -{ - unsigned char *ptr, *head_ptr, *end; - unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; - - ptr = block; - end = block + EDID1_LEN; - while (ptrscrnIndex, X_PROBED, - "chipset doesn't support DDC1\n"); - return NULL; - }; - - if (TestDDC1(pScrn,read_DDC)==-1) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); - return NULL; - }; - - if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); - do { - EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); - count --; - } while (!EDID_block && count); - if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); - - return EDID_block; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEDID_DDC1( - int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, - unsigned int (*DDC1Read)(ScrnInfoPtr) -) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - unsigned char *EDID_block = NULL; - xf86MonPtr tmp = NULL; - int sigio; - /* Default DDC and DDC1 to enabled. */ - Bool noddc = FALSE, noddc1 = FALSE; - OptionInfoPtr options; - - options = xnfalloc(sizeof(DDCOptions)); - (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); - xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); - xfree(options); - - if (noddc || noddc1) - return NULL; - - sigio = xf86BlockSIGIO(); - EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); - xf86UnblockSIGIO(sigio); - - if (EDID_block){ - tmp = xf86InterpretEDID(scrnIndex,EDID_block); - } -#ifdef DEBUG - else ErrorF("No EDID block returned\n"); - if (!tmp) - ErrorF("Cannot interpret EDID block\n"); -#endif - return tmp; -} - -/* DDC2 */ - -static I2CDevPtr -DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) -{ - I2CDevPtr dev = NULL; - - if (!(dev = xf86I2CFindDev(pBus, address))) { - dev = xf86CreateI2CDevRec(); - dev->DevName = name; - dev->SlaveAddr = address; - dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ - dev->StartTimeout = 550; - dev->BitTimeout = 40; - dev->AcknTimeout = 40; - - dev->pI2CBus = pBus; - if (!xf86I2CDevInit(dev)) { - xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); - return NULL; - } - } - - return dev; -} - -static I2CDevPtr -DDC2Init(int scrnIndex, I2CBusPtr pBus) -{ - I2CDevPtr dev = NULL; - - /* - * Slow down the bus so that older monitors don't - * miss things. - */ - pBus->RiseFallTime = 20; - - dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); - if (xf86I2CProbeAddress(pBus, 0x0060)) - DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); - if (xf86I2CProbeAddress(pBus, 0x0062)) - DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface"); - if (xf86I2CProbeAddress(pBus, 0x006E)) - DDC2MakeDevice(pBus, 0x006E, "DDC control interface"); - - return dev; -} - -/* Mmmm, smell the hacks */ -static void -EEDIDStop(I2CDevPtr d) -{ -} - -/* block is the EDID block number. a segment is two blocks. */ -static Bool -DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) -{ - unsigned char W_Buffer[1]; - int i, segment; - I2CDevPtr seg; - void (*stop)(I2CDevPtr); - - for (i = 0; i < RETRIES; i++) { - /* Stop bits reset the segment pointer to 0, so be careful here. */ - segment = block >> 1; - if (segment) { - Bool b; - - if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) - return FALSE; - - W_Buffer[0] = segment; - - stop = dev->pI2CBus->I2CStop; - dev->pI2CBus->I2CStop = EEDIDStop; - - b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); - - dev->pI2CBus->I2CStop = stop; - if (!b) { - dev->pI2CBus->I2CStop(dev); - continue; - } - } - - W_Buffer[0] = (block & 0x01) * EDID1_LEN; - - if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { - if (!DDC_checksum(R_Buffer, EDID1_LEN)) - return TRUE; - } - } - - return FALSE; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return - * the complete EDID data, including all extension blocks, if the 'complete' - * parameter is TRUE; - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - unsigned char *EDID_block = NULL; - xf86MonPtr tmp = NULL; - I2CDevPtr dev = NULL; - /* Default DDC and DDC2 to enabled. */ - Bool noddc = FALSE, noddc2 = FALSE; - OptionInfoPtr options; - - options = xalloc(sizeof(DDCOptions)); - if (!options) - return NULL; - memcpy(options, DDCOptions, sizeof(DDCOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); - xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); - xfree(options); - - if (noddc || noddc2) - return NULL; - - if (!(dev = DDC2Init(scrnIndex, pBus))) - return NULL; - - EDID_block = xcalloc(1, EDID1_LEN); - if (!EDID_block) - return NULL; - - if (DDC2Read(dev, 0, EDID_block)) { - int i, n = EDID_block[0x7e]; - - if (complete && n) { - EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n)); - - for (i = 0; i < n; i++) - DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); - } - - tmp = xf86InterpretEEDID(scrnIndex, EDID_block); - } - - if (tmp && complete) - tmp->flags |= EDID_COMPLETE_RAWDATA; - - return tmp; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) -{ - return xf86DoEEDID(scrnIndex, pBus, FALSE); -} -- cgit v1.2.3