summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-13 10:26:53 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-13 10:26:53 -0800
commitaedec718b1d6e9487861528dfb310db0b3a53c89 (patch)
tree15406822148df7b1f2dbdc1cd3a120f3fe6a0e42
parent6d20700cde575d515a14a043f8ffe76171ed5355 (diff)
-rw-r--r--XF86Config-parser/Generate.c2
-rw-r--r--XF86Config-parser/Monitor.c11
-rw-r--r--extract_edids.c410
-rw-r--r--make_usable.c43
-rw-r--r--nvidia-xconfig.c96
-rw-r--r--nvidia-xconfig.h8
-rw-r--r--option_table.h14
-rw-r--r--options.c140
8 files changed, 640 insertions, 84 deletions
diff --git a/XF86Config-parser/Generate.c b/XF86Config-parser/Generate.c
index d61771a..3d2da41 100644
--- a/XF86Config-parser/Generate.c
+++ b/XF86Config-parser/Generate.c
@@ -405,6 +405,8 @@ static void add_modules(GenerateOptions *gop, XConfigPtr config)
XCONFIG_LOAD_MODULE, NULL, FALSE);
l = xconfigAddNewLoadDirective(l, xconfigStrdup("bitstream"),
XCONFIG_LOAD_MODULE, NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("xtsol"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
#else
l = xconfigAddNewLoadDirective(l, xconfigStrdup("freetype"),
XCONFIG_LOAD_MODULE, NULL, FALSE);
diff --git a/XF86Config-parser/Monitor.c b/XF86Config-parser/Monitor.c
index 8c273c4..cacc284 100644
--- a/XF86Config-parser/Monitor.c
+++ b/XF86Config-parser/Monitor.c
@@ -668,9 +668,14 @@ xconfigPrintMonitorSection (FILE * cf, XConfigMonitorPtr ptr)
}
for (i = 0; i < ptr->n_vrefresh; i++)
{
- fprintf (cf, " VertRefresh %2.1f - %2.1f\n",
- ptr->vrefresh[i].lo,
- ptr->vrefresh[i].hi);
+ if (ptr->vrefresh[i].lo == ptr->vrefresh[i].hi) {
+ fprintf (cf, " VertRefresh %2.1f\n",
+ ptr->vrefresh[i].lo);
+ } else {
+ fprintf (cf, " VertRefresh %2.1f - %2.1f\n",
+ ptr->vrefresh[i].lo,
+ ptr->vrefresh[i].hi);
+ }
}
if (ptr->gamma_red) {
if (ptr->gamma_red == ptr->gamma_green
diff --git a/extract_edids.c b/extract_edids.c
index 9fc1603..25a4747 100644
--- a/extract_edids.c
+++ b/extract_edids.c
@@ -25,8 +25,8 @@
* extract-edids.c
*
* This source file gives us the means to extract EDIDs from verbose X
- * log files. A verbose log will contain a raw EDID byte dump like
- * this:
+ * log files or from .txt files. A verbose log will contain a raw EDID
+ * byte dump like this:
*
* (--) NVIDIA(0): Raw EDID bytes:
* (--) NVIDIA(0):
@@ -41,14 +41,27 @@
* (--) NVIDIA(0):
* (--) NVIDIA(0): --- End of EDID for ViewSonic VPD150 (DFP-1) ---
*
- * We read a log file, identify and read any EDID(s) contained in the
- * log file, and then write the EDID bytes to edid.bin files (just
+ * A .txt file will contain a raw EDID byte dump like this:
+ *
+ * 00 FF FF FF FF FF FF 00-06 10 F4 01 01 01 01 01 ................
+ * 27 08 01 01 28 1F 17 96-E8 44 E4 A1 57 4A 97 23 '...(....D..WJ.#
+ * 19 4F 57 BF EE 00 01 01-01 01 01 01 01 01 01 01 .OW.............
+ * 01 01 01 01 01 01 64 19-00 40 41 00 26 30 18 88 ......d..@A.&0..
+ * 36 00 33 E6 10 00 00 18-40 1F 00 30 41 00 24 30 6.3.....@..0A.$0
+ * 20 60 33 00 33 E6 10 00-00 18 00 00 00 FD 00 38 `3.3..........8
+ * 4C 1F 3D 08 00 0A 20 20-20 20 20 20 00 00 00 FC L.=... ....
+ * 00 41 70 70 6C 65 53 74-75 64 69 6F 0A 20 00 88 .AppleStudio. ..
+ *
+ * EDID Version : 1.1
+ *
+ * We read a log file or a .txt file, identify and read any EDID(s) contained
+ * in the file, and then write the EDID bytes to edid.bin files (just
* like what nvidia-settings can capture for display devices running
* on the current X server).
*
* This is useful for NVIDIA engineers to simulate users' display
- * environments, based on a verbose nvidia-bug-report.log or X log.
- * This utility is included in nvidia-xconfig, since maybe users will
+ * environments, based on a verbose nvidia-bug-report.log or X log or a .txt
+ * file. This utility is included in nvidia-xconfig, since maybe users will
* find use for this, too.
*/
@@ -84,6 +97,9 @@
#define EDID_OUTPUT_FILE_NAME "edid.bin"
+#define LOG_FILE 10
+#define TEXT_FILE 20
+#define UNKNOWN_FILE 30
typedef struct {
int size;
@@ -98,12 +114,18 @@ typedef struct {
} FileRec, *FilePtr;
+static int findFileType(FilePtr pFile);
+
+static EdidPtr findEdidforLogFile(FilePtr pFile);
+static EdidPtr findEdidforTextFile(FilePtr pFile);
-static EdidPtr findEdid(FilePtr pFile);
+static int findEdidHeaderforLogFile(FilePtr pFile);
+static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid);
+static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid);
-static int findEdidHeader(FilePtr pFile);
-static int readEdidData(FilePtr pFile, EdidPtr pEdid);
-static int readEdidFooter(FilePtr pFile, EdidPtr pEdid);
+static int findEdidfooterforTextFile(FilePtr pFile);
+static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid);
+static int readMonitorNameforTextFile(FilePtr pFile, EdidPtr pEdid);
static char *findFileName(char *option);
static int writeEdidFile(EdidPtr pEdid, char *filename);
@@ -118,27 +140,28 @@ static void freeEdid(EdidPtr pEdid);
int extract_edids(Options *op)
{
- int fd = -1, ret, funcRet = FALSE;
+ int fd = -1, ret, fileType, funcRet = FALSE;
char *filename;
struct stat stat_buf;
-
+
FileRec file;
EdidPtr pEdid, *pEdids;
int nEdids, i;
nEdids = 0;
+ pEdid = NULL;
pEdids = NULL;
memset(&file, 0, sizeof(FileRec));
file.start = (void *) -1;
/* open the file and get its length */
-
- fd = open(op->extract_edids_from_log, O_RDONLY);
-
+
+ fd = open(op->extract_edids_from_file, O_RDONLY);
+
if (fd == -1) {
- fmterr("Unable to open file \"%s\".", op->extract_edids_from_log);
+ fmterr("Unable to open file \"%s\".", op->extract_edids_from_file);
goto done;
}
@@ -146,14 +169,14 @@ int extract_edids(Options *op)
if (ret == -1) {
fmterr("Unable to get length of file \"%s\".",
- op->extract_edids_from_log);
+ op->extract_edids_from_file);
goto done;
}
file.length = stat_buf.st_size;
if (file.length == 0) {
- fmterr("File \"%s\" is empty.", op->extract_edids_from_log);
+ fmterr("File \"%s\" is empty.", op->extract_edids_from_file);
goto done;
}
@@ -163,26 +186,55 @@ int extract_edids(Options *op)
MAP_SHARED, fd, 0);
if (file.start == (void *) -1) {
- fmterr("Unable to map file \"%s\".", op->extract_edids_from_log);
+ fmterr("Unable to map file \"%s\".", op->extract_edids_from_file);
goto done;
}
/* start parsing at the start of file */
file.current = file.start;
+
+ /* check for the file type(log or .txt) */
- /* scan through the whole file, and build a list of pEdids */
+ fileType = findFileType(&file);
+
+ /* if the file does not contain any edid information, goto done */
+
+ if (fileType == UNKNOWN_FILE) {
+ funcRet = TRUE;
+ goto done;
+ }
+
+ if (fileType == LOG_FILE) {
+ file.current = file.start;
+ }
+ /* scan through the whole file, and build a list of pEdids */
+
while(1) {
+
+ if (fileType == LOG_FILE) {
+
+ pEdid = findEdidforLogFile(&file);
+
+ }
- pEdid = findEdid(&file);
-
+ if (fileType == TEXT_FILE) {
+
+ pEdid = findEdidforTextFile(&file);
+
+ }
+
if (!pEdid) break;
pEdids = nvrealloc(pEdids, sizeof(pEdids) * (nEdids + 1));
pEdids[nEdids] = pEdid;
nEdids++;
+
+ /* Only one edid in a .txt file */
+
+ if (fileType == TEXT_FILE) break;
}
/* fall through to the 'done' label */
@@ -211,7 +263,7 @@ int extract_edids(Options *op)
fmtout("");
fmtout("Found %d EDID%s in \"%s\".",
- nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_log);
+ nEdids, (nEdids == 1) ? "": "s", op->extract_edids_from_file);
filename = findFileName(op->extract_edids_output_file);
@@ -234,7 +286,20 @@ int extract_edids(Options *op)
} // extract_edids()
+/*
+ * findFileType() - scan through the pFile to determine the file type
+ * file type can be LOG_FILE, TEXT_FILE, UNKNOWN_FILE(file with no EDID)
+ */
+
+static int findFileType(FilePtr pFile)
+{
+ if (findEdidHeaderforLogFile(pFile)) return LOG_FILE;
+
+ if (findEdidfooterforTextFile(pFile)) return TEXT_FILE;
+ return UNKNOWN_FILE;
+
+} // findFileType()
/*
* findEdid() - scan through pFile for an EDID header, if we find one,
@@ -242,15 +307,15 @@ int extract_edids(Options *op)
* allocated pEdid data structure. On failure, return NULL.
*/
-static EdidPtr findEdid(FilePtr pFile)
+static EdidPtr findEdidforLogFile(FilePtr pFile)
{
EdidPtr pEdid = nvalloc(sizeof(EdidRec));
- if (!findEdidHeader(pFile)) goto fail;
+ if (!findEdidHeaderforLogFile(pFile)) goto fail;
- if (!readEdidData(pFile, pEdid)) goto fail;
+ if (!readEdidDataforLogFile(pFile, pEdid)) goto fail;
- if (!readEdidFooter(pFile, pEdid)) goto fail;
+ if (!readEdidFooterforLogFile(pFile, pEdid)) goto fail;
return pEdid;
@@ -260,10 +325,28 @@ static EdidPtr findEdid(FilePtr pFile)
return NULL;
-} // findEdid()
+} // findEdidforLogFile()
+
+/*
+ * scan through the pFile for EDID data and Monitor name.
+ */
+
+static EdidPtr findEdidforTextFile(FilePtr pFile)
+{
+ EdidPtr pEdid = nvalloc(sizeof(EdidRec));
+
+ if (!readEdidDataforTextFile(pFile,pEdid)) goto fail;
+ if (!readMonitorNameforTextFile(pFile, pEdid)) goto fail;
+ return pEdid;
+ fail:
+ freeEdid(pEdid);
+
+ return NULL;
+
+} // findEdidforTextFile()
/*
@@ -274,7 +357,7 @@ static EdidPtr findEdid(FilePtr pFile)
* file, return FALSE.
*/
-static int findEdidHeader(FilePtr pFile)
+static int findEdidHeaderforLogFile(FilePtr pFile)
{
while (((pFile->current - pFile->start) + 15) <= pFile->length) {
@@ -302,7 +385,7 @@ static int findEdidHeader(FilePtr pFile)
return FALSE;
-} // findEdidHeader()
+} // findEdidHeaderforLogFile()
@@ -314,14 +397,14 @@ static int findEdidHeader(FilePtr pFile)
* and upper nibbles of each EDID byte, and to advance past the label,
* that looks something like "(--) NVIDIA(0):".
*/
-
+
#define STATE_LOOKING_FOR_TOP_NIBBLE 0
#define STATE_LOOKING_FOR_BOTTOM_NIBBLE 1
#define STATE_LOOKING_FOR_END_OF_LABEL 2
#define MAX_EDID_SIZE 4096
-static int readEdidData(FilePtr pFile, EdidPtr pEdid)
+static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid)
{
int state;
@@ -333,7 +416,7 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid)
/* clear the scratch EDID data */
bzero(pData, MAX_EDID_SIZE);
-
+
/*
* start the parsing state machine by looking for the upper nibble
* of the first byte in the EDID
@@ -468,9 +551,166 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid)
return FALSE;
-} // readEdidData()
+} // readEdidDataforLogFile()
+
+/*
+ * read EDID data for the .txt file; pFile->current gives the starting
+ * position of the EDID bytes, which is same as file starting position.
+ * We use a state machine to look for the lower and upper nibbles of each
+ * EDID byte, and to advance past the label.
+ */
+
+static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid)
+{
+ int state;
+
+ unsigned char pData[MAX_EDID_SIZE];
+ int k;
+
+ char c;
+
+ /* clear the scratch EDID data */
+
+ bzero(pData, MAX_EDID_SIZE);
+
+ /*
+ * start the parsing state machine by looking for the upper nibble
+ * of the first byte in the EDID
+ */
+
+ state = STATE_LOOKING_FOR_TOP_NIBBLE;
+ k = 0;
+
+ while(1) {
+
+ c = pFile->current[0];
+
+ switch (state) {
+
+ case STATE_LOOKING_FOR_TOP_NIBBLE:
+
+ /*
+ * if we found a hex value, treat it as upper nibble, then
+ * look for lower nibble
+ */
+
+ if (IS_HEX(c)) {
+ pData[k] |= ((HEX_TO_NIBBLE(c)) << 4);
+ state = STATE_LOOKING_FOR_BOTTOM_NIBBLE;
+ goto nextChar;
+ }
+
+ /* skip '-' and keep looking for top nibble */
+
+ if (c == '-') {
+ state = STATE_LOOKING_FOR_TOP_NIBBLE;
+ goto nextChar;
+ }
+
+ /*
+ * if two consecutive white space, change lebel.
+ * if one white space, skip it.
+ */
+
+ if (isspace(c)) {
+
+ if (isspace(pFile->current[1])) {
+ state = STATE_LOOKING_FOR_END_OF_LABEL;
+ goto nextChar;
+ } else {
+ state = STATE_LOOKING_FOR_TOP_NIBBLE;
+ goto nextChar;
+ }
+ }
+
+ goto fail; /* anything else is an error */
+
+ break;
+
+ case STATE_LOOKING_FOR_BOTTOM_NIBBLE:
+
+ /*
+ * if we found a hex value, treat it as the lower nibble,
+ * then look for the upper nibble of the next byte
+ */
+
+ if (IS_HEX(c)) {
+ pData[k] |= (HEX_TO_NIBBLE(c));
+ state = STATE_LOOKING_FOR_TOP_NIBBLE;
+ k++;
+ if (k >= MAX_EDID_SIZE) goto fail;
+ goto nextChar;
+ }
+
+ goto fail; /* anything else is an error */
+
+ break;
+
+ case STATE_LOOKING_FOR_END_OF_LABEL:
+
+ /* if we found two consecutive '\r\n', then the reding of EDID
+ * information is complete. if only one '\r\n', then change the
+ * state.
+ */
+
+ if (c == '\r' && pFile->current[1] == '\n') {
+
+ if (pFile->current[2] == '\r' && pFile->current[3] == '\n') {
+ goto done;
+ } else {
+ state = STATE_LOOKING_FOR_TOP_NIBBLE;
+ goto nextChar;
+ }
+ }
+
+ /* skip the white space */
+
+ if (isspace(c)) {
+
+ state = STATE_LOOKING_FOR_END_OF_LABEL;
+ goto nextChar;
+
+ }
+
+ break;
+
+ default:
+ goto fail;
+ break;
+ }
+
+ nextChar:
+
+ /*
+ * if we are at the end of the mapping without hitting our
+ * exit condition, fail
+ */
+
+ if ((pFile->current - pFile->start) >= pFile->length) goto fail;
+
+ pFile->current++;
+ } /* while(1) */
+
+ done:
+
+ /* we are done parsing the EDID, save what we have into pEdid */
+
+ if (k <= 0) goto fail;
+
+ pEdid->size = k;
+ pEdid->bytes = nvalloc(k);
+
+ memcpy(pEdid->bytes, pData, k);
+
+ return TRUE;
+
+ fail:
+
+ return FALSE;
+
+} // readEdidDataforTextFile()
/*
* readEdidFooter() - the EDID footer is in the form:
@@ -482,7 +722,7 @@ static int readEdidData(FilePtr pFile, EdidPtr pEdid)
* assigned and TRUE is returned. On failure, FALSE is returned.
*/
-static int readEdidFooter(FilePtr pFile, EdidPtr pEdid)
+static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid)
{
char *begin;
int len;
@@ -555,9 +795,107 @@ static int readEdidFooter(FilePtr pFile, EdidPtr pEdid)
return FALSE;
-} // readEdidFooter()
+} // readEdidFooterforLogFile()
+
+/*
+ * read Edid Footer i.e. "EDID Version".
+ * this information is used to check whether the .txt file contains
+ * any edid information or not
+ */
+
+static int findEdidfooterforTextFile(FilePtr pFile)
+{
+ pFile->current = pFile->start;
+ while (((pFile->current - pFile->start) + 12) <= pFile->length) {
+
+ if ((pFile->current[0] == 'E') &&
+ (pFile->current[1] == 'D') &&
+ (pFile->current[2] == 'I') &&
+ (pFile->current[3] == 'D') &&
+ (pFile->current[4] == ' ') &&
+ (pFile->current[5] == 'V') &&
+ (pFile->current[6] == 'e') &&
+ (pFile->current[7] == 'r') &&
+ (pFile->current[8] == 's') &&
+ (pFile->current[9] == 'i') &&
+ (pFile->current[10] == 'o') &&
+ (pFile->current[11] == 'n')) {
+
+ pFile->current = pFile->start;
+ return TRUE;
+ }
+ pFile->current++;
+ }
+
+return FALSE;
+
+} // findEdidfooterforTextFile()
+
+/* read the monitor information */
+
+static int readMonitorNameforTextFile(FilePtr pFile, EdidPtr pEdid)
+{
+ char *begin;
+ int len;
+
+ while (((pFile->current - pFile->start) + 12) <= pFile->length) {
+
+ if ((pFile->current[0] == 'M') &&
+ (pFile->current[1] == 'o') &&
+ (pFile->current[2] == 'n') &&
+ (pFile->current[3] == 'i') &&
+ (pFile->current[4] == 't') &&
+ (pFile->current[5] == 'o') &&
+ (pFile->current[6] == 'r') &&
+ (pFile->current[7] == ' ') &&
+ (pFile->current[8] == 'N') &&
+ (pFile->current[9] == 'a') &&
+ (pFile->current[10] == 'm') &&
+ (pFile->current[11] == 'e')) {
+
+ pFile->current += 12;
+ goto next;
+ }
+
+ pFile->current++;
+
+ }
+ return FALSE;
+
+ next:
+
+ /* search for start of the expected text */
+
+ while (pFile->current[0] != ':') pFile->current++;
+ pFile->current += 2;
+
+ begin = pFile->current;
+
+ /* search for the end of expected text */
+
+ while (((pFile->current - pFile->start) + 2) <= pFile->length) {
+
+ if ((pFile->current[0] == '\r') && (pFile->current[1] == '\n')) {
+
+ len = pFile->current - begin;
+
+ if ((len > 512) || (len < 1)) {
+ return FALSE;
+ }
+
+ pEdid->name = nvalloc(len + 1);
+
+ strncpy(pEdid->name, begin, len);
+ pEdid->name[len] = '\0';
+
+ return TRUE;
+ }
+ pFile->current++;
+ }
+ return FALSE;
+} // readMonitorNameforTextFile()
/*
* findFileName() - determine the filename to use for writing out the
diff --git a/make_usable.c b/make_usable.c
index 920a7dc..74c4ca2 100644
--- a/make_usable.c
+++ b/make_usable.c
@@ -35,10 +35,30 @@
#include "configProcs.h"
+static void ensure_module_loaded(XConfigPtr config, char *name);
static int update_device(XConfigPtr config, XConfigDevicePtr device);
static void update_depth(Options *op, XConfigScreenPtr screen);
static void update_display(Options *op, XConfigScreenPtr screen);
+/*
+ * ensure_module_loaded() - make sure the given module is present
+ */
+
+static void ensure_module_loaded(XConfigPtr config, char *name) {
+ XConfigLoadPtr load;
+ int found = FALSE;
+
+ for (load = config->modules->loads; load && !found; load = load->next) {
+ if (xconfigNameCompare(name, load->name) == 0) found = TRUE;
+ }
+
+ if (!found) {
+ config->modules->loads =
+ xconfigAddNewLoadDirective(config->modules->loads,
+ name, XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ }
+} /* ensure_module_loaded */
/*
* update_modules() - make sure the glx module is present, and remove
@@ -48,25 +68,16 @@ static void update_display(Options *op, XConfigScreenPtr screen);
int update_modules(XConfigPtr config)
{
XConfigLoadPtr load, next;
- int found;
if (config->modules == NULL) {
config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
}
- /* make sure glx is loaded */
-
- found = FALSE;
- for (load = config->modules->loads; load; load = load->next) {
- if (xconfigNameCompare("glx", load->name) == 0) found = TRUE;
- }
-
- if (!found) {
- config->modules->loads =
- xconfigAddNewLoadDirective(config->modules->loads,
- "glx", XCONFIG_LOAD_MODULE,
- NULL, FALSE);
- }
+ /* make sure all our required modules are loaded */
+ ensure_module_loaded(config, "glx");
+#if defined(NV_SUNOS)
+ ensure_module_loaded(config, "xtsol");
+#endif // defined(NV_SUNOS)
/* make sure GLcore and dri are not loaded */
@@ -158,6 +169,10 @@ int update_extensions(Options *op, XConfigPtr config)
{
char *value;
+ /* validate the composite option against any other options specified */
+
+ validate_composite(op, config);
+
if (GET_BOOL_OPTION(op->boolean_options, COMPOSITE_BOOL_OPTION)) {
/* if we don't already have the Extensions section, create it now */
diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c
index dfb43b5..3ae1af8 100644
--- a/nvidia-xconfig.c
+++ b/nvidia-xconfig.c
@@ -234,7 +234,6 @@ Options *parse_commandline(int argc, char *argv[])
{
Options *op;
int c, boolval;
- u32 bit;
char *strval;
int intval, disable;
@@ -257,17 +256,9 @@ Options *parse_commandline(int argc, char *argv[])
if ((c >= XCONFIG_BOOL_OPTION_START) &&
(c <= (XCONFIG_BOOL_OPTION_START + XCONFIG_BOOL_OPTION_COUNT))) {
+
+ set_boolean_option(op, c - XCONFIG_BOOL_OPTION_START, boolval);
- bit = GET_BOOL_OPTION_BIT(c - XCONFIG_BOOL_OPTION_START);
- GET_BOOL_OPTION_SLOT(op->boolean_options,
- c - XCONFIG_BOOL_OPTION_START) |= bit;
- if (boolval) {
- GET_BOOL_OPTION_SLOT(op->boolean_option_values,
- c - XCONFIG_BOOL_OPTION_START) |= bit;
- } else {
- GET_BOOL_OPTION_SLOT(op->boolean_option_values,
- c - XCONFIG_BOOL_OPTION_START) &= ~bit;
- }
continue;
}
@@ -512,7 +503,7 @@ Options *parse_commandline(int argc, char *argv[])
case QUERY_GPU_INFO_OPTION: op->query_gpu_info = TRUE; break;
case 'E':
- op->extract_edids_from_log = strval;
+ op->extract_edids_from_file = strval;
break;
case EXTRACT_EDIDS_OUTPUT_FILE_OPTION:
@@ -583,6 +574,15 @@ Options *parse_commandline(int argc, char *argv[])
op->logo_path = disable ? NV_DISABLE_STRING_OPTION : strval;
break;
+ case USE_DISPLAY_DEVICE_OPTION:
+ op->use_display_device =
+ disable ? NV_DISABLE_STRING_OPTION : strval;
+ break;
+
+ case CUSTOM_EDID_OPTION:
+ op->custom_edid = disable ? NV_DISABLE_STRING_OPTION : strval;
+ break;
+
default:
goto fail;
}
@@ -939,33 +939,71 @@ int update_xconfig(Options *op, XConfigPtr config)
/*
* get_xserver_in_use() - try to determine which X server is in use
- * (XFree86, Xorg)
+ * (XFree86, Xorg); also determine if the X server supports the
+ * Extension section of the X config file; support for the "Extension"
+ * section was added between X.Org 6.7 and 6.8.
*
- * XXX need to update for modular layout
+ * Some of the parsing here mimics what is done in the
+ * check_for_modular_xorg() function in nvidia-installer
*/
-# define NV_LINE_LEN 1024
+#define NV_LINE_LEN 1024
+#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
+#define VERSION_FORMAT "X Protocol Version %d, Revision %d, Release %d.%d"
+
static void get_xserver_in_use(Options *op)
{
#if defined(NV_SUNOS)
- op->gop.xserver=X_IS_XORG;
+
+ /*
+ * Solaris x86/x64 always uses X.Org 6.8 or higher, atleast as far
+ * as the NVIDIA X driver is concerned
+ */
+
+ op->gop.xserver = X_IS_XORG;
+ op->supports_extension_section = TRUE;
+
#else
- char *cmd;
+
FILE *stream = NULL;
int xserver = -1;
-
- cmd = xconfigStrcat(op->gop.x_project_root, "/bin/X -version 2>&1", NULL);
+ int dummy, len, release_major, release_minor;
+ char *cmd, *ptr, *ret;
+
+ op->supports_extension_section = FALSE;
+
+ /* run `X -version` with a PATH that hopefully includes the X binary */
+
+ cmd = xconfigStrcat("PATH=", op->gop.x_project_root, ":",
+ EXTRA_PATH, ":$PATH X -version 2>&1", NULL);
+
if ((stream = popen(cmd, "r"))) {
- char buf[NV_LINE_LEN];
+ char buf[NV_LINE_LEN];
+
+ /* read in as much of the input as we can fit into the buffer */
+
+ ptr = buf;
- while (1) {
- if (fgets(buf, NV_LINE_LEN-1, stream) == NULL) break;
-
- if (xserver == -1) {
- if (strcmp(buf, "XFree86") >= 0) {
- xserver = X_IS_XF86;
- } else if (strcmp(buf, "X Window System") >= 0) {
- xserver = X_IS_XORG;
+ do {
+ len = NV_LINE_LEN - (ptr - buf) - 1;
+ ret = fgets(ptr, len, stream);
+ ptr = strchr(ptr, '\0');
+ } while ((ret != NULL) && (len > 1));
+
+ /* Check if this is an XFree86 release */
+
+ if (strstr(buf, "XFree86 Version") != NULL) {
+ xserver = X_IS_XF86;
+ op->supports_extension_section = FALSE;
+ } else if (strstr(buf, "X Window System") != NULL) {
+ xserver = X_IS_XORG;
+ if ((ptr = strstr(buf, "X Protocol Version")) != NULL &&
+ sscanf(ptr, VERSION_FORMAT, &dummy, &dummy,
+ &release_major, &release_minor) == 4) {
+
+ if ((release_major > 6) ||
+ ((release_major == 6) && (release_minor >= 8))) {
+ op->supports_extension_section = TRUE;
}
}
}
@@ -1037,7 +1075,7 @@ int main(int argc, char *argv[])
return (ret ? 0 : 1);
}
- if (op->extract_edids_from_log) {
+ if (op->extract_edids_from_file) {
ret = extract_edids(op);
return (ret ? 0 : 1);
}
diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h
index 521e494..b252b6d 100644
--- a/nvidia-xconfig.h
+++ b/nvidia-xconfig.h
@@ -150,11 +150,13 @@ typedef struct __options {
char *rotate;
char *nvidia_cfg_path;
- char *extract_edids_from_log;
+ char *extract_edids_from_file;
char *extract_edids_output_file;
char *twinview_xinerama_info_order;
char *logo_path;
char *twinview_orientation;
+ char *use_display_device;
+ char *custom_edid;
struct {
int x;
@@ -164,6 +166,8 @@ typedef struct __options {
TextRows add_modes;
TextRows remove_modes;
+ int supports_extension_section;
+
GenerateOptions gop;
} Options;
@@ -243,6 +247,8 @@ int print_tree(Options *op, XConfigPtr config);
/* options.c */
void remove_option_from_list(XConfigOptionPtr *list, const char *name);
+void set_boolean_option(Options *op, const int c, const int boolval);
+void validate_composite(Options *op, XConfigPtr config);
void update_options(Options *op, XConfigScreenPtr screen);
/* lscf.c */
diff --git a/option_table.h b/option_table.h
index 6eaec1f..8b59c03 100644
--- a/option_table.h
+++ b/option_table.h
@@ -35,6 +35,8 @@
#define LOGO_PATH_OPTION 24
#define TWINVIEW_ORIENTATION_OPTION 25
#define VIRTUAL_OPTION 26
+#define USE_DISPLAY_DEVICE_OPTION 27
+#define CUSTOM_EDID_OPTION 28
/*
* To add a boolean option to nvidia-xconfig:
@@ -148,6 +150,12 @@ static const NVGetoptOption __options[] = {
"millimeters of the X screen when XRandR changes the size in pixels "
"of the X screen." },
+ { "custom-edid", CUSTOM_EDID_OPTION,
+ NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "CUSTOM-EDID",
+ "Enable or disable the \"CustomEDID\" X configuration option; "
+ "setting this option forces the X driver to use the EDID specified "
+ "in a file rather than the display's EDID." },
+
{ "dac-8bit", XCONFIG_BOOL_VAL(DAC_8BIT_BOOL_OPTION),
NVGETOPT_IS_BOOLEAN, NULL,
"Most Quadro parts by default use a 10 bit color look up table (LUT) "
@@ -194,7 +202,7 @@ static const NVGetoptOption __options[] = {
"Forces the initialization of the X server with "
"the exact timings specified in the ModeLine." },
- { "extract-edids-from-log", 'E', NVGETOPT_STRING_ARGUMENT, "LOG",
+ { "extract-edids-from-file", 'E', NVGETOPT_STRING_ARGUMENT, "FILE",
"Extract any raw EDID byte blocks contained in the specified X "
"log file [LOG]; raw EDID bytes are printed by the NVIDIA X driver to "
"the X log as hexidecimal when verbose logging is enabled with the "
@@ -476,6 +484,10 @@ static const NVGetoptOption __options[] = {
"Enable use of the X Int10 module to soft-boot all secondary cards, "
"rather than POSTing the cards through the NVIDIA kernel module." },
+ { "use-display-device", USE_DISPLAY_DEVICE_OPTION,
+ NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "DISPLAY-DEVICE",
+ "Force the X driver to use the display device specified." },
+
{ "virtual", VIRTUAL_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "WIDTHxHEIGHT",
"Specify the virtual screen resolution." },
diff --git a/options.c b/options.c
index 5d7c081..2819f9d 100644
--- a/options.c
+++ b/options.c
@@ -113,6 +113,126 @@ void remove_option_from_list(XConfigOptionPtr *list, const char *name)
/*
+ * set_boolean_option() - set boolean option 'c' to the given 'boolval'
+ */
+
+void set_boolean_option(Options *op, const int c, const int boolval)
+{
+ u32 bit;
+
+ bit = GET_BOOL_OPTION_BIT(c);
+
+ GET_BOOL_OPTION_SLOT(op->boolean_options, c) |= bit;
+
+ if (boolval) {
+ GET_BOOL_OPTION_SLOT(op->boolean_option_values, c) |= bit;
+ } else {
+ GET_BOOL_OPTION_SLOT(op->boolean_option_values, c) &= ~bit;
+ }
+} /* set_boolean_option() */
+
+
+
+/*
+ * validate_composite() - check whether any options conflict with the
+ * Composite extension; update the composite option value, if
+ * appropriate.
+ */
+
+void validate_composite(Options *op, XConfigPtr config)
+{
+ int i, n, opt, disable_composite;
+ char scratch[256], *s;
+
+
+ /*
+ * the composite_incompatible_options[] array lists all the
+ * options that are incompatible with the composite extension; we
+ * list boolean options and then special-case any non-boolean options
+ */
+
+ static int composite_incompatible_options[] = {
+ XINERAMA_BOOL_OPTION,
+ OVERLAY_BOOL_OPTION,
+ CIOVERLAY_BOOL_OPTION,
+ UBB_BOOL_OPTION,
+ -1, /* stereo */
+ -2 /* end */
+ };
+
+ disable_composite = FALSE;
+ s = scratch;
+ n = 0;
+
+ /*
+ * loop through all the incompatible options, and check if the
+ * user specified any of them
+ */
+
+ for (i = 0; composite_incompatible_options[i] != -2; i++) {
+
+ int present = 0;
+ const char *name;
+
+ opt = composite_incompatible_options[i];
+
+ if (opt == -1) { /* special case stereo */
+
+ present = (op->stereo > 0);
+ name = "Stereo";
+
+ } else {
+ const NvidiaXConfigOption *o;
+
+ present = (GET_BOOL_OPTION(op->boolean_options, opt) &&
+ GET_BOOL_OPTION(op->boolean_option_values, opt));
+
+ o = get_option(opt);
+ name = o->name;
+ }
+
+ /*
+ * if the option is present, then we have to disable
+ * composite; append to the scratch string that lists all the
+ * present conflicting options
+ */
+
+ if (present) {
+ disable_composite = TRUE;
+ n++;
+ s += sprintf(s, "%s%s", (n > 1) ? " or " : "", name);
+ }
+ }
+
+ /*
+ * if we have to disable the composite extension, print a warning
+ * and set the option value.
+ *
+ * We need to be careful to only set the option value if the X
+ * server is going to recognize the Extension section and the
+ * composite option. We guess whether the server will recognize
+ * the option: if get_xserver_in_use() thinks the X server
+ * supports the "Composite" extension, or the current config
+ * already has an extension section, or the user specified the
+ * composite option.
+ */
+
+ if (disable_composite &&
+ (op->supports_extension_section ||
+ config->extensions ||
+ GET_BOOL_OPTION(op->boolean_options, COMPOSITE_BOOL_OPTION))) {
+
+ fmtwarn("The Composite X extension does not currently interact well "
+ "with the %s option%s; the Composite X extension will be "
+ "disabled.", scratch, (n > 1) ? "s": "");
+
+ set_boolean_option(op, COMPOSITE_BOOL_OPTION, FALSE);
+ }
+} /* validate_composite() */
+
+
+
+/*
* remove_option() - make sure the named option does not exist in any
* of the possible option lists:
*
@@ -375,4 +495,24 @@ void update_options(Options *op, XConfigScreenPtr screen)
}
}
+ /* add the UseDisplayDevice option */
+
+ if (op->use_display_device) {
+ remove_option(screen, "UseDisplayDevice");
+ if (op->use_display_device != NV_DISABLE_STRING_OPTION) {
+ set_option_value(screen, "UseDisplayDevice",
+ op->use_display_device);
+ }
+ }
+
+ /* add the CustomEDID option */
+
+ if (op->custom_edid) {
+ remove_option(screen, "CustomEDID");
+ if (op->custom_edid != NV_DISABLE_STRING_OPTION) {
+ set_option_value(screen, "CustomEDID", op->custom_edid);
+ }
+ }
+
+
} /* update_options() */