On 3/16/08, Maarten Maathuis <[EMAIL PROTECTED]> wrote:
> This is primarily targeted at Koala_BR, but if someone happens to have
> a a fully working nouveay g80 setup, then go ahead.
>
> Maarten.
>
> (this is attempt 2, as 100 KiB seems to be the maximum allowed size)
>
>
And a combined patch.
diff --git a/src/nv50_crtc.c b/src/nv50_crtc.c
index 214c964..816362d 100644
--- a/src/nv50_crtc.c
+++ b/src/nv50_crtc.c
@@ -99,22 +99,8 @@ static const xf86CrtcFuncsRec nv50_crtc_funcs = {
.destroy = NULL,
};
-void NV50DispCreateCrtcs(ScrnInfoPtr pScrn)
+const xf86CrtcFuncsRec * nv50_get_crtc_funcs()
{
- NVPtr pNv = NVPTR(pScrn);
- Head head;
- xf86CrtcPtr crtc;
- NVCrtcPrivatePtr nv50_crtc;
-
- /* Create a "crtc" object for each head */
- for(head = HEAD0; head <= HEAD1; head++) {
- crtc = xf86CrtcCreate(pScrn, &nv50_crtc_funcs);
- if(!crtc) return;
-
- nv50_crtc = xnfcalloc(sizeof(*nv50_crtc), 1);
- nv50_crtc->head = head;
- nv50_crtc->ditherEnabled = pNv->FPDither;
- crtc->driver_private = nv50_crtc;
- }
+ return &nv50_crtc_funcs;
}
diff --git a/src/nv50_dac.c b/src/nv50_dac.c
index 0f9109a..74235d5 100644
--- a/src/nv50_dac.c
+++ b/src/nv50_dac.c
@@ -191,25 +191,8 @@ static const xf86OutputFuncsRec NV50DacOutputFuncs = {
.destroy = NV50DacDestroy,
};
-xf86OutputPtr
-NV50CreateDac(ScrnInfoPtr pScrn, ORNum or)
+const xf86OutputFuncsRec * nv50_get_analog_output_funcs()
{
- NVOutputPrivatePtr nv_output = xnfcalloc(sizeof(*nv_output), 1);
- xf86OutputPtr output;
- char orName[5];
-
- if(!nv_output)
- return NULL;
-
- snprintf(orName, 5, "VGA%i", or);
- output = xf86OutputCreate(pScrn, &NV50DacOutputFuncs, orName);
-
- nv_output->type = OUTPUT_ANALOG;
- nv_output->output_resource = or;
- output->driver_private = nv_output;
- output->interlaceAllowed = TRUE;
- output->doubleScanAllowed = TRUE;
-
- return output;
+ return &NV50DacOutputFuncs;
}
diff --git a/src/nv50_display.c b/src/nv50_display.c
index 5391fc9..55333a8 100644
--- a/src/nv50_display.c
+++ b/src/nv50_display.c
@@ -205,6 +205,7 @@ Bool
NV50DispInit(ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
+ uint32_t val;
if (NVRead(pNv, 0x00610024) & 0x100) {
NVWrite(pNv, 0x00610024, 0x100);
NVWrite(pNv, 0x006194e8, NVRead(pNv, 0x006194e8) & ~1);
@@ -214,20 +215,21 @@ NV50DispInit(ScrnInfoPtr pScrn)
NVWrite(pNv, 0x00610200, 0x2b00);
/* A bugfix (#12637) from the nv driver, to unlock the driver if it's left in a poor state */
do {
- CARD32 val = NVRead(pNv, 0x00610200);
+ val = NVRead(pNv, 0x00610200);
if ((val & 0x9f0000) == 0x20000)
NVWrite(pNv, 0x00610200, val | 0x800000);
if ((val & 0x3f0000) == 0x30000)
NVWrite(pNv, 0x00610200, val | 0x200000);
- } while ((NVRead(pNv, 0x00610200) & 0x1e0000) != 0);
+ } while ((val & 0x1e0000) != 0);
NVWrite(pNv, 0x00610300, 0x1);
NVWrite(pNv, 0x00610200, 0x1000b03);
while (!(NVRead(pNv, 0x00610200) & 0x40000000));
NV50DisplayCommand(pScrn, 0x84, 0);
NV50DisplayCommand(pScrn, 0x88, 0);
- NV50DisplayCommand(pScrn, 0x874, 0);
+ /* Does the bios always use crtc0? */
+ NV50DisplayCommand(pScrn, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
NV50DisplayCommand(pScrn, 0x800, 0);
NV50DisplayCommand(pScrn, 0x810, 0);
NV50DisplayCommand(pScrn, 0x82c, 0);
@@ -248,7 +250,7 @@ NV50DispShutdown(ScrnInfoPtr pScrn)
NV50CrtcBlankScreen(crtc, TRUE);
}
- NV50DisplayCommand(pScrn, 0x80, 0);
+ NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
for(i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -339,7 +341,7 @@ NV50CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_m
NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_24BPP);
break;
}
- NV50CrtcSetDither(crtc, nv_crtc->ditherEnabled, FALSE);
+ NV50CrtcSetDither(crtc, FALSE);
NV50CrtcCommand(crtc, 0x8a8, 0x40000);
NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, y << 16 | x);
NV50CrtcCommand(crtc, NV50_CRTC0_SCRN_SIZE, VDisplay << 16 | HDisplay);
@@ -361,10 +363,10 @@ NV50CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank)
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, NV50_CRTC0_CLUT_MODE_BLANK);
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, 0);
if(pNv->NVArch != 0x50)
- NV50CrtcCommand(crtc, 0x85c, 0);
- NV50CrtcCommand(crtc, 0x874, 0);
+ NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_BLANK);
+ NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
if(pNv->NVArch != 0x50)
- NV50CrtcCommand(crtc, 0x89c, 0);
+ NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_BLANK);
} else {
NV50CrtcCommand(crtc, NV50_CRTC0_FB_OFFSET, pNv->FB->offset >> 8);
NV50CrtcCommand(crtc, 0x864, 0);
@@ -375,15 +377,15 @@ NV50CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank)
NVWrite(pNv, 0x0061038C, 0);
NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, pNv->Cursor->offset >> 8);
if(pNv->NVArch != 0x50)
- NV50CrtcCommand(crtc, 0x89c, 1);
+ NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_UNBLANK);
if(nv_crtc->cursorVisible)
NV50CrtcShowHideCursor(crtc, TRUE, FALSE);
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE,
pScrn->depth == 8 ? NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON);
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, pNv->CLUT->offset >> 8);
if(pNv->NVArch != 0x50)
- NV50CrtcCommand(crtc, 0x85c, 1);
- NV50CrtcCommand(crtc, 0x874, 1);
+ NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_UNBLANK);
+ NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL_BLANK, NV50_CRTC0_BLANK_CTRL_UNBLANK);
}
}
@@ -391,12 +393,13 @@ NV50CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank)
static void NV50CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update)
{
NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
+ ScrnInfoPtr pScrn = crtc->scrn;
- NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR0,
- show ? NV50_CRTC0_CURSOR0_SHOW : NV50_CRTC0_CURSOR0_HIDE);
- if(update) {
+ NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR,
+ show ? NV50_CRTC0_CURSOR_SHOW : NV50_CRTC0_CURSOR_HIDE);
+ if (update) {
nv_crtc->cursorVisible = show;
- NV50CrtcCommand(crtc, 0x80, 0);
+ NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
}
}
@@ -438,15 +441,20 @@ NV50CrtcSkipModeFixup(xf86CrtcPtr crtc)
}
void
-NV50CrtcSetDither(xf86CrtcPtr crtc, Bool dither, Bool update)
+NV50CrtcSetDither(xf86CrtcPtr crtc, Bool update)
{
- NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
+ xf86OutputPtr output = NVGetOutputFromCRTC(crtc);
+ ScrnInfoPtr pScrn = crtc->scrn;
- nv_crtc->ditherEnabled = dither;
+ if (!output)
+ return;
- NV50CrtcCommand(crtc, 0x8a0, dither ? 0x11 : 0);
- if(update)
- NV50CrtcCommand(crtc, 0x80, 0);
+ NVOutputPrivatePtr nv_output = output->driver_private;
+
+ NV50CrtcCommand(crtc, NV50_CRTC0_DITHERING_CTRL, nv_output->dithering ?
+ NV50_CRTC0_DITHERING_CTRL_ON : NV50_CRTC0_DITHERING_CTRL_OFF);
+ if (update)
+ NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
}
static void ComputeAspectScale(DisplayModePtr mode, int *outX, int *outY)
@@ -499,6 +507,7 @@ void
NV50CrtcCommit(xf86CrtcPtr crtc)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ ScrnInfoPtr pScrn = crtc->scrn;
int i, crtc_mask = 0;
/* If any heads are unused, blank them */
@@ -517,6 +526,6 @@ NV50CrtcCommit(xf86CrtcPtr crtc)
}
}
- NV50CrtcCommand(crtc, 0x80, 0);
+ NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
}
diff --git a/src/nv50_display.h b/src/nv50_display.h
index 74f2a26..d8c2498 100644
--- a/src/nv50_display.h
+++ b/src/nv50_display.h
@@ -15,9 +15,10 @@ void NV50CrtcEnableCursor(xf86CrtcPtr, Bool update);
void NV50CrtcDisableCursor(xf86CrtcPtr, Bool update);
void NV50CrtcSetCursorPosition(xf86CrtcPtr, int x, int y);
void NV50CrtcSkipModeFixup(xf86CrtcPtr);
-void NV50CrtcSetDither(xf86CrtcPtr, Bool dither, Bool update);
+void NV50CrtcSetDither(xf86CrtcPtr, Bool update);
void NV50CrtcSetScale(xf86CrtcPtr, DisplayModePtr, enum scaling_modes);
void NV50DispCreateCrtcs(ScrnInfoPtr pScrn);
+const xf86CrtcFuncsRec * nv50_get_crtc_funcs();
#endif
diff --git a/src/nv50_output.c b/src/nv50_output.c
index fa63b21..564db4c 100644
--- a/src/nv50_output.c
+++ b/src/nv50_output.c
@@ -30,143 +30,6 @@
#include <xf86DDC.h>
-static Bool NV50ReadPortMapping(int scrnIndex, NVPtr pNv)
-{
- unsigned const char *VBIOS = (unsigned const char *)pNv->VBIOS.data;
- unsigned char *table2;
- unsigned char headerSize, entries;
- int i;
- CARD16 a;
- CARD32 b;
-
- if (!VBIOS)
- goto fail;
-
- /* Clear the i2c map to invalid */
- for (i = 0; i < 4; i++)
- pNv->i2cMap[i].dac = pNv->i2cMap[i].sor = -1;
-
- if (*(CARD16*)VBIOS != 0xaa55) goto fail;
-
- a = *(CARD16*)(VBIOS + 0x36);
- table2 = (unsigned char*)VBIOS + a;
-
- if (table2[0] != 0x40) goto fail;
-
- b = *(CARD32*)(table2 + 6);
- if (b != 0x4edcbdcb) goto fail;
-
- headerSize = table2[1];
- entries = table2[2];
-
- for(i = 0; i < entries; i++) {
- int type, port;
- ORNum or;
-
- b = *(CARD32*)&table2[headerSize + 8*i];
- type = b & 0xf;
- port = (b >> 4) & 0xf;
- or = ffs((b >> 24) & 0xf) - 1;
-
- if (type == 0xe)
- break;
-
- if(type < 4) {
- switch(type) {
- case 0: /* CRT */
- if(pNv->i2cMap[port].dac != -1) {
- xf86DrvMsg(scrnIndex, X_WARNING,
- "DDC routing table corrupt! DAC %i -> %i "
- "for port %i\n",
- or, pNv->i2cMap[port].dac, port);
- }
- pNv->i2cMap[port].dac = or;
- break;
- case 1: /* TV */
- break;
- case 2: /* TMDS */
- if(pNv->i2cMap[port].sor != -1)
- xf86DrvMsg(scrnIndex, X_WARNING,
- "DDC routing table corrupt! SOR %i -> %i "
- "for port %i\n",
- or, pNv->i2cMap[port].sor, port);
- pNv->i2cMap[port].sor = or;
- break;
- case 3: /* LVDS */
- pNv->lvds.present = TRUE;
- pNv->lvds.or = or;
- break;
- }
- }
- }
-
- xf86DrvMsg(scrnIndex, X_PROBED, "Connector map:\n");
- if (pNv->lvds.present) {
- xf86DrvMsg(scrnIndex, X_PROBED,
- " [N/A] -> SOR%i (LVDS)\n", pNv->lvds.or);
- }
- for(i = 0; i < 4; i++) {
- if(pNv->i2cMap[i].dac != -1)
- xf86DrvMsg(scrnIndex, X_PROBED, " Bus %i -> DAC%i\n", i, pNv->i2cMap[i].dac);
- if(pNv->i2cMap[i].sor != -1)
- xf86DrvMsg(scrnIndex, X_PROBED, " Bus %i -> SOR%i\n", i, pNv->i2cMap[i].sor);
- }
-
- return TRUE;
-
- fail:
- xf86DrvMsg(scrnIndex, X_ERROR, "Couldn't find the DDC routing table. "
- "Mode setting will probably fail!\n");
- return FALSE;
-}
-
-static void NV50_I2CPutBits(I2CBusPtr b, int clock, int data)
-{
- NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
- const int off = b->DriverPrivate.val * 0x18;
-
- pNv->REGS[(0x0000E138+off)/4] = 4 | clock | data << 1;
-}
-
-static void NV50_I2CGetBits(I2CBusPtr b, int *clock, int *data)
-{
- NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
- const int off = b->DriverPrivate.val * 0x18;
- unsigned char val;
-
- val = pNv->REGS[(0x0000E138+off)/4];
- *clock = !!(val & 1);
- *data = !!(val & 2);
-}
-
-static I2CBusPtr
-NV50I2CInit(ScrnInfoPtr pScrn, const char *name, const int port)
-{
- I2CBusPtr i2c;
-
- /* Allocate the I2C bus structure */
- i2c = xf86CreateI2CBusRec();
- if(!i2c) return NULL;
-
- i2c->BusName = strdup(name);
- i2c->scrnIndex = pScrn->scrnIndex;
- i2c->I2CPutBits = NV50_I2CPutBits;
- i2c->I2CGetBits = NV50_I2CGetBits;
- i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
- i2c->StartTimeout = 550;
- i2c->BitTimeout = 40;
- i2c->ByteTimeout = 40;
- i2c->AcknTimeout = 40;
- i2c->DriverPrivate.val = port;
-
- if(xf86I2CBusInit(i2c)) {
- return i2c;
- } else {
- xfree(i2c);
- return NULL;
- }
-}
-
void
NV50OutputSetPClk(xf86OutputPtr output, int pclk)
{
@@ -245,72 +108,3 @@ NV50OutputDestroy(xf86OutputPtr output)
nv_output->pDDCBus = NULL;
}
-
-Bool
-NV50CreateOutputs(ScrnInfoPtr pScrn)
-{
- NVPtr pNv = NVPTR(pScrn);
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int i;
-
- if(!NV50ReadPortMapping(pScrn->scrnIndex, pNv))
- return FALSE;
-
- /* For each DDC port, create an output for the attached ORs */
- for (i = 0; i < 4; i++) {
- xf86OutputPtr dac = NULL, sor = NULL;
- I2CBusPtr i2c;
- char i2cName[16];
-
- if(pNv->i2cMap[i].dac == -1 && pNv->i2cMap[i].sor == -1) {
- /* No outputs on this port */
- continue;
- }
-
- snprintf(i2cName, sizeof(i2cName), "I2C%i", i);
- i2c = NV50I2CInit(pScrn, i2cName, i);
- if (!i2c) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to initialize I2C for port %i.\n",
- i);
- continue;
- }
-
- if (pNv->i2cMap[i].dac != -1)
- dac = NV50CreateDac(pScrn, pNv->i2cMap[i].dac);
- if (pNv->i2cMap[i].sor != -1)
- sor = NV50CreateSor(pScrn, pNv->i2cMap[i].sor, OUTPUT_TMDS);
-
- if (dac) {
- NVOutputPrivatePtr nv_output = dac->driver_private;
-
- nv_output->pDDCBus = i2c;
- nv_output->scaling_mode = SCALE_PANEL;
- }
- if (sor) {
- NVOutputPrivatePtr nv_output = sor->driver_private;
-
- nv_output->pDDCBus = i2c;
- nv_output->scaling_mode = SCALE_ASPECT;
- }
- }
-
- if (pNv->lvds.present) {
- xf86OutputPtr lvds = NV50CreateSor(pScrn, pNv->lvds.or, OUTPUT_LVDS);
- NVOutputPrivatePtr nv_output = lvds->driver_private;
-
- nv_output->scaling_mode = SCALE_ASPECT;
- }
-
- /* For each output, set the crtc and clone masks */
- for(i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr output = xf86_config->output[i];
-
- /* Any output can connect to any head */
- output->possible_crtcs = 0x3;
- output->possible_clones = 0;
- }
-
- return TRUE;
-}
-
diff --git a/src/nv50_output.h b/src/nv50_output.h
index 53b913f..67f3deb 100644
--- a/src/nv50_output.h
+++ b/src/nv50_output.h
@@ -10,15 +10,18 @@ void NV50OutputPrepare(xf86OutputPtr);
void NV50OutputCommit(xf86OutputPtr);
DisplayModePtr NV50OutputGetDDCModes(xf86OutputPtr);
void NV50OutputDestroy(xf86OutputPtr);
-Bool NV50CreateOutputs(ScrnInfoPtr);
/* nv50_dac.c */
xf86OutputPtr NV50CreateDac(ScrnInfoPtr, ORNum);
Bool NV50DacLoadDetect(xf86OutputPtr);
void NV50DacSetPClk(xf86OutputPtr output, int pclk);
+const xf86OutputFuncsRec * nv50_get_analog_output_funcs();
/* nv50_sor.c */
xf86OutputPtr NV50CreateSor(ScrnInfoPtr pScrn, ORNum or, NVOutputType type);
void NV50SorSetPClk(xf86OutputPtr output, int pclk);
+const xf86OutputFuncsRec * nv50_get_tmds_output_funcs();
+const xf86OutputFuncsRec * nv50_get_lvds_output_funcs();
+DisplayModePtr GetLVDSNativeMode(ScrnInfoPtr pScrn);
#endif
diff --git a/src/nv50_sor.c b/src/nv50_sor.c
index a04d928..4f408e5 100644
--- a/src/nv50_sor.c
+++ b/src/nv50_sor.c
@@ -252,150 +252,6 @@ NV50SorGetLVDSModes(xf86OutputPtr output)
return xf86DuplicateMode(nv_output->native_mode);
}
-#define MAKE_ATOM(a) MakeAtom((a), sizeof(a) - 1, TRUE);
-
-struct property {
- Atom atom;
- INT32 range[2];
-};
-
-static struct {
- struct property dither;
- struct property scale;
-} properties;
-
-static void
-NV50SorCreateResources(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- NVPtr pNv = NVPTR(pScrn);
- int data, err;
- const char *s;
-
- /******** dithering ********/
- properties.dither.atom = MAKE_ATOM("dither");
- properties.dither.range[0] = 0;
- properties.dither.range[1] = 1;
- err = RRConfigureOutputProperty(output->randr_output,
- properties.dither.atom, FALSE, TRUE, FALSE,
- 2, properties.dither.range);
- if(err)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to configure dithering property for %s: error %d\n",
- output->name, err);
-
- // Set the default value
- data = pNv->FPDither;
- err = RRChangeOutputProperty(output->randr_output, properties.dither.atom,
- XA_INTEGER, 32, PropModeReplace, 1, &data,
- FALSE, FALSE);
- if(err)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to set dithering property for %s: error %d\n",
- output->name, err);
-
- /******** scaling ********/
- properties.scale.atom = MAKE_ATOM("scale");
- err = RRConfigureOutputProperty(output->randr_output,
- properties.scale.atom, FALSE, FALSE,
- FALSE, 0, NULL);
- if(err)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to configure scaling property for %s: error %d\n",
- output->name, err);
-
- // Set the default value
- s = "aspect";
- err = RRChangeOutputProperty(output->randr_output, properties.scale.atom,
- XA_STRING, 8, PropModeReplace, strlen(s),
- (pointer)s, FALSE, FALSE);
- if(err)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to set scaling property for %s: error %d\n",
- output->name, err);
-}
-
-static Bool
-NV50SorSetProperty(xf86OutputPtr output, Atom prop, RRPropertyValuePtr val)
-{
- NVOutputPrivatePtr nv_output = output->driver_private;
-
- if(prop == properties.dither.atom) {
- INT32 i;
-
- if (val->type != XA_INTEGER || val->format != 32 || val->size != 1)
- return FALSE;
-
- i = *(INT32*)val->data;
- if (i < properties.dither.range[0] || i > properties.dither.range[1])
- return FALSE;
-
- NV50CrtcSetDither(output->crtc, i, TRUE);
- return TRUE;
- } else if (prop == properties.scale.atom) {
- const char *s;
- enum scaling_modes oldScale, scale;
- int i;
- const struct {
- const char *name;
- enum scaling_modes scale;
- } modes[] = {
- { "panel", SCALE_PANEL },
- { "aspect", SCALE_ASPECT },
- { "fullscreen", SCALE_FULLSCREEN },
- { "noscale", SCALE_NOSCALE },
- { NULL, 0 },
- };
-
- if (val->type != XA_STRING || val->format != 8)
- return FALSE;
- s = (char*)val->data;
-
- for (i = 0; modes[i].name; i++) {
- const char *name = modes[i].name;
- const int len = strlen(name);
-
- if(val->size == len && !strncmp(name, s, len)) {
- scale = modes[i].scale;
- break;
- }
- }
- if (!modes[i].name)
- return FALSE;
- if (scale == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
- // LVDS requires scaling
- return FALSE;
-
- oldScale = nv_output->scaling_mode;
- nv_output->scaling_mode = scale;
- if (output->crtc) {
- xf86CrtcPtr crtc = output->crtc;
-
- if (!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation,
- crtc->desiredX, crtc->desiredY)) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "Failed to set scaling to %s for output %s\n",
- modes[i].name, output->name);
-
- // Restore old scale and try again.
- nv_output->scaling_mode = oldScale;
- if (!xf86CrtcSetMode(crtc, &crtc->desiredMode,
- crtc->desiredRotation, crtc->desiredX,
- crtc->desiredY)) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "Failed to restore old scaling for output %s\n",
- output->name);
- }
-
- return FALSE;
- }
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
static const xf86OutputFuncsRec NV50SorTMDSOutputFuncs = {
.dpms = NV50SorDPMSSet,
.save = NULL,
@@ -407,8 +263,8 @@ static const xf86OutputFuncsRec NV50SorTMDSOutputFuncs = {
.mode_set = NV50SorModeSet,
.detect = NV50SorDetect,
.get_modes = NV50OutputGetDDCModes,
- .create_resources = NV50SorCreateResources,
- .set_property = NV50SorSetProperty,
+ .create_resources = nv_digital_output_create_resources,
+ .set_property = nv_digital_output_set_property,
.destroy = NV50SorDestroy,
};
@@ -423,11 +279,21 @@ static const xf86OutputFuncsRec NV50SorLVDSOutputFuncs = {
.mode_set = NV50SorModeSet,
.detect = NV50SorLVDSDetect,
.get_modes = NV50SorGetLVDSModes,
- .create_resources = NV50SorCreateResources,
- .set_property = NV50SorSetProperty,
+ .create_resources = nv_digital_output_create_resources,
+ .set_property = nv_digital_output_set_property,
.destroy = NV50SorDestroy,
};
+const xf86OutputFuncsRec * nv50_get_tmds_output_funcs()
+{
+ return &NV50SorTMDSOutputFuncs;
+}
+
+const xf86OutputFuncsRec * nv50_get_lvds_output_funcs()
+{
+ return &NV50SorLVDSOutputFuncs;
+}
+
static DisplayModePtr
ReadLVDSNativeMode(ScrnInfoPtr pScrn, const int off)
{
@@ -454,7 +320,7 @@ ReadLVDSNativeMode(ScrnInfoPtr pScrn, const int off)
return mode;
}
-static DisplayModePtr
+DisplayModePtr
GetLVDSNativeMode(ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
@@ -468,55 +334,3 @@ GetLVDSNativeMode(ScrnInfoPtr pScrn)
return NULL;
}
-
-xf86OutputPtr
-NV50CreateSor(ScrnInfoPtr pScrn, ORNum or, NVOutputType type)
-{
- NVOutputPrivatePtr nv_output = xnfcalloc(sizeof(*nv_output), 1);
- NVPtr pNv = NVPTR(pScrn);
- xf86OutputPtr output;
- char orName[5];
- const xf86OutputFuncsRec *funcs;
-
- if(!nv_output)
- return NULL;
-
- if(type == OUTPUT_LVDS) {
- strcpy(orName, "LVDS");
- funcs = &NV50SorLVDSOutputFuncs;
-
- nv_output->native_mode = GetLVDSNativeMode(pScrn);
-
- if(!nv_output->native_mode) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Failed to find LVDS native mode\n");
- xfree(nv_output);
- return NULL;
- }
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s native size %dx%d\n",
- orName, nv_output->native_mode->HDisplay,
- nv_output->native_mode->VDisplay);
- } else {
- snprintf(orName, 5, "DVI%d", or);
- funcs = &NV50SorTMDSOutputFuncs;
- }
-
- output = xf86OutputCreate(pScrn, funcs, orName);
-
- nv_output->output_resource = or;
- nv_output->type = type;
- output->driver_private = nv_output;
- output->interlaceAllowed = TRUE;
- output->doubleScanAllowed = TRUE;
-
- if (type != OUTPUT_LVDS) {
- NVWrite(pNv, 0x0061c00c + nv_output->output_resource * 0x800, 0x03010700);
- NVWrite(pNv, 0x0061c010 + nv_output->output_resource * 0x800, 0x0000152f);
- NVWrite(pNv, 0x0061c014 + nv_output->output_resource * 0x800, 0x00000000);
- NVWrite(pNv, 0x0061c018 + nv_output->output_resource * 0x800, 0x00245af8);
- }
-
- return output;
-}
-
diff --git a/src/nv50reg.h b/src/nv50reg.h
index 70a2656..44fa8c5 100644
--- a/src/nv50reg.h
+++ b/src/nv50reg.h
@@ -30,36 +30,92 @@
#define NV50_CRTC_VPLL2_A 0x00614904
#define NV50_CRTC_VPLL2_B 0x00614908
+/* Clamped to 256 MiB */
+#define NV50_CRTC0_RAM_AMOUNT 0x00610384
+#define NV50_CRTC1_RAM_AMOUNT 0x00610784
+
/* These things below are so called "commands" */
+#define NV50_UPDATE_DISPLAY 0x80
+
#define NV50_CRTC0_CLOCK 0x804
-#define NV50_CRTC1_CLOCK 0xC04
#define NV50_CRTC0_INTERLACE 0x808
-#define NV50_CRTC1_INTERLACE 0xC08
#define NV50_CRTC0_HBLANK_START 0x814
#define NV50_CRTC0_HSYNC_END 0x818
#define NV50_CRTC0_HBLANK_END 0x81C
#define NV50_CRTC0_HTOTAL 0x820
+/* You can't have a palette in 8 bit mode (=OFF) */
+#define NV50_CRTC0_CLUT_MODE 0x840
+ #define NV50_CRTC0_CLUT_MODE_BLANK 0x00000000
+ #define NV50_CRTC0_CLUT_MODE_OFF 0x80000000
+ #define NV50_CRTC0_CLUT_MODE_ON 0xC0000000
+#define NV50_CRTC0_CLUT_OFFSET 0x844
+
+/* Anyone know what part of the chip is triggered here precisely? */
+#define NV84_CRTC0_BLANK_UNK1 0x85C
+ #define NV84_CRTC0_BLANK_UNK1_BLANK 0x0
+ #define NV84_CRTC0_BLANK_UNK1_UNBLANK 0x1
+
+#define NV50_CRTC0_FB_OFFSET 0x860
+
+#define NV50_CRTC0_FB_SIZE 0x868
+#define NV50_CRTC0_PITCH 0x86C
+
+#define NV50_CRTC0_DEPTH 0x870
+ #define NV50_CRTC0_DEPTH_8BPP 0x1E00
+ #define NV50_CRTC0_DEPTH_15BPP 0xE900
+ #define NV50_CRTC0_DEPTH_16BPP 0xE800
+ #define NV50_CRTC0_DEPTH_24BPP 0xCF00
+
+/* I'm openminded to better interpretations. */
+/* This is an educated guess. */
+/* NV50 has RAMDAC and TMDS offchip, so it's unlikely to be that. */
+#define NV50_CRTC0_BLANK_CTRL 0x874
+ #define NV50_CRTC0_BLANK_CTRL_BLANK 0x0
+ #define NV50_CRTC0_BLANK_CTRL_UNBLANK 0x1
+
+#define NV50_CRTC0_CURSOR 0x880
+ #define NV50_CRTC0_CURSOR_SHOW 0x85000000
+ #define NV50_CRTC0_CURSOR_HIDE 0x05000000
+
+#define NV50_CRTC0_CURSOR_OFFSET 0x884
+
+/* Anyone know what part of the chip is triggered here precisely? */
+#define NV84_CRTC0_BLANK_UNK2 0x89C
+ #define NV84_CRTC0_BLANK_UNK2_BLANK 0x0
+ #define NV84_CRTC0_BLANK_UNK2_UNBLANK 0x1
+
+#define NV50_CRTC0_DITHERING_CTRL 0x8A0
+ #define NV50_CRTC0_DITHERING_CTRL_ON 0x11
+ #define NV50_CRTC0_DITHERING_CTRL_OFF 0x0
+
+#define NV50_CRTC0_FB_POS 0x8C0
+#define NV50_CRTC0_SCRN_SIZE 0x8C8
+
+#define NV50_CRTC1_CLOCK 0xC04
+#define NV50_CRTC1_INTERLACE 0xC08
+
#define NV50_CRTC1_HBLANK_START 0xC14
#define NV50_CRTC1_HSYNC_END 0xC18
#define NV50_CRTC1_HBLANK_END 0xC1C
#define NV50_CRTC1_HTOTAL 0xC20
-#define NV50_CRTC0_FB_SIZE 0x868
+#define NV50_CRTC1_CLUT_MODE 0xC40
+ #define NV50_CRTC1_CLUT_MODE_BLANK 0x00000000
+ #define NV50_CRTC1_CLUT_MODE_OFF 0x80000000
+ #define NV50_CRTC1_CLUT_MODE_ON 0xC0000000
+#define NV50_CRTC1_CLUT_OFFSET 0xC44
+
+/* Anyone know what part of the chip is triggered here precisely? */
+#define NV84_CRTC1_BLANK_UNK1 0xC5C
+ #define NV84_CRTC1_BLANK_UNK1_BLANK 0x0
+ #define NV84_CRTC1_BLANK_UNK1_UNBLANK 0x1
+
+#define NV50_CRTC1_FB_OFFSET 0xC60
+
#define NV50_CRTC1_FB_SIZE 0xC68
-#define NV50_CRTC0_PITCH 0x86C
#define NV50_CRTC1_PITCH 0xC6C
-#define NV50_CRTC0_FB_POS 0x8C0
-#define NV50_CRTC1_FB_POS 0xCC0
-#define NV50_CRTC0_SCRN_SIZE 0x8C8
-#define NV50_CRTC1_SCRN_SIZE 0xCC8
-
-#define NV50_CRTC0_DEPTH 0x870
-#define NV50_CRTC0_DEPTH_8BPP 0x1E00
-#define NV50_CRTC0_DEPTH_15BPP 0xE900
-#define NV50_CRTC0_DEPTH_16BPP 0xE800
-#define NV50_CRTC0_DEPTH_24BPP 0xCF00
#define NV50_CRTC1_DEPTH 0xC70
#define NV50_CRTC1_DEPTH_8BPP 0x1E00
@@ -67,35 +123,27 @@
#define NV50_CRTC1_DEPTH_16BPP 0xE800
#define NV50_CRTC1_DEPTH_24BPP 0xCF00
-#define NV50_CRTC0_FB_OFFSET 0x860
-#define NV50_CRTC1_FB_OFFSET 0xC60
+/* I'm openminded to better interpretations. */
+#define NV50_CRTC1_BLANK_CTRL 0xC74
+ #define NV50_CRTC1_BLANK_CTRL_BLANK 0x0
+ #define NV50_CRTC1_BLANK_CTRL_UNBLANK 0x1
-#define NV50_CRTC0_CURSOR_OFFSET 0x884
-#define NV50_CRTC1_CURSOR_OFFSET 0xC84
+#define NV50_CRTC1_CURSOR 0xC80
+ #define NV50_CRTC1_CURSOR_SHOW 0x85000000
+ #define NV50_CRTC1_CURSOR_HIDE 0x05000000
-/* You can't have a palette in 8 bit mode (=OFF) */
-#define NV50_CRTC0_CLUT_MODE 0x840
- #define NV50_CRTC0_CLUT_MODE_BLANK 0x00000000
- #define NV50_CRTC0_CLUT_MODE_OFF 0x80000000
- #define NV50_CRTC0_CLUT_MODE_ON 0xC0000000
-#define NV50_CRTC0_CLUT_OFFSET 0x844
-
-#define NV50_CRTC1_CLUT_MODE 0xC40
- #define NV50_CRTC1_CLUT_MODE_BLANK 0x00000000
- #define NV50_CRTC1_CLUT_MODE_OFF 0x80000000
- #define NV50_CRTC1_CLUT_MODE_ON 0xC0000000
-#define NV50_CRTC1_CLUT_OFFSET 0xC44
+#define NV50_CRTC1_CURSOR_OFFSET 0xC84
-/* Clamped to 256 MiB */
-#define NV50_CRTC0_RAM_AMOUNT 0x00610384
-#define NV50_CRTC1_RAM_AMOUNT 0x00610784
+/* Anyone know what part of the chip is triggered here precisely? */
+#define NV84_CRTC1_BLANK_UNK2 0xC9C
+ #define NV84_CRTC1_BLANK_UNK2_BLANK 0x0
+ #define NV84_CRTC1_BLANK_UNK2_UNBLANK 0x1
-#define NV50_CRTC0_CURSOR0 0x880
- #define NV50_CRTC0_CURSOR0_SHOW 0x85000000
- #define NV50_CRTC0_CURSOR0_HIDE 0x05000000
+#define NV50_CRTC1_DITHERING_CTRL 0xCA0
+ #define NV50_CRTC1_DITHERING_CTRL_ON 0x11
+ #define NV50_CRTC1_DITHERING_CTRL_OFF 0x0
-#define NV50_CRTC1_CURSOR0 0xC80
- #define NV50_CRTC1_CURSOR0_SHOW 0x85000000
- #define NV50_CRTC1_CURSOR0_HIDE 0x05000000
+#define NV50_CRTC1_FB_POS 0xCC0
+#define NV50_CRTC1_SCRN_SIZE 0xCC8
#endif /* __NV50REG_H_ */
diff --git a/src/nv_crtc.c b/src/nv_crtc.c
index 83bf3df..2d8e23c 100644
--- a/src/nv_crtc.c
+++ b/src/nv_crtc.c
@@ -102,7 +102,7 @@ void NVCrtcLockUnlock(xf86CrtcPtr crtc, Bool lock)
NVLockVgaCrtc(pNv, nv_crtc->head, lock);
}
-static xf86OutputPtr
+xf86OutputPtr
NVGetOutputFromCRTC(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
@@ -1228,8 +1228,8 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP
/* Flatpanel support needs at least a NV10 */
if (pNv->twoHeads) {
- if (pNv->FPDither || (is_lvds && !pNv->VBIOS.fp.if_is_24bit)) {
- nv_crtc->ditherEnabled = TRUE;
+ /* Output property. */
+ if (nv_output && nv_output->dithering) {
if (pNv->NVArch == 0x11)
regp->dither = savep->dither | 0x00010000;
else {
@@ -1241,7 +1241,14 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP
}
}
} else {
- nv_crtc->ditherEnabled = FALSE;
+ if (pNv->NVArch != 0x11) {
+ /* reset them */
+ int i;
+ for (i = 0; i < 3; i++) {
+ regp->dither_regs[i] = savep->dither_regs[i];
+ regp->dither_regs[i + 3] = savep->dither_regs[i + 3];
+ }
+ }
regp->dither = savep->dither;
}
}
@@ -1744,7 +1751,9 @@ nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
NVCrtcRegPtr regp = &pNv->ModeReg.crtc_reg[crtc_num];
int i;
- if (pNv->NVArch >= 0x11)
+ if (pNv->Architecture == NV_ARCH_50)
+ crtc = xf86CrtcCreate(pScrn, nv50_get_crtc_funcs());
+ else if (pNv->NVArch >= 0x11)
crtc = xf86CrtcCreate(pScrn, &nv11_crtc_funcs);
else
crtc = xf86CrtcCreate(pScrn, &nv_crtc_funcs);
@@ -1754,10 +1763,12 @@ nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
nv_crtc = xnfcalloc (sizeof (NVCrtcPrivateRec), 1);
nv_crtc->head = crtc_num;
nv_crtc->last_dpms = NV_DPMS_CLEARED;
- nv_crtc->ditherEnabled = pNv->FPDither;
crtc->driver_private = nv_crtc;
+ if (pNv->Architecture == NV_ARCH_50)
+ return;
+
/* Initialise the default LUT table. */
for (i = 0; i < 256; i++) {
regp->DAC[i*3] = i;
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 79a479a..03d153b 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -1424,23 +1424,19 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
NVCommonSetup(pScrn);
if (pNv->randr12_enable) {
- if (pNv->Architecture < NV_ARCH_50) {
- NVI2CInit(pScrn);
-
- num_crtc = pNv->twoHeads ? 2 : 1;
- for (i = 0; i < num_crtc; i++) {
- nv_crtc_init(pScrn, i);
- }
-
- NvSetupOutputs(pScrn);
- } else {
+ if (pNv->Architecture == NV_ARCH_50)
if (!NV50DispPreInit(pScrn))
NVPreInitFail("\n");
- if (!NV50CreateOutputs(pScrn))
- NVPreInitFail("\n");
- NV50DispCreateCrtcs(pScrn);
+
+ NVI2CInit(pScrn);
+
+ num_crtc = pNv->twoHeads ? 2 : 1;
+ for (i = 0; i < num_crtc; i++) {
+ nv_crtc_init(pScrn, i);
}
+ NvSetupOutputs(pScrn);
+
if (!xf86InitialConfiguration(pScrn, FALSE))
NVPreInitFail("No valid modes.\n");
}
diff --git a/src/nv_i2c.c b/src/nv_i2c.c
index 8da2ca5..7b2aa49 100644
--- a/src/nv_i2c.c
+++ b/src/nv_i2c.c
@@ -46,10 +46,30 @@ NVI2CPutBits(I2CBusPtr b, int clock, int data)
NVWriteVgaCrtc(pNv, 0, b->DriverPrivate.uval + 1, val | 0x1);
}
+static void NV50_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
+ const int off = b->DriverPrivate.val * 0x18;
+
+ NVWrite(pNv, (0x0000E138+off)/4, (4 | clock | data << 1));
+}
+
+static void NV50_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
+ const int off = b->DriverPrivate.val * 0x18;
+ unsigned char val;
+
+ val = NVRead(pNv, (0x0000E138+off)/4);
+ *clock = !!(val & 1);
+ *data = !!(val & 2);
+}
+
Bool
NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
{
I2CBusPtr pI2CBus;
+ NVPtr pNv = NVPTR(pScrn);
pI2CBus = xf86CreateI2CBusRec();
if(!pI2CBus)
@@ -57,9 +77,20 @@ NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
pI2CBus->BusName = name;
pI2CBus->scrnIndex = pScrn->scrnIndex;
- pI2CBus->I2CPutBits = NVI2CPutBits;
- pI2CBus->I2CGetBits = NVI2CGetBits;
- pI2CBus->AcknTimeout = 5;
+ if (pNv->Architecture == NV_ARCH_50) {
+ pI2CBus->I2CPutBits = NV50_I2CPutBits;
+ pI2CBus->I2CGetBits = NV50_I2CGetBits;
+ /* Could this be used for the rest as well? */
+ pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+ pI2CBus->StartTimeout = 550;
+ pI2CBus->BitTimeout = 40;
+ pI2CBus->ByteTimeout = 40;
+ pI2CBus->AcknTimeout = 40;
+ } else {
+ pI2CBus->I2CPutBits = NVI2CPutBits;
+ pI2CBus->I2CGetBits = NVI2CGetBits;
+ pI2CBus->AcknTimeout = 5;
+ }
pI2CBus->DriverPrivate.uval = i2c_reg;
diff --git a/src/nv_output.c b/src/nv_output.c
index cb26c62..cea4bfd 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -738,6 +738,10 @@ static const struct {
};
static Atom scaling_mode_atom;
+#define DITHERING_MODE_NAME "DITHERING"
+static Atom dithering_atom;
+int32_t dithering_range[2];
+
static int
nv_scaling_mode_lookup(char *name, int size)
{
@@ -756,7 +760,7 @@ nv_scaling_mode_lookup(char *name, int size)
return scaling_mode[i].mode;
}
-static void
+void
nv_digital_output_create_resources(xf86OutputPtr output)
{
NVOutputPrivatePtr nv_output = output->driver_private;
@@ -791,9 +795,35 @@ nv_digital_output_create_resources(xf86OutputPtr output)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to set scaling mode, %d\n", error);
}
+
+ /*
+ * Setup dithering property.
+ */
+ dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE);
+
+ dithering_range[0] = 0;
+ dithering_range[1] = 1;
+
+ error = RRConfigureOutputProperty(output->randr_output,
+ dithering_atom, TRUE, TRUE, FALSE,
+ 2, dithering_range);
+
+ if (error != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", error);
+ }
+
+ error = RRChangeOutputProperty(output->randr_output, dithering_atom,
+ XA_INTEGER, 32, PropModeReplace, 1, &nv_output->dithering,
+ FALSE, FALSE);
+
+ if (error != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to set dithering mode, %d\n", error);
+ }
}
-static Bool
+Bool
nv_digital_output_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
{
@@ -819,6 +849,17 @@ nv_digital_output_set_property(xf86OutputPtr output, Atom property,
nv_output->scaling_mode = ret;
return TRUE;
+ } else if (property == dithering_atom) {
+ if (value->type != XA_INTEGER || value->format != 32)
+ return FALSE;
+
+ int32_t val = *(int32_t *) value->data;
+
+ if (val < dithering_range[0] || val > dithering_range[1])
+ return FALSE;
+
+ nv_output->dithering = val;
+ return TRUE;
}
return TRUE;
@@ -964,20 +1005,19 @@ static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFunc
output->driver_private = nv_output;
+ /* needed for NV5x, used by pre-NV5x as well. */
+ nv_output->output_resource = ffs(pNv->dcb_table.entry[dcb_entry].or);
+
nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
nv_output->dcb_entry = dcb_entry;
nv_output->type = pNv->dcb_table.entry[dcb_entry].type;
nv_output->last_dpms = NV_DPMS_CLEARED;
- /* output route:
- * bit0: OUTPUT_0 valid
- * bit1: OUTPUT_1 valid
- * So lowest order has highest priority.
- * Below is guesswork:
- * bit2: All outputs valid
- */
- /* We choose the preferred output resource initially. */
- if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1)
+ /* Output property for tmds and lvds. */
+ nv_output->dithering = (pNv->FPDither || (nv_output->type == OUTPUT_LVDS && !pNv->VBIOS.fp.if_is_24bit));
+
+ /* This is mostly for tmds/lvds routing on pre-NV5x cards. */
+ if (nv_output->output_resource & OUTPUT_1)
nv_output->preferred_output = 1;
else
nv_output->preferred_output = 0;
@@ -996,16 +1036,69 @@ static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFunc
}
output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
+ output->interlaceAllowed = TRUE;
+ output->doubleScanAllowed = TRUE;
+
+ if (pNv->Architecture == NV_ARCH_50) {
+ if (nv_output->type == OUTPUT_TMDS) {
+ NVWrite(pNv, 0x0061c00c + nv_output->output_resource * 0x800, 0x03010700);
+ NVWrite(pNv, 0x0061c010 + nv_output->output_resource * 0x800, 0x0000152f);
+ NVWrite(pNv, 0x0061c014 + nv_output->output_resource * 0x800, 0x00000000);
+ NVWrite(pNv, 0x0061c018 + nv_output->output_resource * 0x800, 0x00245af8);
+ }
+
+ /* This needs to be handled in the same way as pre-NV5x on the long run. */
+ if (nv_output->type == OUTPUT_LVDS)
+ nv_output->native_mode = GetLVDSNativeMode(pScrn);
+ }
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Added output %s\n", outputname);
}
+static const xf86OutputFuncsRec * nv_get_output_funcs(ScrnInfoPtr pScrn, int type)
+{
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (pNv->Architecture == NV_ARCH_50) {
+ switch (type) {
+ case OUTPUT_ANALOG:
+ return nv50_get_analog_output_funcs();
+ break;
+ case OUTPUT_TMDS:
+ return nv50_get_tmds_output_funcs();
+ break;
+ case OUTPUT_LVDS:
+ return nv50_get_lvds_output_funcs();
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ } else {
+ switch (type) {
+ case OUTPUT_ANALOG:
+ return &nv_analog_output_funcs;
+ break;
+ case OUTPUT_TMDS:
+ return &nv_tmds_output_funcs;
+ break;
+ case OUTPUT_LVDS:
+ return &nv_lvds_output_funcs;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+}
+
void NvSetupOutputs(ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
int i, type, i2c_count[0xf];
char outputname[20];
int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
+ xf86OutputFuncsRec * funcs = NULL;
memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
memset(i2c_count, 0, sizeof(i2c_count));
@@ -1024,24 +1117,24 @@ void NvSetupOutputs(ScrnInfoPtr pScrn)
sprintf(outputname, "VGA-%d", vga_count++);
else
sprintf(outputname, "DVI-A-%d", dvia_count++);
- nv_add_output(pScrn, i, &nv_analog_output_funcs, outputname);
break;
case OUTPUT_TMDS:
sprintf(outputname, "DVI-D-%d", dvid_count++);
- nv_add_output(pScrn, i, &nv_tmds_output_funcs, outputname);
break;
case OUTPUT_TV:
sprintf(outputname, "TV-%d", tv_count++);
-// nv_add_output(pScrn, i, &nv_tv_output_funcs, outputname);
break;
case OUTPUT_LVDS:
sprintf(outputname, "LVDS-%d", lvds_count++);
- nv_add_output(pScrn, i, &nv_lvds_output_funcs, outputname);
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
break;
}
+
+ funcs = (xf86OutputFuncsRec *) nv_get_output_funcs(pScrn, type);
+ if (funcs)
+ nv_add_output(pScrn, i, funcs, outputname);
}
}
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 71eb50e..857058c 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -87,10 +87,13 @@ void nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num);
void NVCrtcLockUnlock(xf86CrtcPtr crtc, Bool lock);
void NVCrtcWriteCRTC(xf86CrtcPtr crtc, uint32_t reg, uint32_t val);
void NVCrtcWriteRAMDAC(xf86CrtcPtr crtc, uint32_t reg, uint32_t val);
+xf86OutputPtr NVGetOutputFromCRTC(xf86CrtcPtr crtc);
/* nv_output.c */
void NvSetupOutputs(ScrnInfoPtr pScrn);
uint32_t nv_get_clock_from_crtc(ScrnInfoPtr pScrn, RIVA_HW_STATE *state, uint8_t crtc);
+void nv_digital_output_create_resources(xf86OutputPtr output);
+Bool nv_digital_output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
/* nv_hw.c */
uint32_t NVRead(NVPtr pNv, uint32_t reg);
diff --git a/src/nv_type.h b/src/nv_type.h
index 13d7803..e2eab41 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -187,7 +187,6 @@ typedef struct _NVCrtcPrivateRec {
int head;
uint8_t last_dpms;
Bool cursorVisible;
- Bool ditherEnabled;
Bool skipModeFixup; /* NV50 only */
int pclk; /* Pixel clock in kHz */ /* NV50 only */
#if NOUVEAU_EXA_PIXMAPS
@@ -213,6 +212,7 @@ typedef struct _NVOutputPrivateRec {
uint32_t fpHeight;
DisplayModePtr native_mode;
uint8_t scaling_mode;
+ Bool dithering;
NVOutputRegRec restore;
} NVOutputPrivateRec, *NVOutputPrivatePtr;
_______________________________________________
Nouveau mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/nouveau