xf86-video-nv 2.1.6

This commit is contained in:
matthieu 2008-01-12 16:28:55 +00:00
parent c8a36eb115
commit e63dd002ce
9 changed files with 300 additions and 98 deletions

View File

@ -1,3 +1,27 @@
commit 58dbd31953d0e2f30d06b3fc5118a016a17666fe
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Tue Oct 23 13:17:27 2007 -0700
Bump to 2.1.6.
commit 0887084730af8428e902dabc6e00c505f383f57f
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Sun Oct 14 14:15:07 2007 -0700
G80 bug #12397: Fix LVDS detection on certain laptops.
commit 1003bcbe4381201f1d7b34dc1af72f57b2943b67
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Sat Oct 13 14:36:49 2007 -0700
G80 bug #12637: Unwedge the hardware if the BIOS left it stuck.
commit 1e12277650dff10b1083915cb73961525e21a471
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Sat Oct 13 13:50:04 2007 -0700
Remove unused headers.
commit 7a124edd1fcc0be6bdad489b0e8d7db3efe44b14
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Fri Sep 21 18:55:21 2007 -0700

View File

@ -711,7 +711,8 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height)
for (mode = output->probed_modes; mode; mode = mode->next)
{
int dpi;
int preferred = (mode->type & M_T_PREFERRED) != 0;
int preferred = (((mode->type & M_T_PREFERRED) != 0) +
((mode->type & M_T_USERPREF) != 0));
int diff;
if (xf86ModeWidth (mode, output->initial_rotation) > width ||
@ -1415,10 +1416,9 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
mode->prev = NULL;
output->probed_modes = mode;
}
mode->type |= M_T_PREFERRED;
mode->type |= (M_T_PREFERRED|M_T_USERPREF);
break;
}
else
mode->type &= ~M_T_PREFERRED;
}
}
@ -1532,6 +1532,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
int o, c;
DisplayModePtr target_mode = NULL;
int target_preferred = 0;
Rotation target_rotation = RR_Rotate_0;
xf86CrtcPtr *crtcs;
DisplayModePtr *modes;
@ -1572,43 +1573,34 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
}
/*
* Let outputs with preferred modes drive screen size
* User preferred > preferred > other modes
*/
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
xf86OutputPtr output = config->output[o];
DisplayModePtr default_mode;
int default_preferred;
if (enabled[o] &&
xf86OutputHasPreferredMode (output, width, height))
if (!enabled[o])
continue;
default_mode = xf86DefaultMode (output, width, height);
if (!default_mode)
continue;
default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
((default_mode->type & M_T_USERPREF) != 0));
if (default_preferred > target_preferred || !target_mode)
{
target_mode = xf86DefaultMode (output, width, height);
target_mode = default_mode;
target_preferred = default_preferred;
target_rotation = output->initial_rotation;
if (target_mode)
{
modes[o] = target_mode;
config->compat_output = o;
break;
}
}
}
if (!target_mode)
{
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
if (enabled[o])
{
target_mode = xf86DefaultMode (output, width, height);
target_rotation = output->initial_rotation;
if (target_mode)
{
modes[o] = target_mode;
config->compat_output = o;
break;
}
}
config->compat_output = o;
}
}
if (target_mode)
modes[config->compat_output] = target_mode;
/*
* Fill in other output modes
*/
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
@ -2134,8 +2126,12 @@ _X_EXPORT xf86MonPtr
xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
{
ScrnInfoPtr scrn = output->scrn;
xf86MonPtr mon;
return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
xf86DDCApplyQuirks (scrn->scrnIndex, pDDCBus);
return mon;
}
static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D",
@ -2220,7 +2216,10 @@ xf86_covering_crtc(ScrnInfoPtr pScrn,
/*
* For overlay video, compute the relevant CRTC and
* clip video to that
* clip video to that.
*
* returning FALSE means there was a memory failure of some kind,
* not that the video shouldn't be displayed
*/
_X_EXPORT Bool

View File

@ -39,6 +39,9 @@
#ifndef M_T_DRIVER
#define M_T_DRIVER 0x40
#endif
#ifndef M_T_USERPREF
#define M_T_USERPREF 0x80
#endif
#ifndef HARDWARE_CURSOR_ARGB
#define HARDWARE_CURSOR_ARGB 0x00004000
#endif

View File

@ -54,6 +54,18 @@ typedef enum {
DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
/* 135MHz clock is too high, drop a bit */
DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
/* Prefer the largest mode at 75 Hz */
DDC_QUIRK_PREFER_LARGE_75 = 1 << 2,
/* Convert detailed timing's horizontal from units of cm to mm */
DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3,
/* Convert detailed timing's vertical from units of cm to mm */
DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4,
/* Detailed timing descriptors have bogus size values, so just take the
* maximum size and use that.
*/
DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5,
/* Monitor forgot to set the first detailed is preferred bit. */
DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
} ddc_quirk_t;
static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
@ -81,6 +93,52 @@ static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
return FALSE;
}
static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC)
{
/* Bug #11603: Funai Electronics PM36B */
if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
DDC->vendor.prod_id == 13600)
return TRUE;
return FALSE;
}
static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC)
{
/* Bug #10304: "LGPhilipsLCD LP154W01-A5" */
/* Bug #12784: "LGPhilipsLCD LP154W01-TLA2" */
if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
DDC->vendor.prod_id == 0)
return TRUE;
/* Bug #11603: Funai Electronics PM36B */
if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
DDC->vendor.prod_id == 13600)
return TRUE;
return FALSE;
}
static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC)
{
/* Bug #11603: Funai Electronics PM36B */
if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
DDC->vendor.prod_id == 13600)
return TRUE;
return FALSE;
}
static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC)
{
/* Bug #10304: LGPhilipsLCD LP154W01-A5 */
if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
DDC->vendor.prod_id == 0)
return TRUE;
return FALSE;
}
static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
{
/* Envision Peripherals, Inc. EN-7100e. See bug #9550. */
@ -91,6 +149,16 @@ static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
return FALSE;
}
static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC)
{
/* Philips 107p5 CRT. Reported on xorg@ with pastebin. */
if (memcmp (DDC->vendor.name, "PHL", 4) == 0 &&
DDC->vendor.prod_id == 57364)
return TRUE;
return FALSE;
}
typedef struct {
Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
ddc_quirk_t quirk;
@ -106,6 +174,26 @@ static const ddc_quirk_map_t ddc_quirks[] = {
quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH,
"Recommended 135MHz pixel clock is too high"
},
{
quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75,
"Detailed timing is not preferred, use largest mode at 75Hz"
},
{
quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM,
"Detailed timings give horizontal size in cm."
},
{
quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM,
"Detailed timings give vertical size in cm."
},
{
quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
"Detailed timings give sizes in cm."
},
{
quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED,
"First detailed timing was not marked as preferred."
},
{
NULL, DDC_QUIRK_NONE,
"No known quirks"
@ -185,7 +273,7 @@ DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
*/
static DisplayModePtr
DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
int preferred, ddc_quirk_t quirks)
Bool preferred, ddc_quirk_t quirks)
{
DisplayModePtr Mode;
@ -303,27 +391,116 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
}
}
static ddc_quirk_t
xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
{
ddc_quirk_t quirks;
int i;
quirks = DDC_QUIRK_NONE;
for (i = 0; ddc_quirks[i].detect; i++) {
if (ddc_quirks[i].detect (scrnIndex, DDC)) {
if (verbose) {
xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
ddc_quirks[i].description);
}
quirks |= ddc_quirks[i].quirk;
}
}
return quirks;
}
/**
* Applies monitor-specific quirks to the decoded EDID information.
*
* Note that some quirks applying to the mode list are still implemented in
* xf86DDCGetModes.
*/
void
xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC)
{
ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE);
int i;
for (i = 0; i < DET_TIMINGS; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
if (det_mon->type != DT)
continue;
if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
det_mon->section.d_timings.h_size *= 10;
if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
det_mon->section.d_timings.v_size *= 10;
if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
det_mon->section.d_timings.h_size = 10 * DDC->features.hsize;
det_mon->section.d_timings.v_size = 10 * DDC->features.vsize;
}
}
}
/**
* Walks the modes list, finding the mode with the largest area which is
* closest to the target refresh rate, and marks it as the only preferred mode.
*/
static void
xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes,
float target_refresh)
{
DisplayModePtr mode, best = modes;
for (mode = modes; mode; mode = mode->next)
{
mode->type &= ~M_T_PREFERRED;
if (mode == best) continue;
if (mode->HDisplay * mode->VDisplay >
best->HDisplay * best->VDisplay)
{
best = mode;
continue;
}
if (mode->HDisplay * mode->VDisplay ==
best->HDisplay * best->VDisplay)
{
double mode_refresh = xf86ModeVRefresh (mode);
double best_refresh = xf86ModeVRefresh (best);
double mode_dist = fabs(mode_refresh - target_refresh);
double best_dist = fabs(best_refresh - target_refresh);
if (mode_dist < best_dist)
{
best = mode;
continue;
}
}
}
if (best)
best->type |= M_T_PREFERRED;
}
_X_EXPORT DisplayModePtr
xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
{
int preferred, i;
int i;
DisplayModePtr Modes = NULL, Mode;
ddc_quirk_t quirks;
Bool preferred;
xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
DDC->vendor.name, DDC->vendor.prod_id);
quirks = DDC_QUIRK_NONE;
for (i = 0; ddc_quirks[i].detect; i++)
if (ddc_quirks[i].detect (scrnIndex, DDC))
{
xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
ddc_quirks[i].description);
quirks |= ddc_quirks[i].quirk;
}
quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE);
preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
if (quirks & DDC_QUIRK_PREFER_LARGE_60)
preferred = 0;
if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED)
preferred = TRUE;
if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75))
preferred = FALSE;
for (i = 0; i < DET_TIMINGS; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
@ -334,7 +511,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
&det_mon->section.d_timings,
preferred,
quirks);
preferred = 0;
preferred = FALSE;
Modes = xf86ModesAdd(Modes, Mode);
break;
case DS_STD_TIMINGS:
@ -357,32 +534,11 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
Modes = xf86ModesAdd(Modes, Mode);
if (quirks & DDC_QUIRK_PREFER_LARGE_60)
{
DisplayModePtr best = Modes;
for (Mode = Modes; Mode; Mode = Mode->next)
{
if (Mode == best) continue;
if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
{
best = Mode;
continue;
}
if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
{
double mode_refresh = xf86ModeVRefresh (Mode);
double best_refresh = xf86ModeVRefresh (best);
double mode_dist = fabs(mode_refresh - 60.0);
double best_dist = fabs(best_refresh - 60.0);
if (mode_dist < best_dist)
{
best = Mode;
continue;
}
}
}
if (best)
best->type |= M_T_PREFERRED;
}
xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
if (quirks & DDC_QUIRK_PREFER_LARGE_75)
xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
return Modes;
}

View File

@ -389,8 +389,8 @@ xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
bad = TRUE;
for (i = 0; i < mon->nHsync; i++) {
if (xf86ModeHSync(mode) >= mon->hsync[i].lo &&
xf86ModeHSync(mode) <= mon->hsync[i].hi)
if (xf86ModeHSync(mode) >= mon->hsync[i].lo * (1-SYNC_TOLERANCE) &&
xf86ModeHSync(mode) <= mon->hsync[i].hi * (1+SYNC_TOLERANCE))
{
bad = FALSE;
}
@ -400,8 +400,8 @@ xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
bad = TRUE;
for (i = 0; i < mon->nVrefresh; i++) {
if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo * (1-SYNC_TOLERANCE) &&
xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi * (1+SYNC_TOLERANCE))
{
bad = FALSE;
}
@ -434,7 +434,8 @@ xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
for (mode = modeList; mode != NULL; mode = mode->next) {
Bool good = FALSE;
for (i = 0; i < n_ranges; i++) {
if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
if (mode->Clock >= min[i] * (1-SYNC_TOLERANCE) &&
mode->Clock <= max[i] * (1+SYNC_TOLERANCE)) {
good = TRUE;
break;
}

View File

@ -95,4 +95,7 @@ xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
DisplayModePtr
xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
void
xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC);
#endif /* _XF86MODES_H_ */

View File

@ -22,7 +22,7 @@
AC_PREREQ(2.57)
AC_INIT([xf86-video-nv],
2.1.5,
2.1.6,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
xf86-video-nv)

View File

@ -41,11 +41,9 @@ nv_sources = \
nv_include.h \
nv_local.h \
nv_proto.h \
nvreg.h \
nv_setup.c \
nv_shadow.c \
nv_type.h \
nvvga.h \
nv_video.c \
nv_xaa.c

View File

@ -427,20 +427,20 @@ static const xf86OutputFuncsRec G80SorLVDSOutputFuncs = {
};
static DisplayModePtr
GetLVDSNativeMode(G80Ptr pNv)
ReadLVDSNativeMode(G80Ptr pNv, const int off)
{
DisplayModePtr mode = xnfcalloc(1, sizeof(DisplayModeRec));
const CARD32 size = pNv->reg[0x00610B4C/4];
const CARD32 size = pNv->reg[(0x00610B4C+off)/4];
const int width = size & 0x3fff;
const int height = (size >> 16) & 0x3fff;
mode->HDisplay = mode->CrtcHDisplay = width;
mode->VDisplay = mode->CrtcVDisplay = height;
mode->Clock = pNv->reg[0x610AD4/4] & 0x3fffff;
mode->CrtcHBlankStart = pNv->reg[0x610AFC/4];
mode->CrtcHSyncEnd = pNv->reg[0x610B04/4];
mode->CrtcHBlankEnd = pNv->reg[0x610AE8/4];
mode->CrtcHTotal = pNv->reg[0x610AF4/4];
mode->Clock = pNv->reg[(0x610AD4+off)/4] & 0x3fffff;
mode->CrtcHBlankStart = pNv->reg[(0x610AFC+off)/4];
mode->CrtcHSyncEnd = pNv->reg[(0x610B04+off)/4];
mode->CrtcHBlankEnd = pNv->reg[(0x610AE8+off)/4];
mode->CrtcHTotal = pNv->reg[(0x610AF4+off)/4];
mode->next = mode->prev = NULL;
mode->status = MODE_OK;
@ -451,6 +451,19 @@ GetLVDSNativeMode(G80Ptr pNv)
return mode;
}
static DisplayModePtr
GetLVDSNativeMode(G80Ptr pNv)
{
CARD32 val = pNv->reg[0x00610050/4];
if((val & 3) == 2)
return ReadLVDSNativeMode(pNv, 0);
else if((val & 0x300) == 0x200)
return ReadLVDSNativeMode(pNv, 0x540);
return NULL;
}
xf86OutputPtr
G80CreateSor(ScrnInfoPtr pScrn, ORNum or, PanelType panelType)
{
@ -467,6 +480,19 @@ G80CreateSor(ScrnInfoPtr pScrn, ORNum or, PanelType panelType)
if(panelType == LVDS) {
strcpy(orName, "LVDS");
funcs = &G80SorLVDSOutputFuncs;
pPriv->nativeMode = GetLVDSNativeMode(pNv);
if(!pPriv->nativeMode) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to find LVDS native mode\n");
xfree(pPriv);
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s native size %dx%d\n",
orName, pPriv->nativeMode->HDisplay,
pPriv->nativeMode->VDisplay);
} else {
snprintf(orName, 5, "DVI%d", or);
pNv->reg[(0x61C00C+off)/4] = 0x03010700;
@ -488,13 +514,5 @@ G80CreateSor(ScrnInfoPtr pScrn, ORNum or, PanelType panelType)
output->interlaceAllowed = TRUE;
output->doubleScanAllowed = TRUE;
if(panelType == LVDS) {
pPriv->nativeMode = GetLVDSNativeMode(pNv);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s native size %dx%d\n",
orName, pPriv->nativeMode->HDisplay,
pPriv->nativeMode->VDisplay);
}
return output;
}