From 139d33ac807fb0fc35c37c3689a6e80238199442 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Feb 2006 13:46:30 -0800 Subject: [PATCH 001/257] Initial add of native CRT modesetting code. --- TODO | 1 + src/Makefile.am | 2 + src/i810_reg.h | 24 ++++ src/i830_display.c | 347 +++++++++++++++++++++++++++++++++++++++++++++ src/i830_display.h | 1 + src/i830_driver.c | 13 +- 6 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 TODO create mode 100644 src/i830_display.c create mode 100644 src/i830_display.h diff --git a/TODO b/TODO new file mode 100644 index 00000000..0dcae975 --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +- licensing of new files diff --git a/src/Makefile.am b/src/Makefile.am index c64c2036..16e9812b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,8 @@ i810_drv_la_SOURCES = \ i830_common.h \ i830_cursor.c \ i830_dga.c \ + i830_display.c \ + i830_display.h \ i830_driver.c \ i830.h \ i830_io.c \ diff --git a/src/i810_reg.h b/src/i810_reg.h index e52375f8..8afe855d 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -660,8 +660,32 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DPLL_A 0x06014 #define DPLL_B 0x06018 +# define DPLL_VCO_ENABLE (1 << 31) +# define DPLL_DVO_HIGH_SPEED (1 << 30) +# define DPLL_SYNCLOCK_ENABLE (1 << 29) +# define DPLL_VGA_MODE_DIS (1 << 28) +# define DPLLB_MODE_DAC_SERIAL (1 << 26) +# define DPLLB_MODE_LVDS (2 << 26) +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) +# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) +# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) +# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 +# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 +# define PLL_REF_INPUT_DREFCLK (0 << 13) +# define PLL_REF_INPUT_TVCLKIN (2 << 13) +# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +# define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +# define SDVO_MULTIPLIER_MASK 0x000000ff +# define SDV0_DEFAULT_MULTIPLIER 0x00000003 + #define FPA0 0x06040 #define FPA1 0x06044 +#define FPB0 0x06048 +#define FPB1 0x0604c +# define FP_N_DIV_MASK 0x003f0000 +# define FP_M1_DIV_MASK 0x00003f00 +# define FP_M2_DIV_MASK 0x0000003f #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff diff --git a/src/i830_display.c b/src/i830_display.c new file mode 100644 index 00000000..340a51b1 --- /dev/null +++ b/src/i830_display.c @@ -0,0 +1,347 @@ +#include "xf86.h" +#include "xf86_ansic.h" +#include "i830.h" + +static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) +{ + return (refclk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2); +} + +static void +i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) +{ + int dotclock; + + dotclock = i830_clock(refclk, m1, m2, n, p1, p2); + + ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock, + m1, m2, n, p1, p2); +} + +static Bool +i830PllIsValid(int refclk, int m1, int m2, int n, int p1, int p2) +{ + int p, m, vco, dotclock; + + p = p1 + p2; + m = 5 * (m1 + 2) + (m2 + 2); + vco = refclk * m / (n + 2); + dotclock = i830_clock(refclk, m1, m2, n, p1, p2); + + if (p1 < 1 || p1 > 8) + return FALSE; + if (p < 5 || p > 80) /* XXX: 7-98 for LVDS */ + return FALSE; + if (m2 < 5 || m2 > 9) + return FALSE; + if (m1 < 10 || m1 > 20) + return FALSE; + if (m1 <= m2) + return FALSE; + if (m < 70 || m > 120) + return FALSE; + if (n + 2 < 3 || n + 2 > 8) /*XXX: Is the +2 right? */ + return FALSE; + if (vco < 1400000 || vco > 2800000) + return FALSE; + /* XXX: We may need to be checking "Dot clock" depending on the multiplier, + * output, etc., rather than just a single range. + */ + if (dotclock < 20000 || dotclock > 400000) + return FALSE; + + return TRUE; +} + +#if 0 +int +i830ReadAndReportPLL(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp, dpll; + int refclk, m1, m2, n, p1, p2; + + refclk = 96000; /* XXX: The refclk may be 100000 for the LVDS */ + + dpll = INREG(DPLL_A); + switch ((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> 16) { + case 0x01: + p1 = 1; + break; + case 0x02: + p1 = 2; + break; + case 0x04: + p1 = 3; + break; + case 0x08: + p1 = 4; + break; + case 0x10: + p1 = 5; + break; + case 0x20: + p1 = 6; + break; + case 0x40: + p1 = 7; + break; + case 0x80: + p1 = 8; + break; + default: + FatalError("Unknown p1 clock div: 0x%x\n", + dpll & DPLL_FPA01_P1_POST_DIV_MASK); + } + + switch (dpll & DPLL_P2_CLOCK_DIV_MASK) { + case DPLL_DAC_SERIAL_P2_CLOCK_DIV_5: + p2 = 5; + break; + case DPLL_DAC_SERIAL_P2_CLOCK_DIV_10: + p2 = 10; + break; +/* XXX: + case DPLLB_LVDS_P2_CLOCK_DIV_7: + p2 = 7; + break; + case DPLLB_LVDS_P2_CLOCK_DIV_14: + p2 = 14; + break; +*/ + default: + FatalError("Unknown p2 clock div: 0x%x\n", dpll & DPLL_P2_CLOCK_DIV_MASK); + } + + if (dpll & DISPLAY_RATE_SELECT_FPA1) + temp = INREG(FPA1); + else + temp = INREG(FPA0); + n = (temp & FP_N_DIV_MASK) >> 16; + m1 = (temp & FP_M1_DIV_MASK) >> 8; + m2 = (temp & FP_M2_DIV_MASK); + + i830PrintPll("FPA", refclk, m1, m2, n, p1, p2); + ErrorF("clock settings for FPA0 look %s\n", + i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad"); + ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, temp); +} +#endif + +static Bool +i830FindBestPLL(int target, int refclk, int *outm1, int *outm2, int *outn, + int *outp1, int *outp2) +{ + int m1, m2, n, p1, p2; + int err = target; + + if (target < 200000) /* XXX: LVDS */ + p2 = 10; + else + p2 = 5; + for (m1 = 10; m1 <= 20; m1++) { + for (m2 = 5; m2 < 9; m2++) { + for (n = 1; n <= 6; n++) { + for (p1 = 1; p1 <= 8; p1++) { + int clock, this_err; + + if (!i830PllIsValid(refclk, m1, m2, n, p1, p2)) + continue; + + clock = i830_clock(refclk, m1, m2, n, p1, p2); + this_err = abs(clock - target); + if (this_err < err) { + *outm1 = m1; + *outm2 = m2; + *outn = n; + *outp1 = p1; + *outp2 = p2; + err = this_err; + } + } + } + } + } + + return (err != target); +} + +/* + * xf86SetModeCrtc + * + * Copied from xf86Mode.c because it's static there, and i830 likes to hand us + * these hand-rolled modes. + * + * Initialises the Crtc parameters for a mode. The initialisation includes + * adjustments for interlaced and double scan modes. + */ +static void +xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) +{ + if ((p == NULL) /* XXX: || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)*/) + return; + + p->CrtcHDisplay = p->HDisplay; + p->CrtcHSyncStart = p->HSyncStart; + p->CrtcHSyncEnd = p->HSyncEnd; + p->CrtcHTotal = p->HTotal; + p->CrtcHSkew = p->HSkew; + p->CrtcVDisplay = p->VDisplay; + p->CrtcVSyncStart = p->VSyncStart; + p->CrtcVSyncEnd = p->VSyncEnd; + p->CrtcVTotal = p->VTotal; + if (p->Flags & V_INTERLACE) { + if (adjustFlags & INTERLACE_HALVE_V) { + p->CrtcVDisplay /= 2; + p->CrtcVSyncStart /= 2; + p->CrtcVSyncEnd /= 2; + p->CrtcVTotal /= 2; + } + /* Force interlaced modes to have an odd VTotal */ + /* maybe we should only do this when INTERLACE_HALVE_V is set? */ + p->CrtcVTotal |= 1; + } + + if (p->Flags & V_DBLSCAN) { + p->CrtcVDisplay *= 2; + p->CrtcVSyncStart *= 2; + p->CrtcVSyncEnd *= 2; + p->CrtcVTotal *= 2; + } + if (p->VScan > 1) { + p->CrtcVDisplay *= p->VScan; + p->CrtcVSyncStart *= p->VScan; + p->CrtcVSyncEnd *= p->VScan; + p->CrtcVTotal *= p->VScan; + } + p->CrtcHAdjusted = FALSE; + p->CrtcVAdjusted = FALSE; + + /* + * XXX + * + * The following is taken from VGA, but applies to other cores as well. + */ + p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); + p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); + if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) { + /* + * V Blanking size must be < 127. + * Moving blank start forward is safer than moving blank end + * back, since monitors clamp just AFTER the sync pulse (or in + * the sync pulse), but never before. + */ + p->CrtcVBlankStart = p->CrtcVBlankEnd - 127; + /* + * If VBlankStart is now > VSyncStart move VBlankStart + * to VSyncStart using the maximum width that fits into + * VTotal. + */ + if (p->CrtcVBlankStart > p->CrtcVSyncStart) { + p->CrtcVBlankStart = p->CrtcVSyncStart; + p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal); + } + } + p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); + p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); + + if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) { + /* + * H Blanking size must be < 63*8. Same remark as above. + */ + p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8; + if (p->CrtcHBlankStart > p->CrtcHSyncStart) { + p->CrtcHBlankStart = p->CrtcHSyncStart; + p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal); + } + } +} + +void +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + int m1, m2, n, p1, p2; + CARD32 dpll = 0, fp = 0, temp; + CARD32 htot, hblank, hsync, vtot, vblank, vsync; + CARD32 pipesrc, dspsize; + Bool ok; + int refclk = 96000; + + xf86SetModeCrtc(pMode, 0); + + ErrorF("Requested pix clock: %d\n", pMode->Clock); + + ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); + if (!ok) + FatalError("Couldn't find PLL settings for mode!\n"); + + dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; + dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */ + dpll |= (1 << (p1 - 1)) << 16; + if (p2 == 5 || p2 == 7) + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */ + dpll |= SDV0_DEFAULT_MULTIPLIER; + + fp = (n << 16) | (m1 << 8) | m2; + + htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); + hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); + hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16); + vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); + vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); + vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); + pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); + dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + + i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); + ErrorF("clock settings for chosen look %s\n", + i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad"); + ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp); + + /* First, disable display planes */ + temp = INREG(DSPACNTR); + OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); + temp = INREG(DSPBCNTR); + OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + + /* Next, disable display pipes */ + temp = INREG(PIPEACONF); + OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); + temp = INREG(PIPEBCONF); + OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + + /* XXX: Wait for a vblank */ + sleep(1); + + /* Set up display timings and PLLs for the pipe. XXX: Choose pipe! */ + OUTREG(FPA0, fp); + OUTREG(DPLL_A, dpll); + OUTREG(HTOTAL_A, htot); + OUTREG(HBLANK_A, hblank); + OUTREG(HSYNC_A, hsync); + OUTREG(VTOTAL_A, vtot); + OUTREG(VBLANK_A, vblank); + OUTREG(VSYNC_A, vsync); + OUTREG(DSPABASE, 0); /* XXX: Base placed elsewhere? */ + /*OUTREG(DSPASTRIDE, pScrn->displayWidth);*/ + /*OUTREG(DSPAPOS, 0);*/ + OUTREG(PIPEASRC, pipesrc); + OUTREG(DSPASIZE, dspsize); + + /* Turn pipes and planes back on */ + /*if (pI830->planeEnabled[0]) {*/ + temp = INREG(PIPEACONF); + OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE); + temp = INREG(DSPACNTR); + OUTREG(DSPACNTR, temp | DISPLAY_PLANE_ENABLE); + /*} + + if (pI830->planeEnabled[1]) { + temp = INREG(PIPEBCONF); + OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE); + temp = INREG(DSPBCNTR); + OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); + }*/ +} diff --git a/src/i830_display.h b/src/i830_display.h new file mode 100644 index 00000000..6cadd75d --- /dev/null +++ b/src/i830_display.h @@ -0,0 +1 @@ +void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 622565c8..de31b6e0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -181,6 +181,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "vbeModes.h" #include "shadow.h" #include "i830.h" +#include "i830_display.h" #ifdef XF86DRI #include "dri.h" @@ -273,8 +274,10 @@ static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack); static Bool I830BIOSEnterVT(int scrnIndex, int flags); +#if 0 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock *block); +#endif static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); static Bool SetPipeAccess(ScrnInfoPtr pScrn); @@ -3299,6 +3302,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) p = p->next; } while (p != NULL && p != pScrn->modes); + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + pScrn->currentMode = pScrn->modes; #ifndef USE_PITCHES @@ -3891,6 +3896,7 @@ static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock } } +#if 0 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) { @@ -4038,6 +4044,7 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) return ret; } +#endif static Bool I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) @@ -4075,6 +4082,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) SetPipeAccess(pScrn); +#if 0 if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); return FALSE; @@ -4102,6 +4110,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) SetPipeAccess(pScrn); VBESetGetDACPaletteFormat(pVbe, 8); } +#endif /* XXX Fix plane A with pipe A, and plane B with pipe B. */ planeA = INREG(DSPACNTR); @@ -4269,7 +4278,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } } -#if 0 +#if 1 /* Print out some CRTC/display information. */ temp = INREG(HTOTAL_A); ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, @@ -4337,6 +4346,8 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); #endif + i830SetMode(pScrn, pMode); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", pMode->HDisplay * pMode->VDisplay * refresh / 1000000); From 1555229f29fa7479d6a7a51f451d04a5ef3460bd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Feb 2006 13:48:26 -0800 Subject: [PATCH 002/257] Move .cvsignore to .gitignore --- .cvsignore => .gitignore | 0 man/{.cvsignore => .gitignore} | 0 src/{.cvsignore => .gitignore} | 0 src/xvmc/{.cvsignore => .gitignore} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename .cvsignore => .gitignore (100%) rename man/{.cvsignore => .gitignore} (100%) rename src/{.cvsignore => .gitignore} (100%) rename src/xvmc/{.cvsignore => .gitignore} (100%) diff --git a/.cvsignore b/.gitignore similarity index 100% rename from .cvsignore rename to .gitignore diff --git a/man/.cvsignore b/man/.gitignore similarity index 100% rename from man/.cvsignore rename to man/.gitignore diff --git a/src/.cvsignore b/src/.gitignore similarity index 100% rename from src/.cvsignore rename to src/.gitignore diff --git a/src/xvmc/.cvsignore b/src/xvmc/.gitignore similarity index 100% rename from src/xvmc/.cvsignore rename to src/xvmc/.gitignore From 9fe316da7390918dd88940087567314b6f253981 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Feb 2006 13:49:31 -0800 Subject: [PATCH 003/257] Add the manpage's possible names when generated. --- man/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/man/.gitignore b/man/.gitignore index 282522db..77b43621 100644 --- a/man/.gitignore +++ b/man/.gitignore @@ -1,2 +1,4 @@ Makefile Makefile.in +i810.4 +i810.4x From 73496b765c9783a8a271b4774a44fa263dd47684 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 09:26:51 -0800 Subject: [PATCH 004/257] Change an if statement to a more obvious but equivalent case statement. --- src/i830_display.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 340a51b1..0fa0405f 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -279,8 +279,20 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */ dpll |= (1 << (p1 - 1)) << 16; - if (p2 == 5 || p2 == 7) + switch (p2) { + case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; + } dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */ dpll |= SDV0_DEFAULT_MULTIPLIER; From 4955cd267e7f8ed70e90b2a3de6f93de2ef859c8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 09:37:47 -0800 Subject: [PATCH 005/257] Add untested save/restore code, and starting on not using VBEValidateModes --- TODO | 1 + src/i830.h | 32 ++++++++++++++ src/i830_driver.c | 110 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index 0dcae975..ef2bab62 100644 --- a/TODO +++ b/TODO @@ -1 +1,2 @@ - licensing of new files +- Figure out what exactly doublescan, interlace mean, and see if we support them. diff --git a/src/i830.h b/src/i830.h index 11695a20..00d03863 100644 --- a/src/i830.h +++ b/src/i830.h @@ -377,6 +377,38 @@ typedef struct _I830Rec { Bool devicePresence; OsTimerPtr devicesTimer; + + CARD32 saveDSPACNTR; + CARD32 saveDSPBCNTR; + CARD32 savePIPEACONF; + CARD32 savePIPEBCONF; + CARD32 savePIPEASRC; + CARD32 savePIPEBSRC; + CARD32 saveFPA0; + CARD32 saveFPA1; + CARD32 saveDPLL_A; + CARD32 saveHTOTAL_A; + CARD32 saveHBLANK_A; + CARD32 saveHSYNC_A; + CARD32 saveVTOTAL_A; + CARD32 saveVBLANK_A; + CARD32 saveVSYNC_A; + CARD32 saveDSPASTRIDE; + CARD32 saveDSPAPOS; + CARD32 saveDSPABASE; + CARD32 saveFPB0; + CARD32 saveFPB1; + CARD32 saveDPLL_B; + CARD32 saveHTOTAL_B; + CARD32 saveHBLANK_B; + CARD32 saveHSYNC_B; + CARD32 saveVTOTAL_B; + CARD32 saveVBLANK_B; + CARD32 saveVSYNC_B; + CARD32 saveDSPBSTRIDE; + CARD32 saveDSPBPOS; + CARD32 saveDSPBBASE; + } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) diff --git a/src/i830_driver.c b/src/i830_driver.c index de31b6e0..b1beafd0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -697,6 +697,7 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) return i; } +#if 0 static int SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh) { @@ -724,7 +725,6 @@ SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh) return 0; } -#if 0 static Bool SetPowerStatus(ScrnInfoPtr pScrn, int mode) { @@ -2075,6 +2075,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) int DDCclock = 0; char *s; DisplayModePtr p, pMon; + ClockRangePtr clockRanges; pointer pDDCModule = NULL, pVBEModule = NULL; Bool enable; const char *chipname; @@ -3225,6 +3226,20 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) SetPipeAccess(pScrn); VBESetModeNames(pScrn->modePool); +#if 0 + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 12000; /* XXX: Random number */ + clockRanges->maxClock = 400000; /* XXX: May be lower */ + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = TRUE; /* XXX check this */ + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ +#endif + /* * XXX DDC information: There's code in xf86ValidateModes * (VBEValidateModes) to set monitor defaults based on DDC information @@ -3235,12 +3250,23 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* XXX Need to get relevant modes and virtual parameters. */ /* Do the mode validation without regard to special scanline pitches. */ SetPipeAccess(pScrn); +#if 1 n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL, NULL, 0, MAX_DISPLAY_PITCH, 1, 0, MAX_DISPLAY_HEIGHT, pScrn->display->virtualX, pScrn->display->virtualY, memsize, LOOKUP_BEST_REFRESH); +#else + n = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 4096, + pScrn->bitsPerPixel, 128, 4096, + pScrn->display->virtualX, + pScrn->display->virtualY, + pI830->FbMapSize, + LOOKUP_BEST_REFRESH); +#endif if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); @@ -3716,6 +3742,39 @@ SaveHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "SaveHWState\n"); + /* Save video mode information for native mode-setting. */ + pI830->saveDSPACNTR = INREG(DSPACNTR); + pI830->saveDSPBCNTR = INREG(DSPBCNTR); + pI830->savePIPEACONF = INREG(PIPEACONF); + pI830->savePIPEBCONF = INREG(PIPEBCONF); + pI830->savePIPEASRC = INREG(PIPEASRC); + pI830->savePIPEBSRC = INREG(PIPEBSRC); + pI830->saveFPA0 = INREG(FPA0); + pI830->saveFPA1 = INREG(FPA1); + pI830->saveDPLL_A = INREG(DPLL_A); + pI830->saveHTOTAL_A = INREG(HTOTAL_A); + pI830->saveHBLANK_A = INREG(HBLANK_A); + pI830->saveHSYNC_A = INREG(HSYNC_A); + pI830->saveVTOTAL_A = INREG(VTOTAL_A); + pI830->saveVBLANK_A = INREG(VBLANK_A); + pI830->saveVSYNC_A = INREG(VSYNC_A); + pI830->saveDSPASTRIDE = INREG(DSPASTRIDE); + pI830->saveDSPAPOS = INREG(DSPAPOS); + pI830->saveDSPABASE = INREG(DSPABASE); + + pI830->saveFPB0 = INREG(FPB0); + pI830->saveFPB1 = INREG(FPB1); + pI830->saveDPLL_B = INREG(DPLL_B); + pI830->saveHTOTAL_B = INREG(HTOTAL_B); + pI830->saveHBLANK_B = INREG(HBLANK_B); + pI830->saveHSYNC_B = INREG(HSYNC_B); + pI830->saveVTOTAL_B = INREG(VTOTAL_B); + pI830->saveVBLANK_B = INREG(VBLANK_B); + pI830->saveVSYNC_B = INREG(VSYNC_B); + pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); + pI830->saveDSPBPOS = INREG(DSPBPOS); + pI830->saveDSPBBASE = INREG(DSPBBASE); + if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else @@ -3788,6 +3847,7 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaRegPtr vgaReg = &hwp->SavedReg; VESAPtr pVesa; Bool restored = FALSE; + CARD32 temp; DPRINTF(PFX, "RestoreHWState\n"); @@ -3852,6 +3912,54 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); + /* First, disable display planes */ + temp = INREG(DSPACNTR); + OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); + temp = INREG(DSPBCNTR); + OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + + /* Next, disable display pipes */ + temp = INREG(PIPEACONF); + OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); + temp = INREG(PIPEBCONF); + OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + + /* XXX: Wait for a vblank */ + sleep(1); + + OUTREG(FPA0, pI830->saveFPA0); + OUTREG(FPA1, pI830->saveFPA1); + OUTREG(DPLL_A, pI830->saveDPLL_A); + OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); + OUTREG(HBLANK_A, pI830->saveHBLANK_A); + OUTREG(HSYNC_A, pI830->saveHSYNC_A); + OUTREG(VTOTAL_A, pI830->saveVTOTAL_A); + OUTREG(VBLANK_A, pI830->saveVBLANK_A); + OUTREG(VSYNC_A, pI830->saveVSYNC_A); + OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); + OUTREG(DSPAPOS, pI830->saveDSPAPOS); + OUTREG(DSPABASE, pI830->saveDSPABASE); + + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); + OUTREG(DPLL_B, pI830->saveDPLL_B); + OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); + OUTREG(HBLANK_B, pI830->saveHBLANK_B); + OUTREG(HSYNC_B, pI830->saveHSYNC_B); + OUTREG(VTOTAL_B, pI830->saveVTOTAL_B); + OUTREG(VBLANK_B, pI830->saveVBLANK_B); + OUTREG(VSYNC_B, pI830->saveVSYNC_B); + OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); + OUTREG(DSPBPOS, pI830->saveDSPBPOS); + OUTREG(DSPBBASE, pI830->saveDSPBBASE); + + OUTREG(DSPACNTR, pI830->saveDSPACNTR); + OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); + OUTREG(PIPEACONF, pI830->savePIPEACONF); + OUTREG(PIPEBCONF, pI830->savePIPEBCONF); + OUTREG(PIPEASRC, pI830->savePIPEASRC); + OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + return TRUE; } From 767944e3782f9941e9fc72a6705cc3115a6e24ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 13:08:46 -0800 Subject: [PATCH 006/257] Replace a few magic numbers with symbolic names. Reviewed by md5. --- src/i810_reg.h | 7 +++++++ src/i830_driver.c | 32 +++++++++++++++++--------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 8afe855d..7af23e73 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -658,6 +658,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PIPEBSRC 0x6101c #define BCLRPAT_B 0x61020 +#define PP_STATUS 0x61200 +# define PP_ON (1 << 31) + +#define PP_CONTROL 0x61204 +# define POWER_TARGET_ON (1 << 0) + #define DPLL_A 0x06014 #define DPLL_B 0x06018 # define DPLL_VCO_ENABLE (1 << 31) @@ -736,6 +742,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DVOC_SRCDIM 0x61164 #define LVDS 0x61180 +# define LVDS_PORT_EN (1 << 31) #define PIPEACONF 0x70008 #define PIPEACONF_ENABLE (1<<31) diff --git a/src/i830_driver.c b/src/i830_driver.c index b1beafd0..b7d13225 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1061,36 +1061,38 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices) /* Disable LVDS */ if (singlepipe & PIPE_LFP) { /* LFP on PipeA is unlikely! */ - OUTREG(0x61200, INREG(0x61200) & ~0x80000000); - OUTREG(0x61204, INREG(0x61204) & ~0x00000001); - while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1)); + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1)); /* Fix up LVDS */ OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300); /* Enable LVDS */ - OUTREG(0x61200, INREG(0x61200) | 0x80000000); - OUTREG(0x61204, INREG(0x61204) | 0x00000001); - while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1)); + OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); + while (!(INREG(PP_STATUS) & PP_ON) && !(INREG(PP_CONTROL) & 1)); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Enabling LVDS directly. Pipe A.\n"); } else if (singlepipe & (PIPE_LFP << 8)) { - OUTREG(0x61200, INREG(0x61200) & ~0x80000000); - OUTREG(0x61204, INREG(0x61204) & ~0x00000001); - while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1)); + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1)); /* Fix up LVDS */ OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300); /* Enable LVDS */ - OUTREG(0x61200, INREG(0x61200) | 0x80000000); - OUTREG(0x61204, INREG(0x61204) | 0x00000001); - while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1)); + OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); + while (!(INREG(PP_STATUS) & PP_ON) && + !(INREG(PP_CONTROL) & POWER_TARGET_ON)); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Enabling LVDS directly. Pipe B.\n"); } else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) { if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) { - OUTREG(0x61200, INREG(0x61200) & ~0x80000000); - OUTREG(0x61204, INREG(0x61204) & ~0x00000001); - while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1)); + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + while ((INREG(PP_STATUS) & PP_ON) || + (INREG(PP_CONTROL) & POWER_TARGET_ON)); /* Fix up LVDS */ OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, From 9838f639911e8c165ab615fdd9a00e02fa4b3f8a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 14:12:50 -0800 Subject: [PATCH 007/257] Always ErrorF output debugging info when doing BIOS calls, including file/line. --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index bb89dd25..e9debe50 100644 --- a/src/common.h +++ b/src/common.h @@ -101,8 +101,8 @@ extern void I830DPRINTF_stub(const char *filename, int line, /* BIOS debug macro */ #define xf86ExecX86int10_wrapper(pInt, pScrn) do { \ + ErrorF("Executing (ax == 0x%x) BIOS call at %s:%d\n", pInt->ax, __FILE__, __LINE__); \ if (I810_DEBUG & DEBUG_VERBOSE_BIOS) { \ - ErrorF("\n\n\n\nExecuting (ax == 0x%x) BIOS call\n", pInt->ax); \ ErrorF("Checking Error state before execution\n"); \ PrintErrorState(pScrn); \ } \ From 611264ab9b82bca6648a9b27e5ba4b7457c46aa6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 15:44:11 -0800 Subject: [PATCH 008/257] Remove more VBE stuff and start using xf86ValidateModes. Guessed some params to xf86ValidateModes. --- src/i830_driver.c | 84 +++++++++-------------------------------------- 1 file changed, 16 insertions(+), 68 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index b7d13225..2fd391ef 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3197,38 +3197,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) DDCclock = I830UseDDC(pScrn); - /* - * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS - * functions. - */ - pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo); - - if (!pScrn->modePool) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No Video BIOS modes for chosen depth.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - - /* This may look a little weird, but to notify that we're using the - * default hsync/vrefresh we need to unset what we just set ..... - */ - if (defmon & 1) { - pScrn->monitor->hsync[0].lo = 0; - pScrn->monitor->hsync[0].hi = 0; - pScrn->monitor->nHsync = 0; - } - - if (defmon & 2) { - pScrn->monitor->vrefresh[0].lo = 0; - pScrn->monitor->vrefresh[0].hi = 0; - pScrn->monitor->nVrefresh = 0; - } - - SetPipeAccess(pScrn); - VBESetModeNames(pScrn->modePool); - -#if 0 +#if 1 /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. @@ -3249,26 +3218,21 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * there's code in vesa/vesa.c. */ - /* XXX Need to get relevant modes and virtual parameters. */ - /* Do the mode validation without regard to special scanline pitches. */ - SetPipeAccess(pScrn); -#if 1 - n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL, - NULL, 0, MAX_DISPLAY_PITCH, 1, - 0, MAX_DISPLAY_HEIGHT, - pScrn->display->virtualX, - pScrn->display->virtualY, - memsize, LOOKUP_BEST_REFRESH); -#else - n = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, clockRanges, - NULL, 256, 4096, - pScrn->bitsPerPixel, 128, 4096, - pScrn->display->virtualX, - pScrn->display->virtualY, - pI830->FbMapSize, - LOOKUP_BEST_REFRESH); -#endif + /* XXX minPitch, minHeight are random numbers. */ + n = xf86ValidateModes(pScrn, + pScrn->monitor->Modes, /* availModes */ + pScrn->display->modes, /* modeNames */ + clockRanges, /* clockRanges */ + NULL, /* linePitches */ + 256, /* minPitch */ + MAX_DISPLAY_PITCH, /* maxPitch */ + 64, /* pitchInc */ + pScrn->bitsPerPixel, /* minHeight */ + MAX_DISPLAY_HEIGHT, /* maxHeight */ + pScrn->display->virtualX, /* virtualX */ + pScrn->display->virtualY, /* virtualY */ + pI830->FbMapSize, /* apertureSize */ + LOOKUP_BEST_REFRESH /* strategy */); if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); @@ -3314,22 +3278,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - /* Now we check the VESA BIOS's displayWidth and reset if necessary */ - p = pScrn->modes; - do { - VbeModeInfoData *data = (VbeModeInfoData *) p->Private; - VbeModeInfoBlock *modeInfo; - - /* Get BytesPerScanline so we can reset displayWidth */ - if ((modeInfo = VBEGetModeInfo(pI830->pVbe, data->mode))) { - if (pScrn->displayWidth < modeInfo->BytesPerScanline / pI830->cpp) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Correcting stride (%d -> %d)\n", pScrn->displayWidth, modeInfo->BytesPerScanline); - pScrn->displayWidth = modeInfo->BytesPerScanline / pI830->cpp; - } - } - p = p->next; - } while (p != NULL && p != pScrn->modes); - xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); pScrn->currentMode = pScrn->modes; From 2d4415ff1729554537b20be2b6c878444485e406 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Feb 2006 16:57:43 -0800 Subject: [PATCH 009/257] Remove the hacked local xf86SetModeCRTC now that xf86SetCrtcForModes is taking effect on all of our modes. --- src/i830_display.c | 93 ---------------------------------------------- 1 file changed, 93 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 0fa0405f..a09ed60d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -166,97 +166,6 @@ i830FindBestPLL(int target, int refclk, int *outm1, int *outm2, int *outn, return (err != target); } -/* - * xf86SetModeCrtc - * - * Copied from xf86Mode.c because it's static there, and i830 likes to hand us - * these hand-rolled modes. - * - * Initialises the Crtc parameters for a mode. The initialisation includes - * adjustments for interlaced and double scan modes. - */ -static void -xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) -{ - if ((p == NULL) /* XXX: || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)*/) - return; - - p->CrtcHDisplay = p->HDisplay; - p->CrtcHSyncStart = p->HSyncStart; - p->CrtcHSyncEnd = p->HSyncEnd; - p->CrtcHTotal = p->HTotal; - p->CrtcHSkew = p->HSkew; - p->CrtcVDisplay = p->VDisplay; - p->CrtcVSyncStart = p->VSyncStart; - p->CrtcVSyncEnd = p->VSyncEnd; - p->CrtcVTotal = p->VTotal; - if (p->Flags & V_INTERLACE) { - if (adjustFlags & INTERLACE_HALVE_V) { - p->CrtcVDisplay /= 2; - p->CrtcVSyncStart /= 2; - p->CrtcVSyncEnd /= 2; - p->CrtcVTotal /= 2; - } - /* Force interlaced modes to have an odd VTotal */ - /* maybe we should only do this when INTERLACE_HALVE_V is set? */ - p->CrtcVTotal |= 1; - } - - if (p->Flags & V_DBLSCAN) { - p->CrtcVDisplay *= 2; - p->CrtcVSyncStart *= 2; - p->CrtcVSyncEnd *= 2; - p->CrtcVTotal *= 2; - } - if (p->VScan > 1) { - p->CrtcVDisplay *= p->VScan; - p->CrtcVSyncStart *= p->VScan; - p->CrtcVSyncEnd *= p->VScan; - p->CrtcVTotal *= p->VScan; - } - p->CrtcHAdjusted = FALSE; - p->CrtcVAdjusted = FALSE; - - /* - * XXX - * - * The following is taken from VGA, but applies to other cores as well. - */ - p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); - p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); - if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) { - /* - * V Blanking size must be < 127. - * Moving blank start forward is safer than moving blank end - * back, since monitors clamp just AFTER the sync pulse (or in - * the sync pulse), but never before. - */ - p->CrtcVBlankStart = p->CrtcVBlankEnd - 127; - /* - * If VBlankStart is now > VSyncStart move VBlankStart - * to VSyncStart using the maximum width that fits into - * VTotal. - */ - if (p->CrtcVBlankStart > p->CrtcVSyncStart) { - p->CrtcVBlankStart = p->CrtcVSyncStart; - p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal); - } - } - p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); - p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); - - if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) { - /* - * H Blanking size must be < 63*8. Same remark as above. - */ - p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8; - if (p->CrtcHBlankStart > p->CrtcHSyncStart) { - p->CrtcHBlankStart = p->CrtcHSyncStart; - p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal); - } - } -} - void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { @@ -268,8 +177,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) Bool ok; int refclk = 96000; - xf86SetModeCrtc(pMode, 0); - ErrorF("Requested pix clock: %d\n", pMode->Clock); ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); From a085813714818a23aa8d326804f642cd699e0f17 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Feb 2006 15:16:59 -0800 Subject: [PATCH 010/257] Add adjustments of PLL divisor limits for "Almador". --- src/i830_display.c | 74 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index a09ed60d..84379ac0 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -19,9 +19,43 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) } static Bool -i830PllIsValid(int refclk, int m1, int m2, int n, int p1, int p2) +i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1, + int p2) { + I830Ptr pI830 = I830PTR(pScrn); int p, m, vco, dotclock; + int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n; + int min_p, max_p; + + min_p = 5; + max_p = 80; + if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + min_m1 = 10; + max_m1 = 20; + min_m2 = 5; + max_m2 = 9; + min_m = 70; + max_m = 120; + min_n = 3; + max_n = 8; + if (0) { /* lvds */ + min_p = 7; + max_p = 98; + } + } else { + min_m1 = 16; + max_m1 = 24; + min_m2 = 7; + max_m2 = 11; + min_m = 90; + max_m = 130; + min_n = 4; + max_n = 8; + if (0) { /* lvds */ + min_n = 3; + min_m = 88; + } + } p = p1 + p2; m = 5 * (m1 + 2) + (m2 + 2); @@ -30,17 +64,17 @@ i830PllIsValid(int refclk, int m1, int m2, int n, int p1, int p2) if (p1 < 1 || p1 > 8) return FALSE; - if (p < 5 || p > 80) /* XXX: 7-98 for LVDS */ + if (p < min_p || p > max_p) return FALSE; - if (m2 < 5 || m2 > 9) + if (m2 < min_m2 || m2 > max_m2) return FALSE; - if (m1 < 10 || m1 > 20) + if (m1 < min_m1 || m1 > max_m1) return FALSE; if (m1 <= m2) return FALSE; - if (m < 70 || m > 120) + if (m < min_m || m > max_m) return FALSE; - if (n + 2 < 3 || n + 2 > 8) /*XXX: Is the +2 right? */ + if (n + 2 < min_n || n + 2 > max_n) /*XXX: Is the +2 right? */ return FALSE; if (vco < 1400000 || vco > 2800000) return FALSE; @@ -129,23 +163,37 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn) #endif static Bool -i830FindBestPLL(int target, int refclk, int *outm1, int *outm2, int *outn, - int *outp1, int *outp2) +i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1, + int *outm2, int *outn, int *outp1, int *outp2) { + I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; int err = target; + int min_m1, max_m1, min_m2, max_m2; + + if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + min_m1 = 10; + max_m1 = 20; + min_m2 = 5; + max_m2 = 9; + } else { + min_m1 = 16; + max_m1 = 24; + min_m2 = 7; + max_m2 = 11; + } if (target < 200000) /* XXX: LVDS */ p2 = 10; else p2 = 5; - for (m1 = 10; m1 <= 20; m1++) { - for (m2 = 5; m2 < 9; m2++) { + for (m1 = min_m1; m1 <= max_m1; m1++) { + for (m2 = min_m2; m2 < max_m2; m2++) { for (n = 1; n <= 6; n++) { for (p1 = 1; p1 <= 8; p1++) { int clock, this_err; - if (!i830PllIsValid(refclk, m1, m2, n, p1, p2)) + if (!i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2)) continue; clock = i830_clock(refclk, m1, m2, n, p1, p2); @@ -179,7 +227,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) ErrorF("Requested pix clock: %d\n", pMode->Clock); - ok = i830FindBestPLL(pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); + ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) FatalError("Couldn't find PLL settings for mode!\n"); @@ -216,7 +264,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); ErrorF("clock settings for chosen look %s\n", - i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad"); + i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad"); ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp); /* First, disable display planes */ From 6877f532c5f41a445d41eb6a9982bf6bcf691bf2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Feb 2006 15:56:06 -0800 Subject: [PATCH 011/257] Add untested CRT detection code. --- src/i810_reg.h | 13 +++++++++++++ src/i830_display.c | 16 ++++++++++++++++ src/i830_display.h | 1 + 3 files changed, 30 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index 7af23e73..1194c231 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -693,6 +693,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define FP_M1_DIV_MASK 0x00003f00 # define FP_M2_DIV_MASK 0x0000003f +#define PORT_HOTPLUG_EN 0x61110 +# define SDVOB_HOTPLUG_INT_EN (1 << 26) +# define SDVOC_HOTPLUG_INT_EN (1 << 25) +# define TV_HOTPLUG_INT_EN (1 << 18) +# define CRT_HOTPLUG_INT_EN (1 << 9) +# define CRT_HOTPLUG_FORCE_DETECT (1 << 3) + +#define PORT_HOTPLUG_STAT 0x61114 +# define CRT_HOTPLUG_INT_STATUS (1 << 11) +# define TV_HOTPLUG_INT_STATUS (1 << 10) +# define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +# define SDVOB_HOTPLUG_INT_STATUS (1 << 6) + #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff diff --git a/src/i830_display.c b/src/i830_display.c index 84379ac0..73f2d9fa 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -312,3 +312,19 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); }*/ } + +Bool +i830DetectCRT(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + + temp = INREG(PORT_HOTPLUG_EN); + OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT); + + /* Wait for the bit to clear to signal detection finished. */ + while (INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) + ; + + return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS)); +} diff --git a/src/i830_display.h b/src/i830_display.h index 6cadd75d..6ad150ad 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1 +1,2 @@ void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +Bool i830DetectCRT(ScreenPtr pScrn); From 142bc4f91a5d776e7ab44cc5fb2328e3f7267557 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Feb 2006 18:50:57 -0800 Subject: [PATCH 012/257] Write the ADPA (CRTC) register on mode setup. Obtained from airlied. --- src/i830_display.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 73f2d9fa..e4ef4775 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -221,7 +221,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) int m1, m2, n, p1, p2; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync; - CARD32 pipesrc, dspsize; + CARD32 pipesrc, dspsize, adpa; Bool ok; int refclk = 96000; @@ -262,6 +262,15 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + adpa = INREG(ADPA); + adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH); + adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE); + adpa |= ADPA_DAC_ENABLE; + if (pMode->Flags & V_PHSYNC) + adpa |= ADPA_HSYNC_ACTIVE_HIGH; + if (pMode->Flags & V_PVSYNC) + adpa |= ADPA_VSYNC_ACTIVE_HIGH; + i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); ErrorF("clock settings for chosen look %s\n", i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad"); @@ -296,6 +305,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /*OUTREG(DSPAPOS, 0);*/ OUTREG(PIPEASRC, pipesrc); OUTREG(DSPASIZE, dspsize); + OUTREG(ADPA, adpa); /* Turn pipes and planes back on */ /*if (pI830->planeEnabled[0]) {*/ From 7746da3b346968ab8d2534fc158d026da67cc7b5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 12:49:06 -0800 Subject: [PATCH 013/257] Move LVDS panel power state setting to a separate function, and reduce magic numbers. --- src/i810_reg.h | 3 +++ src/i830_display.c | 26 ++++++++++++++++++++++++++ src/i830_display.h | 1 + src/i830_driver.c | 38 ++++++++++++++------------------------ 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 1194c231..8785b069 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -756,6 +756,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define LVDS 0x61180 # define LVDS_PORT_EN (1 << 31) +# define LVDS_PIPEB_SELECT (1 << 30) +# define LVDS_CLKA_POWER_DOWN (0 << 8) +# define LVDS_CLKA_POWER_UP (3 << 8) #define PIPEACONF 0x70008 #define PIPEACONF_ENABLE (1<<31) diff --git a/src/i830_display.c b/src/i830_display.c index e4ef4775..6bf823a6 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -338,3 +338,29 @@ i830DetectCRT(ScrnInfoPtr pScrn) return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS)); } + +/** + * Sets the power state for the panel. + */ +void +i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 pp_status, pp_control; + + if (on) { + OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); + do { + pp_status = INREG(PP_STATUS); + pp_control = INREG(PP_CONTROL); + } while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON)); + } else { + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + do { + pp_status = INREG(PP_STATUS); + pp_control = INREG(PP_CONTROL); + } while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON)); + } +} diff --git a/src/i830_display.h b/src/i830_display.h index 6ad150ad..894148c5 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,2 +1,3 @@ void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScreenPtr pScrn); +void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_driver.c b/src/i830_driver.c index 2fd391ef..88f89d14 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1061,40 +1061,30 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices) /* Disable LVDS */ if (singlepipe & PIPE_LFP) { /* LFP on PipeA is unlikely! */ - OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); - while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1)); - /* Fix up LVDS */ - OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300); - /* Enable LVDS */ - OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); - while (!(INREG(PP_STATUS) & PP_ON) && !(INREG(PP_CONTROL) & 1)); + i830SetLVDSPanelPower(pScrn, FALSE); + temp = INREG(LVDS) & ~LVDS_PIPEB_SELECT; + temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP; + OUTREG(LVDS, temp); + i830SetLVDSPanelPower(pScrn, TRUE); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Enabling LVDS directly. Pipe A.\n"); } else if (singlepipe & (PIPE_LFP << 8)) { - OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); - while ((INREG(PP_STATUS) & PP_ON) || (INREG(PP_CONTROL) & 1)); - /* Fix up LVDS */ - OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300); - /* Enable LVDS */ - OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); - while (!(INREG(PP_STATUS) & PP_ON) && - !(INREG(PP_CONTROL) & POWER_TARGET_ON)); + i830SetLVDSPanelPower(pScrn, FALSE); + temp = INREG(LVDS) | LVDS_PIPEB_SELECT; + temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP; + OUTREG(LVDS, temp); + i830SetLVDSPanelPower(pScrn, TRUE); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Enabling LVDS directly. Pipe B.\n"); } else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) { if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) { - OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); - while ((INREG(PP_STATUS) & PP_ON) || - (INREG(PP_CONTROL) & POWER_TARGET_ON)); + i830SetLVDSPanelPower(pScrn, FALSE); /* Fix up LVDS */ - OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300); + temp = INREG(LVDS) | LVDS_PIPEB_SELECT; + temp &= ~(LVDS_PORT_EN | LVDS_CLKA_POWER_UP); + OUTREG(LVDS, temp); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling LVDS directly.\n"); } From 2538cbeb5014e40280a3ae782a755512b1dc85fa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 13:01:52 -0800 Subject: [PATCH 014/257] Enable -Wall on GCC, and do a cleanup of existing warnings. --- configure.ac | 4 ++++ src/i830.h | 6 ++++++ src/i830_cursor.c | 2 ++ src/i830_dri.c | 2 ++ src/i830_randr.c | 1 - 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 665b76a7..5626c4e0 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,10 @@ AC_DISABLE_STATIC AC_PROG_LIBTOOL AC_PROG_CC +if test "x$GCC" = "xyes"; then + CFLAGS="$CFLAGS -Wall" +fi + AH_TOP([#include "xorg-server.h"]) AC_ARG_WITH(xorg-module-dir, diff --git a/src/i830.h b/src/i830.h index 00d03863..a02bda77 100644 --- a/src/i830.h +++ b/src/i830.h @@ -502,6 +502,12 @@ extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh); extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode); extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode); extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); +extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn); +extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); +extern Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize); +extern Rotation I830GetRotation(ScreenPtr pScreen); +extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_cursor.c b/src/i830_cursor.c index dfed8cda..ea472fa5 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -359,7 +359,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp = 0; +#if 0 static Bool outsideViewport = FALSE; +#endif Bool hide = FALSE, show = FALSE; int oldx = x, oldy = y; int hotspotx = 0, hotspoty = 0; diff --git a/src/i830_dri.c b/src/i830_dri.c index 06bccccb..f9f9a2c7 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -101,7 +101,9 @@ static void I830DRITransitionTo3d(ScreenPtr pScreen); static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen); static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen); +#if 0 static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf); +#endif extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig * configs, diff --git a/src/i830_randr.c b/src/i830_randr.c index be790c9a..0311f2b6 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -313,7 +313,6 @@ I830RandRInit (ScreenPtr pScreen, int rotation) { rrScrPrivPtr rp; XF86RandRInfoPtr randrp; - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); #ifdef PANORAMIX /* XXX disable RandR when using Xinerama */ From 7d37c5036956609d0c7ae874d0dc1c616f76f849 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 13:06:04 -0800 Subject: [PATCH 015/257] Re-disable chatty debug code. --- src/i830_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 88f89d14..0befd2bc 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4326,7 +4326,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } } -#if 1 +#if 0 /* Print out some CRTC/display information. */ temp = INREG(HTOTAL_A); ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, From c20e15fbe4daeb7288f5c56cf5467eed13686080 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 13:08:38 -0800 Subject: [PATCH 016/257] Disable I830VESASetVBEMode on restore, since I've removed that code. Note that this means that VT switching is broken. We're fine with that for now, but at least now we get a bad display rather than X crashing about an undefined symbol. --- src/i830_driver.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i830_driver.c b/src/i830_driver.c index 0befd2bc..50ab3ab8 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3836,10 +3836,12 @@ RestoreHWState(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Setting the original video mode instead of restoring\n\t" "the saved state\n"); +#if 0 I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL); if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) { SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh); } +#endif } if (pVesa->savedScanlinePitch) VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch); From b5915ac77a3887cd3aa4ce0bb77b8a36e1aa5a1b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 13:12:25 -0800 Subject: [PATCH 017/257] Clean up a couple of warnings. --- src/i830_driver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 50ab3ab8..5b45231c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3905,6 +3905,7 @@ RestoreHWState(ScrnInfoPtr pScrn) return TRUE; } +#if 0 static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh) { I830Ptr pI830 = I830PTR(pScrn); @@ -3946,7 +3947,6 @@ static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock } } -#if 0 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) { @@ -4100,7 +4100,9 @@ static Bool I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); +#if 0 vbeInfoPtr pVbe = pI830->pVbe; +#endif VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private; int mode, i; CARD32 planeA, planeB, temp; From 7edb25789bd13f26134e8f5bf493897c8df322e0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Mar 2006 14:02:51 -0800 Subject: [PATCH 018/257] Start making i830SetMode aware of multiple pipes. --- src/i830_display.c | 132 ++++++++++++++++++++++++++++++++------------- src/i830_display.h | 2 +- src/i830_driver.c | 2 +- 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 6bf823a6..aa02a42a 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -214,13 +214,24 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1, return (err != target); } +static void +i830WaitForVblank(ScrnInfoPtr pScreen) +{ + /* Wait for 20ms, i.e. one cycle at 50hz. */ + usleep(20000); +} + +/** + * Sets the given video mode on the given pipe. Assumes that plane A feeds + * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. + */ void -i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) { I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; CARD32 dpll = 0, fp = 0, temp; - CARD32 htot, hblank, hsync, vtot, vblank, vsync; + CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize, adpa; Bool ok; int refclk = 96000; @@ -276,51 +287,96 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad"); ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp); - /* First, disable display planes */ - temp = INREG(DSPACNTR); - OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); - temp = INREG(DSPBCNTR); - OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + dspcntr = DISPLAY_PLANE_ENABLE; + switch (pScrn->bitsPerPixel) { + case 8: + dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE; + break; + case 16: + if (pScrn->depth == 15) + dspcntr |= DISPPLANE_16BPP; + else + dspcntr |= DISPPLANE_15_16BPP; + break; + case 32: + dspcntr |= DISPPLANE_32BPP; + break; + default: + FatalError("unknown display bpp\n"); + } + if (pipe == 0) + dspcntr |= DISPPLANE_SEL_PIPE_A; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; - /* Next, disable display pipes */ - temp = INREG(PIPEACONF); - OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); - temp = INREG(PIPEBCONF); - OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + /* Set up display timings and PLLs for the pipe. */ + if (pipe == 0) { + /* First, disable display planes */ + temp = INREG(DSPACNTR); + OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); - /* XXX: Wait for a vblank */ - sleep(1); + /* Next, disable display pipes */ + temp = INREG(PIPEACONF); + OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); - /* Set up display timings and PLLs for the pipe. XXX: Choose pipe! */ - OUTREG(FPA0, fp); - OUTREG(DPLL_A, dpll); - OUTREG(HTOTAL_A, htot); - OUTREG(HBLANK_A, hblank); - OUTREG(HSYNC_A, hsync); - OUTREG(VTOTAL_A, vtot); - OUTREG(VBLANK_A, vblank); - OUTREG(VSYNC_A, vsync); - OUTREG(DSPABASE, 0); /* XXX: Base placed elsewhere? */ - /*OUTREG(DSPASTRIDE, pScrn->displayWidth);*/ - /*OUTREG(DSPAPOS, 0);*/ - OUTREG(PIPEASRC, pipesrc); - OUTREG(DSPASIZE, dspsize); - OUTREG(ADPA, adpa); + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); - /* Turn pipes and planes back on */ - /*if (pI830->planeEnabled[0]) {*/ + OUTREG(FPA0, fp); + OUTREG(DPLL_A, dpll); + OUTREG(HTOTAL_A, htot); + OUTREG(HBLANK_A, hblank); + OUTREG(HSYNC_A, hsync); + OUTREG(VTOTAL_A, vtot); + OUTREG(VBLANK_A, vblank); + OUTREG(VSYNC_A, vsync); + OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp); + OUTREG(DSPASIZE, dspsize); + OUTREG(DSPAPOS, 0); + /* XXX: Deal with adjustframe down here */ + OUTREG(DSPABASE, 0); /* triggers update of display registers */ + OUTREG(PIPEASRC, pipesrc); + + /* Then, turn the pipe on first */ temp = INREG(PIPEACONF); OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE); - temp = INREG(DSPACNTR); - OUTREG(DSPACNTR, temp | DISPLAY_PLANE_ENABLE); - /*} - if (pI830->planeEnabled[1]) { + /* And then turn the plane on */ + OUTREG(DSPACNTR, dspcntr); + } else { + /* First, disable display planes */ + temp = INREG(DSPBCNTR); + OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + + /* Next, disable display pipes */ + temp = INREG(PIPEBCONF); + OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + + OUTREG(FPB0, fp); + OUTREG(DPLL_B, dpll); + OUTREG(HTOTAL_B, htot); + OUTREG(HBLANK_B, hblank); + OUTREG(HSYNC_B, hsync); + OUTREG(VTOTAL_B, vtot); + OUTREG(VBLANK_B, vblank); + OUTREG(VSYNC_B, vsync); + OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp); + OUTREG(DSPBSIZE, dspsize); + OUTREG(DSPBPOS, 0); + /* XXX: Deal with adjustframe down here */ + OUTREG(DSPBBASE, 0); /* triggers update of display registers */ + OUTREG(PIPEBSRC, pipesrc); + + /* Then, turn the pipe on first */ temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE); - temp = INREG(DSPBCNTR); - OUTREG(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); - }*/ + + /* And then turn the plane on */ + OUTREG(DSPBCNTR, dspcntr); + } } Bool diff --git a/src/i830_display.h b/src/i830_display.h index 894148c5..66811ae0 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,3 +1,3 @@ -void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); Bool i830DetectCRT(ScreenPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_driver.c b/src/i830_driver.c index 5b45231c..2dd545e0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4398,7 +4398,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); #endif - i830SetMode(pScrn, pMode); + i830SetMode(pScrn, pMode, pI830->pipe); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", pMode->HDisplay * pMode->VDisplay * refresh / 1000000); From a09d9cf27af7016bbd9e562c7b1c338154fd3d40 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 09:05:13 -0800 Subject: [PATCH 019/257] Replace I830VESASetMode with simpler i830SetMode, which is all native and doesn't have BIOS-setup workarounds. Multihead behavior may be wrong, and it is all untested. --- src/i830_display.c | 81 ++++++++++- src/i830_display.h | 2 +- src/i830_driver.c | 350 +-------------------------------------------- 3 files changed, 81 insertions(+), 352 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index aa02a42a..78a44efd 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -225,8 +225,8 @@ i830WaitForVblank(ScrnInfoPtr pScreen) * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. */ -void -i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) +static Bool +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) { I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; @@ -239,8 +239,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) ErrorF("Requested pix clock: %d\n", pMode->Clock); ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); - if (!ok) - FatalError("Couldn't find PLL settings for mode!\n"); + if (!ok) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't find PLL settings for mode!\n"); + return FALSE; + } dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */ @@ -377,6 +380,76 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPBCNTR, dspcntr); } + + return TRUE; +} + +/** + * This function sets the given mode on the active pipes. + */ +Bool +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool ok = TRUE; + CARD32 planeA, planeB; +#ifdef XF86DRI + Bool didLock = FALSE; +#endif + + DPRINTF(PFX, "i830SetMode\n"); + +#ifdef XF86DRI + didLock = I830DRILock(pScrn); +#endif + + if (pI830->operatingDevices & 0xff) { + pI830->planeEnabled[0] = 1; + } else { + pI830->planeEnabled[0] = 0; + } + + if (pI830->operatingDevices & 0xff00) { + pI830->planeEnabled[1] = 1; + } else { + pI830->planeEnabled[1] = 0; + } + + if (pI830->planeEnabled[0]) { + ok = i830PipeSetMode(pScrn, pMode, 0); + if (!ok) + goto done; + } + if (pI830->planeEnabled[1]) { + ok = i830PipeSetMode(pScrn, pMode, 1); + if (!ok) + goto done; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", + (int)(pMode->HDisplay * pMode->VDisplay * + pMode->VRefresh / 1000000)); + + planeA = INREG(DSPACNTR); + planeB = INREG(DSPBCNTR); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Display plane A is now %s and connected to %s.\n", + pI830->planeEnabled[0] ? "enabled" : "disabled", + planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + if (pI830->availablePipes == 2) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Display plane B is now %s and connected to %s.\n", + pI830->planeEnabled[1] ? "enabled" : "disabled", + planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + +done: +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn); +#endif + + return ok; } Bool diff --git a/src/i830_display.h b/src/i830_display.h index 66811ae0..823e27c8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,3 +1,3 @@ -void i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); +Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScreenPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_driver.c b/src/i830_driver.c index 2dd545e0..1e556562 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4096,350 +4096,6 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) } #endif -static Bool -I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) -{ - I830Ptr pI830 = I830PTR(pScrn); -#if 0 - vbeInfoPtr pVbe = pI830->pVbe; -#endif - VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private; - int mode, i; - CARD32 planeA, planeB, temp; - int refresh = 60; -#ifdef XF86DRI - Bool didLock = FALSE; -#endif - - DPRINTF(PFX, "I830VESASetMode\n"); - - /* Always Enable Linear Addressing */ - mode = data->mode | (1 << 15) | (1 << 14); - -#ifdef XF86DRI - didLock = I830DRILock(pScrn); -#endif - - if (pI830->Clone) { - pI830->CloneHDisplay = pMode->HDisplay; - pI830->CloneVDisplay = pMode->VDisplay; - } - -#ifndef MODESWITCH_RESET_STATE -#define MODESWITCH_RESET_STATE 0 -#endif -#if MODESWITCH_RESET_STATE - ResetState(pScrn, TRUE); -#endif - - SetPipeAccess(pScrn); - -#if 0 - if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); - return FALSE; - } - - /* - * The BIOS may not set a scanline pitch that would require more video - * memory than it's aware of. We check for this later, and set it - * explicitly if necessary. - */ - if (data->data->XResolution != pI830->displayWidth) { - if (pI830->Clone) { - SetBIOSPipe(pScrn, !pI830->pipe); - VBESetLogicalScanline(pVbe, pI830->displayWidth); - } - SetPipeAccess(pScrn); - VBESetLogicalScanline(pVbe, pI830->displayWidth); - } - - if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) { - if (pI830->Clone) { - SetBIOSPipe(pScrn, !pI830->pipe); - VBESetGetDACPaletteFormat(pVbe, 8); - } - SetPipeAccess(pScrn); - VBESetGetDACPaletteFormat(pVbe, 8); - } -#endif - - /* XXX Fix plane A with pipe A, and plane B with pipe B. */ - planeA = INREG(DSPACNTR); - planeB = INREG(DSPBCNTR); - - pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0); - pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s and connected to %s.\n", - pI830->planeEnabled[0] ? "enabled" : "disabled", - planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); - if (pI830->availablePipes == 2) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n", - pI830->planeEnabled[1] ? "enabled" : "disabled", - planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); - - if (pI830->operatingDevices & 0xff) { - pI830->planeEnabled[0] = 1; - } else { - pI830->planeEnabled[0] = 0; - } - - if (pI830->operatingDevices & 0xff00) { - pI830->planeEnabled[1] = 1; - } else { - pI830->planeEnabled[1] = 0; - } - - if (pI830->planeEnabled[0]) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n"); - planeA |= DISPLAY_PLANE_ENABLE; - planeA &= ~DISPPLANE_SEL_PIPE_MASK; - planeA |= DISPPLANE_SEL_PIPE_A; - OUTREG(DSPACNTR, planeA); - /* flush the change. */ - temp = INREG(DSPABASE); - OUTREG(DSPABASE, temp); - } - if (pI830->planeEnabled[1]) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n"); - planeB |= DISPLAY_PLANE_ENABLE; - planeB &= ~DISPPLANE_SEL_PIPE_MASK; - planeB |= DISPPLANE_SEL_PIPE_B; - OUTREG(DSPBCNTR, planeB); - /* flush the change. */ - temp = INREG(DSPBADDR); - OUTREG(DSPBADDR, temp); - } - - planeA = INREG(DSPACNTR); - planeB = INREG(DSPBCNTR); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n", - pI830->planeEnabled[0] ? "enabled" : "disabled", - planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); - if (pI830->availablePipes == 2) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n", - pI830->planeEnabled[1] ? "enabled" : "disabled", - planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); - - /* XXX Plane C is ignored for now (overlay). */ - - /* - * Print out the PIPEACONF and PIPEBCONF registers. - */ - temp = INREG(PIPEACONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", temp); - if (pI830->availablePipes == 2) { - temp = INREG(PIPEBCONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp); - } - - if (xf86IsEntityShared(pScrn->entityList[0])) { - /* Clean this up !! */ - if (I830IsPrimary(pScrn)) { - CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; - CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE; - CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - - temp = INREG(stridereg); - if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), - (int)(temp / pI8301->cpp), pI830->displayWidth); - OUTREG(stridereg, pI830->displayWidth * pI8301->cpp); - } - OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - - if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { - I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; - basereg = pI830->pipe ? DSPABASE : DSPBBASE; - sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; - - temp = INREG(stridereg); - if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), - (int)(temp / pI8302->cpp), pI8302->displayWidth); - OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp); - } - OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16)); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - } - } else { - CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; - CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE; - CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - - temp = INREG(stridereg); - if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), - (int)(temp / pI8301->cpp), pI8301->displayWidth); - OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp); - } - OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16)); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - - stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; - basereg = !pI830->pipe ? DSPABASE : DSPBBASE; - sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; - - temp = INREG(stridereg); - if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), - (int)(temp / pI8302->cpp), pI8302->displayWidth); - OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp); - } - OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - } - } else { - for (i = 0; i < pI830->availablePipes; i++) { - CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE; - CARD32 basereg = i ? DSPBBASE : DSPABASE; - CARD32 sizereg = i ? DSPBSIZE : DSPASIZE; - - if (!pI830->planeEnabled[i]) - continue; - - temp = INREG(stridereg); - if (temp / pI830->cpp != (CARD32)pI830->displayWidth) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i), - (int)(temp / pI830->cpp), pI830->displayWidth); - OUTREG(stridereg, pI830->displayWidth * pI830->cpp); - } - OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - } - } - -#if 0 - /* Print out some CRTC/display information. */ - temp = INREG(HTOTAL_A); - ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, - (temp >> 16) & 0xfff); - temp = INREG(HBLANK_A); - ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(HSYNC_A); - ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(VTOTAL_A); - ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff, - (temp >> 16) & 0xfff); - temp = INREG(VBLANK_A); - ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(VSYNC_A); - ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(PIPEASRC); - ErrorF("Image size: %dx%d (%dx%d)\n", - (temp >> 16) & 0x7ff, temp & 0x7ff, - (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1)); - ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3); - temp = INREG(DSPABASE); - ErrorF("Plane A start offset is %d\n", temp); - temp = INREG(DSPASTRIDE); - ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp); - temp = INREG(DSPAPOS); - ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); - temp = INREG(DSPASIZE); - ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); - - /* Print out some CRTC/display information. */ - temp = INREG(HTOTAL_B); - ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, - (temp >> 16) & 0xfff); - temp = INREG(HBLANK_B); - ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(HSYNC_B); - ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(VTOTAL_B); - ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff, - (temp >> 16) & 0xfff); - temp = INREG(VBLANK_B); - ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(VSYNC_B); - ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff, - (temp >> 16) & 0xfff); - temp = INREG(PIPEBSRC); - ErrorF("Image size: %dx%d (%dx%d)\n", - (temp >> 16) & 0x7ff, temp & 0x7ff, - (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1)); - ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3); - temp = INREG(DSPBBASE); - ErrorF("Plane B start offset is %d\n", temp); - temp = INREG(DSPBSTRIDE); - ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp); - temp = INREG(DSPBPOS); - ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); - temp = INREG(DSPBSIZE); - ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); -#endif - - i830SetMode(pScrn, pMode, pI830->pipe); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", - pMode->HDisplay * pMode->VDisplay * refresh / 1000000); - - { - int maxBandwidth, bandwidthA, bandwidthB; - - if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80, - &maxBandwidth, &bandwidthA, &bandwidthB)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, " - "pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n", - maxBandwidth, bandwidthA, bandwidthB); - } - } - -#if 0 - { - int ret; - - ret = GetLFPCompMode(pScrn); - if (ret != -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "LFP compensation mode: 0x%x\n", ret); - } - } -#endif - -#if MODESWITCH_RESET_STATE - ResetState(pScrn, TRUE); - SetHWOperatingState(pScrn); -#endif - -#ifdef XF86DRI - if (didLock) - I830DRIUnlock(pScrn); -#endif - - pScrn->vtSema = TRUE; - return TRUE; -} - static void InitRegisterRec(ScrnInfoPtr pScrn) { @@ -5616,7 +5272,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) if (!pI830->starting) I830DetectMonitorChange(pScrn); - if (!I830VESASetMode(pScrn, pScrn->currentMode)) + if (!I830SetMode(pScrn, pScrn->currentMode)) return FALSE; #ifdef I830_XV @@ -5686,7 +5342,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * are rotating, we don't need to call the mode setup again. */ if (pI830->currentMode != mode) { - if (!I830VESASetMode(pScrn, mode)) + if (!I830SetMode(pScrn, mode)) ret = FALSE; } @@ -5707,7 +5363,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * video mode here, as we'll have already re-instated the original rotation. */ if (!ret) { - if (!I830VESASetMode(pScrn, pI830->currentMode)) { + if (!I830SetMode(pScrn, pI830->currentMode)) { xf86DrvMsg(scrnIndex, X_INFO, "Failed to restore previous mode (SwitchMode)\n"); } From 2b842c7ee3f9c33cabf16561f11bf1c3a2502d4a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 10:08:20 -0800 Subject: [PATCH 020/257] Start implementing support for setting modes for multiple output devices, particularly LVDS. Untested. --- src/i830_display.c | 84 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 78a44efd..3c961fac 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -19,8 +19,8 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) } static Bool -i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1, - int p2) +i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, + int n, int p1, int p2) { I830Ptr pI830 = I830PTR(pScrn); int p, m, vco, dotclock; @@ -38,7 +38,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1, max_m = 120; min_n = 3; max_n = 8; - if (0) { /* lvds */ + if (outputs & PIPE_LCD_ACTIVE) { min_p = 7; max_p = 98; } @@ -51,7 +51,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int refclk, int m1, int m2, int n, int p1, max_m = 130; min_n = 4; max_n = 8; - if (0) { /* lvds */ + if (outputs & PIPE_LCD_ACTIVE) { min_n = 3; min_m = 88; } @@ -163,8 +163,8 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn) #endif static Bool -i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1, - int *outm2, int *outn, int *outp1, int *outp2) +i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, + int *outm1, int *outm2, int *outn, int *outp1, int *outp2) { I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; @@ -183,18 +183,28 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int target, int refclk, int *outm1, max_m2 = 11; } - if (target < 200000) /* XXX: LVDS */ - p2 = 10; - else - p2 = 5; + if (outputs & PIPE_LCD_ACTIVE) { + if (target < 200000) /* XXX: Is this the right cutoff? */ + p2 = 14; + else + p2 = 7; + } else { + if (target < 200000) + p2 = 10; + else + p2 = 5; + } + for (m1 = min_m1; m1 <= max_m1; m1++) { for (m2 = min_m2; m2 < max_m2; m2++) { for (n = 1; n <= 6; n++) { for (p1 = 1; p1 <= 8; p1++) { int clock, this_err; - if (!i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2)) + if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, + p1, p2)) { continue; + } clock = i830_clock(refclk, m1, m2, n, p1, p2); this_err = abs(clock - target); @@ -235,10 +245,29 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 pipesrc, dspsize, adpa; Bool ok; int refclk = 96000; + int outputs; ErrorF("Requested pix clock: %d\n", pMode->Clock); - ok = i830FindBestPLL(pScrn, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); + if (pipe == 0) + outputs = pI830->operatingDevices & 0xff; + else + outputs = (pI830->operatingDevices >> 8) & 0xff; + + if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable LVDS and non-LVDS on the same pipe\n"); + return FALSE; + } + if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) || + ((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable a TV and any other output on the same pipe\n"); + return FALSE; + } + + ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n, + &p1, &p2); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't find PLL settings for mode!\n"); @@ -246,7 +275,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) } dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; - dpll |= DPLLB_MODE_DAC_SERIAL; /* XXX: LVDS */ + if (outputs & PIPE_LCD_ACTIVE) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + dpll |= (1 << (p1 - 1)) << 16; switch (p2) { case 5: @@ -262,7 +295,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - dpll |= PLL_REF_INPUT_DREFCLK; /* XXX: TV/LVDS */ + if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE)) + dpll |= PLL_REF_INPUT_TVCLKIN; + else + dpll |= PLL_REF_INPUT_DREFCLK; dpll |= SDV0_DEFAULT_MULTIPLIER; fp = (n << 16) | (m1 << 8) | m2; @@ -287,7 +323,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); ErrorF("clock settings for chosen look %s\n", - i830PllIsValid(pScrn, refclk, m1, m2, n, p1, p2) ? "good" : "bad"); + i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ? + "good" : "bad"); ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp); dspcntr = DISPLAY_PLANE_ENABLE; @@ -307,10 +344,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) default: FatalError("unknown display bpp\n"); } - if (pipe == 0) + + adpa = ADPA_DAC_ENABLE; + if (pMode->Flags & V_PHSYNC) + adpa |= ADPA_HSYNC_ACTIVE_HIGH; + if (pMode->Flags & V_PVSYNC) + adpa |= ADPA_VSYNC_ACTIVE_HIGH; + + if (pipe == 0) { dspcntr |= DISPPLANE_SEL_PIPE_A; - else + adpa |= ADPA_PIPE_A_SELECT; + } else { dspcntr |= DISPPLANE_SEL_PIPE_B; + adpa |= ADPA_PIPE_B_SELECT; + } /* Set up display timings and PLLs for the pipe. */ if (pipe == 0) { @@ -381,6 +428,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPBCNTR, dspcntr); } + if (outputs & PIPE_CRT_ACTIVE) + OUTREG(ADPA, adpa); + return TRUE; } From 980fb78e759b752a6cae3c87d188c50ab131ba80 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 10:49:31 -0800 Subject: [PATCH 021/257] Correct capitalization of i830SetMode. --- src/i830_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 1e556562..699d4629 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -5272,7 +5272,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) if (!pI830->starting) I830DetectMonitorChange(pScrn); - if (!I830SetMode(pScrn, pScrn->currentMode)) + if (!i830SetMode(pScrn, pScrn->currentMode)) return FALSE; #ifdef I830_XV @@ -5342,7 +5342,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * are rotating, we don't need to call the mode setup again. */ if (pI830->currentMode != mode) { - if (!I830SetMode(pScrn, mode)) + if (!i830SetMode(pScrn, mode)) ret = FALSE; } @@ -5363,7 +5363,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * video mode here, as we'll have already re-instated the original rotation. */ if (!ret) { - if (!I830SetMode(pScrn, pI830->currentMode)) { + if (!i830SetMode(pScrn, pI830->currentMode)) { xf86DrvMsg(scrnIndex, X_INFO, "Failed to restore previous mode (SwitchMode)\n"); } From ee2410b965321e3d9d64fc500fdcfa6d6dc3a039 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 11:43:41 -0800 Subject: [PATCH 022/257] Move display base setting to a separate function and use it from both mode setup and AdjustFrame. Rename AdjustFrame to reflect the fact that it doesn't touch the BIOS. --- src/i830_display.c | 25 ++++++++++++++++++++---- src/i830_display.h | 1 + src/i830_driver.c | 48 +++++++++++----------------------------------- 3 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 3c961fac..d4c144ff 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -231,6 +231,25 @@ i830WaitForVblank(ScrnInfoPtr pScreen) usleep(20000); } +void +i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long Start; + + if (I830IsPrimary(pScrn)) + Start = pI830->FrontBuffer.Start; + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + Start = pI8301->FrontBuffer2.Start; + } + + if (pipe == 0) + OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + else + OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); +} + /** * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. @@ -383,8 +402,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPASIZE, dspsize); OUTREG(DSPAPOS, 0); - /* XXX: Deal with adjustframe down here */ - OUTREG(DSPABASE, 0); /* triggers update of display registers */ + i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); OUTREG(PIPEASRC, pipesrc); /* Then, turn the pipe on first */ @@ -416,8 +434,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPBSIZE, dspsize); OUTREG(DSPBPOS, 0); - /* XXX: Deal with adjustframe down here */ - OUTREG(DSPBBASE, 0); /* triggers update of display registers */ + i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); OUTREG(PIPEBSRC, pipesrc); /* Then, turn the pipe on first */ diff --git a/src/i830_display.h b/src/i830_display.h index 823e27c8..946e4184 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,3 +1,4 @@ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScreenPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); +void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); diff --git a/src/i830_driver.c b/src/i830_driver.c index 699d4629..26ad98da 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -270,7 +270,7 @@ static OptionInfoRec I830BIOSOptions[] = { static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); -static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags); +static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack); static Bool I830BIOSEnterVT(int scrnIndex, int flags); @@ -4850,18 +4850,14 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } static void -I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) +i830AdjustFrame(int scrnIndex, int x, int y, int flags) { - ScrnInfoPtr pScrn; + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830; - vbeInfoPtr pVbe; - unsigned long Start; - pScrn = xf86Screens[scrnIndex]; pI830 = I830PTR(pScrn); - pVbe = pI830->pVbe; - DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", + DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); /* Sync the engine before adjust frame */ @@ -4870,31 +4866,9 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) pI830->AccelInfoRec->NeedToSync = FALSE; } - if (I830IsPrimary(pScrn)) - Start = pI830->FrontBuffer.Start; - else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - Start = pI8301->FrontBuffer2.Start; - } - - /* Sigh... - * It seems that there are quite a few Video BIOS' that get this wrong. - * So, we'll bypass the VBE call and hit the hardware directly. - */ - - if (pI830->Clone) { - if (!pI830->pipe == 0) { - OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } else { - OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } - } - - if (pI830->pipe == 0) { - OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } else { - OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); - } + i830PipeSetBase(pScrn, pI830->pipe, x, y); + if (pI830->Clone) + i830PipeSetBase(pScrn, !pI830->pipe, x, y); } static void @@ -5878,7 +5852,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Fixing display offsets.\n"); - I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); } } @@ -5903,7 +5877,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI830->currentMode = NULL; I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); - I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); if (xf86IsEntityShared(pScrn->entityList[0])) { ScrnInfoPtr pScrn2; @@ -5922,7 +5896,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI8302->currentMode = NULL; I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); - I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); + i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); @@ -5971,7 +5945,7 @@ I830InitpScrn(ScrnInfoPtr pScrn) pScrn->PreInit = I830BIOSPreInit; pScrn->ScreenInit = I830BIOSScreenInit; pScrn->SwitchMode = I830BIOSSwitchMode; - pScrn->AdjustFrame = I830BIOSAdjustFrame; + pScrn->AdjustFrame = i830AdjustFrame; pScrn->EnterVT = I830BIOSEnterVT; pScrn->LeaveVT = I830BIOSLeaveVT; pScrn->FreeScreen = I830BIOSFreeScreen; From 8e819ced8397f0330fd44efa60fef89bd10ff70e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 11:55:00 -0800 Subject: [PATCH 023/257] It appears from the specs that you have to wait for vblank after disabling the plane, not the pipe. --- src/i830_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index d4c144ff..7d01c589 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -384,13 +384,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) temp = INREG(DSPACNTR); OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + /* Next, disable display pipes */ temp = INREG(PIPEACONF); OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - OUTREG(FPA0, fp); OUTREG(DPLL_A, dpll); OUTREG(HTOTAL_A, htot); @@ -416,13 +416,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) temp = INREG(DSPBCNTR); OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + /* Next, disable display pipes */ temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - OUTREG(FPB0, fp); OUTREG(DPLL_B, dpll); OUTREG(HTOTAL_B, htot); From df6347139bc9de22af981f776d711ac9d44fad1c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 12:52:19 -0800 Subject: [PATCH 024/257] Use DISPPLANE_32BPP_NO_ALPHA for depth 24, else the empty alpha channel results in a black display plane. --- src/i830_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 7d01c589..9a5a9ca5 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -358,7 +358,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dspcntr |= DISPPLANE_15_16BPP; break; case 32: - dspcntr |= DISPPLANE_32BPP; + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; break; default: FatalError("unknown display bpp\n"); From aca0f942f377d997c5c0b5be790ee7f255d6e046 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 13:31:51 -0800 Subject: [PATCH 025/257] Fix prototype for i830DetectCRT. --- src/i830_display.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_display.h b/src/i830_display.h index 946e4184..101d65bd 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,4 +1,4 @@ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); -Bool i830DetectCRT(ScreenPtr pScrn); +Bool i830DetectCRT(ScrnInfoPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); From 84fc3971d76f78546a0bb7dd57dba52dd893a921 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 13:35:40 -0800 Subject: [PATCH 026/257] Turn off panel power before poking pipe B, and turn it back on if we're doing LVDS. Also, refuse to do LVDS on pipe A, as the docs say you can't. --- src/i830_display.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 9a5a9ca5..741dcd2d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1,6 +1,7 @@ #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" +#include "i830_display.h" static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) { @@ -284,6 +285,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) "Can't enable a TV and any other output on the same pipe\n"); return FALSE; } + if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't support LVDS on pipe A\n"); + return FALSE; + } ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n, &p1, &p2); @@ -412,6 +418,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPACNTR, dspcntr); } else { + /* Always make sure the LVDS is off before we play with DPLLs and pipe + * configuration. + */ + i830SetLVDSPanelPower(pScrn, FALSE); + /* First, disable display planes */ temp = INREG(DSPBCNTR); OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); @@ -443,6 +454,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPBCNTR, dspcntr); + + if (outputs & PIPE_LCD_ACTIVE) + i830SetLVDSPanelPower(pScrn, TRUE); } if (outputs & PIPE_CRT_ACTIVE) From f3ec8653ab4c9b26d249bcf4393326de37ac8321 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 14:31:39 -0800 Subject: [PATCH 027/257] Include config.h, fixing many issues with reading from pI830. --- src/i830_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 741dcd2d..354f20be 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" From 7f4dc09dcafc7f0423b7f3e970a0b19fbbf515dd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 15:55:18 -0800 Subject: [PATCH 028/257] Remove some dead VBE code. --- TODO | 1 + src/i830.h | 5 - src/i830_driver.c | 342 ---------------------------------------------- 3 files changed, 1 insertion(+), 347 deletions(-) diff --git a/TODO b/TODO index ef2bab62..17e1449f 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ - licensing of new files - Figure out what exactly doublescan, interlace mean, and see if we support them. +- Remove VbeModeInfoData diff --git a/src/i830.h b/src/i830.h index a02bda77..199416a1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -95,8 +95,6 @@ typedef struct _VESARec { CARD32 *savedPal; int savedScanlinePitch; xf86MonPtr monitor; - /* Don't try to set the refresh rate for any modes. */ - Bool useDefaultRefresh; /* display start */ int x, y; } VESARec, *VESAPtr; @@ -337,9 +335,6 @@ typedef struct _I830Rec { CARD32 saveSWF0; CARD32 saveSWF4; - /* Use BIOS call 0x5f05 to set the refresh rate. */ - Bool useExtendedRefresh; - Bool checkDevices; int monitorSwitch; int operatingDevices; diff --git a/src/i830_driver.c b/src/i830_driver.c index 26ad98da..f4184397 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -697,88 +697,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) return i; } -#if 0 -static int -SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - int i = I830GetBestRefresh(pScrn, refresh); - - DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh); - - DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n", - i830refreshes[i], mode & 0xff); - - /* Only 8-bit mode numbers are supported. */ - if (mode & 0x100) - return 0; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f05; - pVbe->pInt10->bx = mode & 0xff; - - pVbe->pInt10->cx = 1 << i; - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) - return i830refreshes[i]; - else - return 0; -} - -static Bool -SetPowerStatus(ScrnInfoPtr pScrn, int mode) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x0800 | mode; - pVbe->pInt10->cx = 0x0000; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) - return TRUE; - - return FALSE; -} -#endif - -static Bool -GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB, - int devicesPipeA, int devicesPipeB, int *maxBandwidth, - int *bandwidthPipeA, int *bandwidthPipeB) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetModeSupport: modes 0x%x, 0x%x, devices: 0x%x, 0x%x\n", - modePipeA, modePipeB, devicesPipeA, devicesPipeB); - - /* Only 8-bit mode numbers are supported. */ - if ((modePipeA & 0x100) || (modePipeB & 0x100)) - return FALSE; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f28; - pVbe->pInt10->bx = (modePipeA & 0xff) | ((modePipeB & 0xff) << 8); - if ((devicesPipeA & 0x80) || (devicesPipeB & 0x80)) - pVbe->pInt10->cx = 0x8000; - else - pVbe->pInt10->cx = (devicesPipeA & 0xff) | ((devicesPipeB & 0xff) << 8); - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f28, pVbe->pInt10->ax)) { - if (maxBandwidth) - *maxBandwidth = pVbe->pInt10->cx; - if (bandwidthPipeA) - *bandwidthPipeA = pVbe->pInt10->dx & 0xffff; - /* XXX For XFree86 4.2.0 and earlier, ->dx is truncated to 16 bits. */ - if (bandwidthPipeB) - *bandwidthPipeB = (pVbe->pInt10->dx >> 16) & 0xffff; - return TRUE; - } else - return FALSE; -} - #if 0 static int GetLFPCompMode(ScrnInfoPtr pScrn) @@ -3106,49 +3024,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif - pI830->useExtendedRefresh = FALSE; - - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { - int pipe = - (pI830->operatingDevices >> PIPE_SHIFT(pI830->pipe)) & PIPE_ACTIVE_MASK; - if (pipe & ~PIPE_CRT_ACTIVE) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "A non-CRT device is attached to pipe %c.\n" - "\tNo refresh rate overrides will be attempted.\n", - PIPE_NAME(pI830->pipe)); - pI830->vesa->useDefaultRefresh = TRUE; - } - /* - * Some desktop platforms might not have 0x5f05, so useExtendedRefresh - * would need to be set to FALSE for those cases. - */ - if (!pI830->vesa->useDefaultRefresh) - pI830->useExtendedRefresh = TRUE; - } else { - for (i = 0; i < pI830->availablePipes; i++) { - int pipe = - (pI830->operatingDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK; - if (pipe & ~PIPE_CRT_ACTIVE) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "A non-CRT device is attached to pipe %c.\n" - "\tNo refresh rate overrides will be attempted.\n", - PIPE_NAME(i)); - pI830->vesa->useDefaultRefresh = TRUE; - } - /* - * Some desktop platforms might not have 0x5f05, so useExtendedRefresh - * would need to be set to FALSE for those cases. - */ - if (!pI830->vesa->useDefaultRefresh) - pI830->useExtendedRefresh = TRUE; - } - } - - if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n"); - } - /* * Limit videoram available for mode selection to what the video * BIOS can see. @@ -3403,18 +3278,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) SetPipeAccess(pScrn); I830PrintModes(pScrn); - if (!pI830->vesa->useDefaultRefresh) { - /* - * This sets the parameters for the VBE modes according to the best - * usable parameters from the Monitor sections modes (usually the - * default VESA modes), allowing for better than default refresh rates. - * This only works for VBE 3.0 and later. Also, we only do this - * if there are no non-CRT devices attached. - */ - SetPipeAccess(pScrn); - I830SetModeParameters(pScrn, pI830->pVbe); - } - /* PreInit shouldn't leave any state changes, so restore this. */ RestoreBIOSMemSize(pScrn); @@ -3798,14 +3661,6 @@ RestoreHWState(ScrnInfoPtr pScrn) pVesa = pI830->vesa; - /* - * Workaround for text mode restoration with some flat panels. - * Temporarily program a 640x480 mode before switching back to - * text mode. - */ - if (pVesa->useDefaultRefresh) - I830Set640x480(pScrn); - if (pVesa->state && pVesa->stateSize) { CARD16 imr = INREG16(IMR); CARD16 ier = INREG16(IER); @@ -3838,9 +3693,6 @@ RestoreHWState(ScrnInfoPtr pScrn) "the saved state\n"); #if 0 I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL); - if (!pVesa->useDefaultRefresh && pI830->useExtendedRefresh) { - SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh); - } #endif } if (pVesa->savedScanlinePitch) @@ -3905,197 +3757,6 @@ RestoreHWState(ScrnInfoPtr pScrn) return TRUE; } -#if 0 -static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr p = NULL; - int RefreshRate; - int clock; - - /* Search for our mode and get a refresh to match */ - for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { - if ((p->HDisplay != pI830->CloneHDisplay) || - (p->VDisplay != pI830->CloneVDisplay) || - (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - RefreshRate = ((double)(p->Clock * 1000) / - (double)(p->HTotal * p->VTotal)) * 100; - /* we could probably do better here that 2Hz boundaries */ - if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) { - block->HorizontalTotal = p->HTotal; - block->HorizontalSyncStart = p->HSyncStart; - block->HorizontalSyncEnd = p->HSyncEnd; - block->VerticalTotal = p->VTotal; - block->VerticalSyncStart = p->VSyncStart; - block->VerticalSyncEnd = p->VSyncEnd; - block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | - ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); - block->PixelClock = p->Clock * 1000; - /* XXX May not have this. */ - clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock); -#ifdef DEBUG - ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", - (double)data->block->PixelClock / 1000000.0, - (double)clock / 1000000.0); -#endif - if (clock) - block->PixelClock = clock; - block->RefreshRate = RefreshRate; - return; - } - } -} - -static Bool -I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool ret = FALSE; - int Mon; - - DPRINTF(PFX, "Setting mode 0x%.8x\n", mode); - -#if 0 - /* Clear the framebuffer (could do this with VBIOS call) */ - if (I830IsPrimary(pScrn)) - memset(pI830->FbBase + pI830->FrontBuffer.Start, 0, - pScrn->virtualY * pI830->displayWidth * pI830->cpp); - else - memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0, - pScrn->virtualY * pI830->displayWidth * pI830->cpp); -#endif - - if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay && - !pI830->preinit && !pI830->closing) { - VbeCRTCInfoBlock newblock; - int newmode = mode; - - if (pI830->pipe == 1) - Mon = pI830->MonType1; - else - Mon = pI830->MonType2; - - SetBIOSPipe(pScrn, !pI830->pipe); - - /* Now recheck refresh operations we can use */ - pI830->useExtendedRefresh = FALSE; - pI830->vesa->useDefaultRefresh = FALSE; - - if (Mon != PIPE_CRT) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "A non-CRT device is attached to Clone pipe %c.\n" - "\tNo refresh rate overrides will be attempted (0x%x).\n", - PIPE_NAME(!pI830->pipe), newmode); - pI830->vesa->useDefaultRefresh = TRUE; - } - /* - * Some desktop platforms might not have 0x5f05, so useExtendedRefresh - * would need to be set to FALSE for those cases. - */ - if (!pI830->vesa->useDefaultRefresh) - pI830->useExtendedRefresh = TRUE; - - newmode |= 1 << 11; - if (pI830->vesa->useDefaultRefresh) - newmode &= ~(1 << 11); - - if (!SetRefreshRate(pScrn, newmode, 60)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS call 0x5f05 not supported on Clone Head, " - "setting refresh with VBE 3 method.\n"); - pI830->useExtendedRefresh = FALSE; - } - - if (!pI830->vesa->useDefaultRefresh) { - I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100); - - if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) { - if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL)) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set mode for Clone head.\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting refresh on clone head with VBE 3 method.\n"); - pI830->useExtendedRefresh = FALSE; - } - } else { - if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL)) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set mode for Clone head.\n"); - } - - if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) { - if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh)) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set refresh rate to %dHz on Clone head.\n", - pI830->CloneRefresh); - else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Set refresh rate to %dHz on Clone head.\n", - pI830->CloneRefresh); - } - SetPipeAccess(pScrn); - } - - if (pI830->pipe == 0) - Mon = pI830->MonType1; - else - Mon = pI830->MonType2; - - /* Now recheck refresh operations we can use */ - pI830->useExtendedRefresh = FALSE; - pI830->vesa->useDefaultRefresh = FALSE; - - if (Mon != PIPE_CRT) - pI830->vesa->useDefaultRefresh = TRUE; - - mode |= 1 << 11; - if (pI830->vesa->useDefaultRefresh) - mode &= ~(1 << 11); - /* - * Some desktop platforms might not have 0x5f05, so useExtendedRefresh - * would need to be set to FALSE for those cases. - */ - if (!pI830->vesa->useDefaultRefresh) - pI830->useExtendedRefresh = TRUE; - - if (!SetRefreshRate(pScrn, mode, 60)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS call 0x5f05 not supported, " - "setting refresh with VBE 3 method.\n"); - pI830->useExtendedRefresh = FALSE; - } - - if (!pI830->vesa->useDefaultRefresh && block) { - ret = VBESetVBEMode(pI830->pVbe, mode, block); - if (!ret) - ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL); - else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting refresh with VBE 3 method.\n"); - pI830->useExtendedRefresh = FALSE; - } - } else { - ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL); - } - - /* Might as well bail now if we've failed */ - if (!ret) return FALSE; - - if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) { - if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set refresh rate to %dHz.\n", - block->RefreshRate / 100); - pI830->useExtendedRefresh = FALSE; - } - } - - return ret; -} -#endif - static void InitRegisterRec(ScrnInfoPtr pScrn) { @@ -5086,9 +4747,6 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) xf86PruneDriverModes(pScrn); I830PrintModes(pScrn); - if (!pI830->vesa->useDefaultRefresh) - I830SetModeParameters(pScrn, pI830->pVbe); - /* Now check if the previously used mode is o.k. for the current monitor. * This allows VT switching to continue happily when not disconnecting * and reconnecting monitors */ From 33c62e8e654fa2228bc3fd31ec0fe010703f363a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Mar 2006 17:53:38 -0800 Subject: [PATCH 029/257] Change the order of reg writes for restore, possibly increasing chances of success. Also save and restore ADPA. --- src/i830.h | 1 + src/i830_driver.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/i830.h b/src/i830.h index 199416a1..321827ad 100644 --- a/src/i830.h +++ b/src/i830.h @@ -403,6 +403,7 @@ typedef struct _I830Rec { CARD32 saveDSPBSTRIDE; CARD32 saveDSPBPOS; CARD32 saveDSPBBASE; + CARD32 saveADPA; } I830Rec; diff --git a/src/i830_driver.c b/src/i830_driver.c index f4184397..f3bc682d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3578,6 +3578,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveDSPBPOS = INREG(DSPBPOS); pI830->saveDSPBBASE = INREG(DSPBBASE); + pI830->saveADPA = INREG(ADPA); + if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else @@ -3733,6 +3735,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); OUTREG(DSPABASE, pI830->saveDSPABASE); + OUTREG(PIPEASRC, pI830->savePIPEASRC); OUTREG(FPB0, pI830->saveFPB0); OUTREG(FPB1, pI830->saveFPB1); @@ -3746,13 +3749,15 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); OUTREG(DSPBPOS, pI830->saveDSPBPOS); OUTREG(DSPBBASE, pI830->saveDSPBBASE); + OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + + OUTREG(PIPEACONF, pI830->savePIPEACONF); + OUTREG(PIPEBCONF, pI830->savePIPEBCONF); OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - OUTREG(PIPEACONF, pI830->savePIPEACONF); - OUTREG(PIPEBCONF, pI830->savePIPEBCONF); - OUTREG(PIPEASRC, pI830->savePIPEASRC); - OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + + OUTREG(ADPA, pI830->saveADPA); return TRUE; } From 585cc5f256b8e91460414a26409d0e484a86718c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Mar 2006 10:37:26 -0800 Subject: [PATCH 030/257] Add more integrated LVDS support code. --- src/i810_reg.h | 16 ++++++++++++++++ src/i830_display.c | 20 +++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 8785b069..c9b3f5ad 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -664,6 +664,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PP_CONTROL 0x61204 # define POWER_TARGET_ON (1 << 0) +#define PFIT_CONTROL 0x61230 +# define PFIT_ENABLE (1 << 31) +# define VERT_INTERP_DISABLE (0 << 10) +# define VERT_INTERP_BILINEAR (1 << 10) +# define VERT_INTERP_MASK (3 << 10) +# define VERT_AUTO_SCALE (1 << 9) +# define HORIZ_INTERP_DISABLE (0 << 6) +# define HORIZ_INTERP_BILINEAR (1 << 6) +# define HORIZ_INTERP_MASK (3 << 6) +# define HORIZ_AUTO_SCALE (1 << 5) +# define PANEL_8TO6_DITHER_ENABLE (1 << 3) + +#define PFIT_PGM_RATIOS 0x61234 +# define PFIT_VERT_SCALE_MASK 0xfff00000 +# define PFIT_HORIZ_SCALE_MASK 0x0000fff0 + #define DPLL_A 0x06014 #define DPLL_B 0x06018 # define DPLL_VCO_ENABLE (1 << 31) diff --git a/src/i830_display.c b/src/i830_display.c index 354f20be..cfff47ee 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -438,6 +438,17 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + if (outputs & PIPE_LCD_ACTIVE) { + /* Disable the PLL before messing with LVDS enable */ + OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE); + + /* LVDS must be powered on before PLL is enabled and before power + * sequencing the panel. + */ + temp = INREG(LVDS); + OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT); + } + OUTREG(FPB0, fp); OUTREG(DPLL_B, dpll); OUTREG(HTOTAL_B, htot); @@ -459,8 +470,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPBCNTR, dspcntr); - if (outputs & PIPE_LCD_ACTIVE) + if (outputs & PIPE_LCD_ACTIVE) { + /* Enable automatic panel scaling so that non-native modes fill the + * screen. + */ + /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ + OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE | + HORIZ_AUTO_SCALE); i830SetLVDSPanelPower(pScrn, TRUE); + } } if (outputs & PIPE_CRT_ACTIVE) From 12ce799818722473dde2f82739d50ba4ec7f6ecd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Mar 2006 15:38:31 -0800 Subject: [PATCH 031/257] Add some untested debugging code to for helping figure out VT switch issues. --- src/Makefile.am | 2 + src/i830_debug.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++ src/i830_debug.h | 2 + 3 files changed, 104 insertions(+) create mode 100644 src/i830_debug.c create mode 100644 src/i830_debug.h diff --git a/src/Makefile.am b/src/Makefile.am index 16e9812b..f0f6691e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,8 @@ i810_drv_la_SOURCES = \ i830_accel.c \ i830_common.h \ i830_cursor.c \ + i830_debug.c \ + i830_debug.h \ i830_dga.c \ i830_display.c \ i830_display.h \ diff --git a/src/i830_debug.c b/src/i830_debug.c new file mode 100644 index 00000000..37c0e049 --- /dev/null +++ b/src/i830_debug.c @@ -0,0 +1,100 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_ansic.h" +#include "i830.h" + +/* XXX: What was the syntax for sticking quotes around the "reg" argument? */ +#define DEFINEREG(reg) \ + { reg, NULL, 0 } + +static struct i830SnapshotRec { + int reg; + char *name; + CARD32 regval; +} i830_snapshot[] = { + DEFINEREG(ADPA), + DEFINEREG(LVDS), + DEFINEREG(DVOA), + DEFINEREG(DVOB), + DEFINEREG(DVOC), + DEFINEREG(DVO_ENABLE), + DEFINEREG(DVOA_SRCDIM), + DEFINEREG(DVOB_SRCDIM), + DEFINEREG(DVOC_SRCDIM), + + DEFINEREG(PP_CONTROL), + DEFINEREG(PP_STATUS), + DEFINEREG(PFIT_CONTROL), + DEFINEREG(PFIT_PGM_RATIOS), + DEFINEREG(PORT_HOTPLUG_EN), + DEFINEREG(PORT_HOTPLUG_STAT), + + DEFINEREG(DSPACNTR), + DEFINEREG(DSPASTRIDE), + DEFINEREG(DSPAPOS), + DEFINEREG(DSPASIZE), + DEFINEREG(DSPABASE), + DEFINEREG(PIPEACONF), + DEFINEREG(PIPEASRC), + + DEFINEREG(FPA0), + DEFINEREG(FPA1), + DEFINEREG(DPLL_A), + DEFINEREG(HTOTAL_A), + DEFINEREG(HBLANK_A), + DEFINEREG(HSYNC_A), + DEFINEREG(VTOTAL_A), + DEFINEREG(VBLANK_A), + DEFINEREG(VSYNC_A), + + DEFINEREG(DSPBCNTR), + DEFINEREG(DSPBSTRIDE), + DEFINEREG(DSPBPOS), + DEFINEREG(DSPBSIZE), + DEFINEREG(DSPBBASE), + DEFINEREG(PIPEBCONF), + DEFINEREG(PIPEBSRC), + + DEFINEREG(FPB0), + DEFINEREG(FPB1), + DEFINEREG(DPLL_B), + DEFINEREG(HTOTAL_B), + DEFINEREG(HBLANK_B), + DEFINEREG(HSYNC_B), + DEFINEREG(VTOTAL_B), + DEFINEREG(VBLANK_B), + DEFINEREG(VSYNC_B), + + { 0, NULL, 0} +}; +#undef DEFINEREG +#define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0])) + +void i830TakeRegSnapshot(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { + i830_snapshot[i].regval = INREG(i830_snapshot[i].reg); + } +} + +void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { + CARD32 val = INREG(i830_snapshot[i].reg); + if (i830_snapshot[i].regval != val) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n", + i830_snapshot[i].reg, i830_snapshot[i].name, + (int)i830_snapshot[i].regval, (int)val); + } + } +} diff --git a/src/i830_debug.h b/src/i830_debug.h new file mode 100644 index 00000000..c02ff256 --- /dev/null +++ b/src/i830_debug.h @@ -0,0 +1,2 @@ +void i830TakeRegSnapshot(ScrnInfoPtr pScrn); +void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn); From 2b6fc7ddb020a5511f6f599a2f5c37db27eddbcc Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Mar 2006 15:42:15 -0800 Subject: [PATCH 032/257] Add missed save/restore of DSP*SIZE registers. --- src/i830.h | 2 ++ src/i830_driver.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/i830.h b/src/i830.h index 321827ad..4effcd5c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -389,6 +389,7 @@ typedef struct _I830Rec { CARD32 saveVBLANK_A; CARD32 saveVSYNC_A; CARD32 saveDSPASTRIDE; + CARD32 saveDSPASIZE; CARD32 saveDSPAPOS; CARD32 saveDSPABASE; CARD32 saveFPB0; @@ -401,6 +402,7 @@ typedef struct _I830Rec { CARD32 saveVBLANK_B; CARD32 saveVSYNC_B; CARD32 saveDSPBSTRIDE; + CARD32 saveDSPBSIZE; CARD32 saveDSPBPOS; CARD32 saveDSPBBASE; CARD32 saveADPA; diff --git a/src/i830_driver.c b/src/i830_driver.c index f3bc682d..ede9cb86 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3562,6 +3562,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveVBLANK_A = INREG(VBLANK_A); pI830->saveVSYNC_A = INREG(VSYNC_A); pI830->saveDSPASTRIDE = INREG(DSPASTRIDE); + pI830->saveDSPASIZE = INREG(DSPASIZE); pI830->saveDSPAPOS = INREG(DSPAPOS); pI830->saveDSPABASE = INREG(DSPABASE); @@ -3575,6 +3576,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveVBLANK_B = INREG(VBLANK_B); pI830->saveVSYNC_B = INREG(VSYNC_B); pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); + pI830->saveDSPBSIZE = INREG(DSPBSIZE); pI830->saveDSPBPOS = INREG(DSPBPOS); pI830->saveDSPBBASE = INREG(DSPBBASE); @@ -3733,6 +3735,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(VBLANK_A, pI830->saveVBLANK_A); OUTREG(VSYNC_A, pI830->saveVSYNC_A); OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); + OUTREG(DSPASIZE, pI830->saveDSPASIZE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); OUTREG(DSPABASE, pI830->saveDSPABASE); OUTREG(PIPEASRC, pI830->savePIPEASRC); @@ -3747,6 +3750,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(VBLANK_B, pI830->saveVBLANK_B); OUTREG(VSYNC_B, pI830->saveVSYNC_B); OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); + OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); OUTREG(DSPBPOS, pI830->saveDSPBPOS); OUTREG(DSPBBASE, pI830->saveDSPBBASE); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); From 02341aa68cf2171e037196019f2553f0d1b1bd0d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Mar 2006 13:23:29 -0800 Subject: [PATCH 033/257] Make the reg-snapshot code work, add a couple more registers, and use it on VT switching to hopefully help point out where we aren't restoring enough. Currently doesn't reveal anything. --- src/i830_debug.c | 7 +++++-- src/i830_driver.c | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index 37c0e049..0695f065 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -20,7 +20,6 @@ static struct i830SnapshotRec { DEFINEREG(DVOA), DEFINEREG(DVOB), DEFINEREG(DVOC), - DEFINEREG(DVO_ENABLE), DEFINEREG(DVOA_SRCDIM), DEFINEREG(DVOB_SRCDIM), DEFINEREG(DVOC_SRCDIM), @@ -68,7 +67,9 @@ static struct i830SnapshotRec { DEFINEREG(VBLANK_B), DEFINEREG(VSYNC_B), - { 0, NULL, 0} + DEFINEREG(VCLK_DIVISOR_VGA0), + DEFINEREG(VCLK_DIVISOR_VGA1), + DEFINEREG(VCLK_POST_DIV), }; #undef DEFINEREG #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0])) @@ -88,6 +89,8 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); int i; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Comparing regs before/after X's VT usage\n"); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { CARD32 val = INREG(i830_snapshot[i].reg); if (i830_snapshot[i].regval != val) { diff --git a/src/i830_driver.c b/src/i830_driver.c index ede9cb86..cdcea29b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -182,6 +182,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "shadow.h" #include "i830.h" #include "i830_display.h" +#include "i830_debug.h" #ifdef XF86DRI #include "dri.h" @@ -3545,6 +3546,8 @@ SaveHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "SaveHWState\n"); + i830TakeRegSnapshot(pScrn); + /* Save video mode information for native mode-setting. */ pI830->saveDSPACNTR = INREG(DSPACNTR); pI830->saveDSPBCNTR = INREG(DSPBCNTR); @@ -3763,6 +3766,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(ADPA, pI830->saveADPA); + i830CompareRegsToSnapshot(pScrn); + return TRUE; } From de4a9e4a7891daa1488d17bf4c22283759f97373 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Mar 2006 12:54:14 -0800 Subject: [PATCH 034/257] Add a couple more bits to panel auto-fitting, though it isn't working yet. --- src/i810_reg.h | 2 ++ src/i830_display.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index c9b3f5ad..f781b93c 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -680,6 +680,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PFIT_VERT_SCALE_MASK 0xfff00000 # define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +#define PFIT_AUTO_RATIOS 0x61238 + #define DPLL_A 0x06014 #define DPLL_B 0x06018 # define DPLL_VCO_ENABLE (1 << 31) diff --git a/src/i830_display.c b/src/i830_display.c index cfff47ee..a7a01442 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -475,8 +475,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) * screen. */ /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE | - HORIZ_AUTO_SCALE); + OUTREG(PFIT_CONTROL, PFIT_ENABLE | + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + i830SetLVDSPanelPower(pScrn, TRUE); } } From b77bdc2c15640a3b15233f2190179d66bc8b2a4b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Mar 2006 15:08:06 -0800 Subject: [PATCH 035/257] Move the PFIT enabling before the enabling of the pipe, as the specs say we should. This doesn't work yet, as we apparently need to adjust the pipe to output at the full resolution of the panel, not the displayed image size, because PFIT controls scaling between the display planes and the pipe. --- src/i830_display.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index a7a01442..5386ac8d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -463,6 +463,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); OUTREG(PIPEBSRC, pipesrc); + if (outputs & PIPE_LCD_ACTIVE) { + /* Enable automatic panel scaling so that non-native modes fill the + * screen. + */ + /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ + OUTREG(PFIT_CONTROL, PFIT_ENABLE /*| + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR*/); + } + /* Then, turn the pipe on first */ temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE); @@ -471,14 +481,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPBCNTR, dspcntr); if (outputs & PIPE_LCD_ACTIVE) { - /* Enable automatic panel scaling so that non-native modes fill the - * screen. - */ - /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - OUTREG(PFIT_CONTROL, PFIT_ENABLE | - VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); - i830SetLVDSPanelPower(pScrn, TRUE); } } From 5215e19af58f5c2746c8d281e33ecee86e55f0a5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 13 Mar 2006 10:29:51 -0800 Subject: [PATCH 036/257] Add some register information for VGACNTRL, and do the reg-debug thing on it. --- src/i810_reg.h | 5 +++++ src/i830_debug.c | 1 + 2 files changed, 6 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index f781b93c..3316fed3 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -837,6 +837,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DSPBPOS 0x7118C #define DSPBSIZE 0x71190 +#define VGACNTRL 0x71400 +# define VGA_DISP_DISABLE (1 << 31) +# define VGA_2X_MODE (1 << 30) +# define VGA_PIPE_B_SELECT (1 << 29) + /* Various masks for reserved bits, etc. */ #define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \ (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \ diff --git a/src/i830_debug.c b/src/i830_debug.c index 0695f065..96426c46 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -70,6 +70,7 @@ static struct i830SnapshotRec { DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), DEFINEREG(VCLK_POST_DIV), + DEFINEREG(VGACNTRL), }; #undef DEFINEREG #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0])) From 6414ad89b9d368a032adf2358a65404f5443ef35 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Mar 2006 09:48:18 -0800 Subject: [PATCH 037/257] Add enough of airlied's DDC/I2C work to pull EDID info from my CRT. --- src/Makefile.am | 1 + src/common.h | 1 + src/i810_driver.c | 6 + src/i810_reg.h | 19 ++- src/i830.h | 46 ++++++++ src/i830_driver.c | 112 ++++++++++++++++++ src/i830_i2c.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 src/i830_i2c.c diff --git a/src/Makefile.am b/src/Makefile.am index f0f6691e..37682eb0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ i810_drv_la_SOURCES = \ i830_display.h \ i830_driver.c \ i830.h \ + i830_i2c.c \ i830_io.c \ i830_memory.c \ i830_modes.c \ diff --git a/src/common.h b/src/common.h index e9debe50..6e68767a 100644 --- a/src/common.h +++ b/src/common.h @@ -85,6 +85,7 @@ extern const char *I810driSymbols[]; extern const char *I810drmSymbols[]; extern const char *I810shadowSymbols[]; #endif +extern const char *I810i2cSymbols[]; extern void I830DPRINTF_stub(const char *filename, int line, const char *function, const char *fmt, ...); diff --git a/src/i810_driver.c b/src/i810_driver.c index 54395a78..f7247f4b 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -332,6 +332,12 @@ const char *I810shadowSymbols[] = { NULL }; +const char *I810i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + NULL +}; + #ifndef I810_DEBUG int I810_DEBUG = (0 /* | DEBUG_ALWAYS_SYNC */ diff --git a/src/i810_reg.h b/src/i810_reg.h index 3316fed3..6976553f 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -258,7 +258,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define HSYNC_ON 0x00 #define HSYNC_OFF 0x02 - +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 +#define GPIOD 0x501c +#define GPIOE 0x5020 +#define GPIOF 0x5024 +#define GPIOG 0x5028 +#define GPIOH 0x502c +# define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR (1 << 1) +# define GPIO_CLOCK_VAL_MASK (1 << 2) +# define GPIO_CLOCK_VAL_OUT (1 << 3) +# define GPIO_CLOCK_VAL_IN (1 << 4) +# define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR (1 << 9) +# define GPIO_DATA_VAL_MASK (1 << 10) +# define GPIO_DATA_VAL_OUT (1 << 11) +# define GPIO_DATA_VAL_IN (1 << 12) /* p317, 319 */ diff --git a/src/i830.h b/src/i830.h index 4effcd5c..d3d1f5a3 100644 --- a/src/i830.h +++ b/src/i830.h @@ -154,6 +154,44 @@ typedef struct { #endif } I830EntRec, *I830EntPtr; +/* store information about an Ixxx DVO */ +/* The i830->i865 use multiple DVOs with multiple i2cs */ +/* the i915, i945 have a single sDVO i2c bus - which is different */ +#define MAX_DVOS 4 + +#define I830_I2C_BUS_DVO 1 +#define I830_I2C_BUS_SDVO 2 + +#define I830_DVO_CHIP_NONE 0 +#define I830_DVO_CHIP_LVDS 1 +#define I830_DVO_CHIP_TMDS 2 +#define I830_DVO_CHIP_TVOUT 4 + +struct _I830RegI2CDriver { + int type; + char *modulename; + char *fntablename; + int address; + const char **symbols; + void *devpriv; + pointer modhandle; +}; + +struct _I830DVORec { + int bus_type; + int flags; + I2CBusPtr pI2CBus; + I2CBusPtr pDDCBus; + xf86MonPtr MonInfo; + struct _I830RegI2CDriver *i2c_drv; +}; + +typedef struct _I830SDVORec { + int found; + I2CDevRec d; + unsigned char sdvo_regs[20]; +} I830SDVORec, *I830SDVOPtr; + typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; @@ -373,6 +411,12 @@ typedef struct _I830Rec { OsTimerPtr devicesTimer; + int ddc2; + int num_dvos; + + struct _I830DVORec dvos[MAX_DVOS]; + I830SDVOPtr sdvo; + CARD32 saveDSPACNTR; CARD32 saveDSPBCNTR; CARD32 savePIPEACONF; @@ -506,6 +550,8 @@ extern Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); extern Rotation I830GetRotation(ScreenPtr pScreen); extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); +extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, + char *name); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_driver.c b/src/i830_driver.c index cdcea29b..f05e273f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1916,6 +1916,107 @@ I830UseDDC(ScrnInfoPtr pScrn) return mon_range->max_clock; } +void +I830PreInitDDC(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (!xf86LoadSubModule(pScrn, "ddc")) { + pI830->ddc2 = FALSE; + } else { + xf86LoaderReqSymLists(I810ddcSymbols, NULL); + pI830->ddc2 = TRUE; + } + + /* DDC can use I2C bus */ + /* Load I2C if we have the code to use it */ + if (pI830->ddc2) { + if (xf86LoadSubModule(pScrn, "i2c")) { + xf86LoaderReqSymLists(I810i2cSymbols,NULL); + + pI830->num_dvos = 1; + pI830->dvos[0].bus_type = I830_I2C_BUS_DVO; + /* setup the common CRT DVO */ + pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pDDCBus, GPIOA, "DDCGPIOA"); + if (pI830->ddc2 == FALSE) + return; + pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pI2CBus, GPIOB, "I2CGPIOB"); + if (pI830->ddc2 == FALSE) + return; + + if (!(IS_I9XX(pI830))) { + pI830->dvos[1].bus_type = I830_I2C_BUS_DVO; + pI830->num_dvos = 2; + + pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pDDCBus, GPIOD, "DDCGPIOD"); + if (pI830->ddc2 == FALSE) + return; + pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "I2CGPIOE"); + if (pI830->ddc2 == FALSE) + return; + } +#if 0 + else { + pointer ret_p; + pI830->num_dvos = 2; + pI830->dvos[1].bus_type = I830_I2C_BUS_SDVO; + /* i915 has sDVO */ + pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "SDVOCTRL"); + if (pI830->ddc2 = FALSE) + return; + pI830->sdvo=I830SDVOInit(pI830->dvos[1].pI2CBus); + } +#endif + + pI830->ddc2 = TRUE; + } else { + pI830->ddc2 = FALSE; + } + } +} + +void I830DetectMonitors(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + if (!pI830->ddc2) + return; + + for (i=0; inum_dvos; i++) { + /* we can't do EDID on sDVO yet */ + if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO) { + pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->dvos[i].pDDCBus); + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i, + pI830->dvos[i].pDDCBus->DriverPrivate.uval); + xf86PrintEDID(pI830->dvos[i].MonInfo); + +#if 0 + /* if we are on an i2C bus > 0 and we see a monitor - try to + * find a controller chip + */ + if (i > 0 && pI830->dvos[i].MonInfo) { + ret = I830I2CDetectControllers(pScrn, pI830->dvos[i].pI2CBus, + &pI830->dvos[i].i2c_drv); + if (ret==TRUE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->dvos[i].i2c_drv->modulename, pI830->dvos[i].pI2CBus->DriverPrivate.uval); + } + } +#endif + } +#if 0 + else { + ret = I830I2CDetectSDVOController(pScrn, pI830->dvos[i].pI2CBus); + if (ret==TRUE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n"); + } + } +#endif + } +} + static void PreInitCleanup(ScrnInfoPtr pScrn) { @@ -2397,6 +2498,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->fixedPipe = 1; } + I830PreInitDDC(pScrn); + + I830DetectMonitors(pScrn); + + for (i=0; idvos[i].MonInfo) { + pScrn->monitor->DDC = pI830->dvos[i].MonInfo; + break; + } + } + pI830->MonType1 = PIPE_NONE; pI830->MonType2 = PIPE_NONE; pI830->specifiedMonitor = FALSE; diff --git a/src/i830_i2c.c b/src/i830_i2c.c new file mode 100644 index 00000000..8c80a0a1 --- /dev/null +++ b/src/i830_i2c.c @@ -0,0 +1,286 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86RAC.h" +#include "xf86cmap.h" +#include "compiler.h" +#include "mibstore.h" +#include "vgaHW.h" +#include "mipointer.h" +#include "micmap.h" +#include "shadowfb.h" +#include +#include "fb.h" +#include "miscstruct.h" +#include "xf86xv.h" +#include +#include "shadow.h" +#include "i830.h" + +#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ +#define I2C_TRACE(x) /*(x)*/ /* Report progress */ + +static void i830_setscl(I2CBusPtr b, int state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, + (state ? GPIO_CLOCK_VAL_OUT : 0) | + GPIO_CLOCK_DIR | + GPIO_CLOCK_DIR_MASK | + GPIO_CLOCK_VAL_MASK); + val = INREG(b->DriverPrivate.uval); +} + +static void i830_setsda(I2CBusPtr b, int state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, (state ? GPIO_DATA_VAL_OUT : 0) | + GPIO_DATA_DIR | + GPIO_DATA_DIR_MASK | + GPIO_DATA_VAL_MASK); + val = INREG(b->DriverPrivate.uval); +} + +static void i830_getscl(I2CBusPtr b, int *state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_MASK); + OUTREG(b->DriverPrivate.uval, 0); + val = INREG(b->DriverPrivate.uval); + *state = ((val & GPIO_CLOCK_VAL_IN) != 0); +} + +static int i830_getsda(I2CBusPtr b) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_MASK); + OUTREG(b->DriverPrivate.uval, 0); + val = INREG(b->DriverPrivate.uval); + return ((val & GPIO_DATA_VAL_IN) != 0); +} + +static inline void sdalo(I2CBusPtr b) +{ + i830_setsda(b, 0); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline void sdahi(I2CBusPtr b) +{ + i830_setsda(b, 1); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline void scllo(I2CBusPtr b) +{ + i830_setscl(b, 0); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline int sclhi(I2CBusPtr b, int timeout) +{ + int scl = 0; + int i; + + i830_setscl(b, 1); + b->I2CUDelay(b, b->RiseFallTime); + + for (i = timeout; i > 0; i -= b->RiseFallTime) { + i830_getscl(b, &scl); + if (scl) break; + b->I2CUDelay(b, b->RiseFallTime); + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]", b->BusName, timeout)); + return FALSE; + } + return TRUE; +} + +static Bool +I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +{ + I2CBusPtr b = d->pI2CBus; + int i; + unsigned char indata = 0; + + sdahi(b); + + for (i = 0; i < 8; i++) { + if (sclhi(b, d->BitTimeout)==FALSE) { + I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i)); + return FALSE; + } + indata*=2; + if ( i830_getsda (b) ) { + indata |= 0x01; + } + scllo(b); + } + + if (last) + sdahi(b); + else + sdalo(b); + + if (sclhi(b, d->BitTimeout) == FALSE) { + sdahi(b); + return FALSE; + } + + scllo(b); + sdahi(b); + + *data = indata & 0xff; + I2C_TRACE(ErrorF("R%02x ", (int) *data)); + + return TRUE; +} + +static Bool +I830I2CPutByte(I2CDevPtr d, I2CByte c) +{ + int i; + int sb, ack; + I2CBusPtr b = d->pI2CBus; + + for (i = 7; i>=0; i--) { + sb = c & (1 << i); + i830_setsda(b, sb); + b->I2CUDelay(b, b->RiseFallTime); + + if (sclhi(b, d->ByteTimeout) == FALSE) { + sdahi(b); + return FALSE; + } + + i830_setscl(b, 0); + b->I2CUDelay(b, b->RiseFallTime); + } + sdahi(b); + if (sclhi(b, d->ByteTimeout) == FALSE) { + I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", + b->BusName, c, d->BitTimeout, + d->ByteTimeout, d->AcknTimeout)); + return FALSE; + } + ack = i830_getsda(b); + I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack)); + + scllo(b); + return 0 == ack; +} + +static Bool +I830I2CStart(I2CBusPtr b, int timeout) +{ + if (sclhi(b, timeout) == FALSE) + return FALSE; + + sdalo(b); + scllo(b); + + return TRUE; +} + +static void +I830I2CStop(I2CDevPtr d) +{ + I2CBusPtr b = d->pI2CBus; + + sdalo(b); + sclhi(b, d->ByteTimeout); + sdahi(b); +} + +static Bool +I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + if (I830I2CStart(d->pI2CBus, d->StartTimeout)) { + if (I830I2CPutByte(d, addr & 0xFF)) { + if ((addr & 0xF8) != 0xF0 && + (addr & 0xFE) != 0x00) + return TRUE; + + if (I830I2CPutByte(d, (addr >> 8) & 0xFF)) + return TRUE; + } + + I830I2CStop(d); + } + + return FALSE; +} + + +/* the i830 has a number of I2C Buses */ +Bool +I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) +{ + I2CBusPtr pI2CBus; + + pI2CBus = xf86CreateI2CBusRec(); + + if (!pI2CBus) + return FALSE; + + pI2CBus->BusName = name; + pI2CBus->scrnIndex = pScrn->scrnIndex; + pI2CBus->I2CGetByte = I830I2CGetByte; + pI2CBus->I2CPutByte = I830I2CPutByte; + pI2CBus->I2CStart = I830I2CStart; + pI2CBus->I2CStop = I830I2CStop; + pI2CBus->I2CAddress = I830I2CAddress; + pI2CBus->DriverPrivate.uval = i2c_reg; + + if (!xf86I2CBusInit(pI2CBus)) + return FALSE; + + *bus_ptr = pI2CBus; + return TRUE; +} From 8411c126ae66239f8b3a2261e338a723c36aa44f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Mar 2006 11:31:24 -0800 Subject: [PATCH 038/257] Update to newer airlied DDC code, and do some cleanups as well. Now tries DDC on LVDS, though my current LVDS gives no results. --- src/i830.h | 43 ++++++++---- src/i830_driver.c | 170 ++++++++++++++++++++++++++++++---------------- 2 files changed, 140 insertions(+), 73 deletions(-) diff --git a/src/i830.h b/src/i830.h index d3d1f5a3..f971638c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -157,41 +157,55 @@ typedef struct { /* store information about an Ixxx DVO */ /* The i830->i865 use multiple DVOs with multiple i2cs */ /* the i915, i945 have a single sDVO i2c bus - which is different */ -#define MAX_DVOS 4 +#define MAX_OUTPUTS 6 #define I830_I2C_BUS_DVO 1 #define I830_I2C_BUS_SDVO 2 +/* these are outputs from the chip - integrated only + external chips are via DVO or SDVO output */ +#define I830_OUTPUT_UNUSED 0 +#define I830_OUTPUT_ANALOG 1 +#define I830_OUTPUT_DVO 2 +#define I830_OUTPUT_SDVO 3 +#define I830_OUTPUT_LVDS 4 +#define I830_OUTPUT_TVOUT 5 + #define I830_DVO_CHIP_NONE 0 #define I830_DVO_CHIP_LVDS 1 #define I830_DVO_CHIP_TMDS 2 #define I830_DVO_CHIP_TVOUT 4 -struct _I830RegI2CDriver { +struct _I830DVODriver { int type; char *modulename; char *fntablename; int address; const char **symbols; +#if 0 + I830I2CVidOutputRec *vid_rec; +#endif void *devpriv; pointer modhandle; }; - -struct _I830DVORec { - int bus_type; - int flags; - I2CBusPtr pI2CBus; - I2CBusPtr pDDCBus; - xf86MonPtr MonInfo; - struct _I830RegI2CDriver *i2c_drv; -}; -typedef struct _I830SDVORec { +typedef struct _I830SDVODriver { int found; I2CDevRec d; unsigned char sdvo_regs[20]; } I830SDVORec, *I830SDVOPtr; +struct _I830OutputRec { + int type; + int pipe; + int flags; + xf86MonPtr MonInfo; + I2CBusPtr pI2CBus; + I2CBusPtr pDDCBus; + struct _I830DVODriver *i2c_drv; + struct _I830SDVODriver *sdvo_drv; +}; + typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; @@ -412,9 +426,8 @@ typedef struct _I830Rec { OsTimerPtr devicesTimer; int ddc2; - int num_dvos; - - struct _I830DVORec dvos[MAX_DVOS]; + int num_outputs; + struct _I830OutputRec output[MAX_OUTPUTS]; I830SDVOPtr sdvo; CARD32 saveDSPACNTR; diff --git a/src/i830_driver.c b/src/i830_driver.c index f05e273f..ee5c635b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -269,6 +269,15 @@ static OptionInfoRec I830BIOSOptions[] = { }; /* *INDENT-ON* */ +static const char *output_type_names[] = { + "Unused", + "Analog", + "DVO", + "SDVO", + "LVDS", + "TVOUT", +}; + static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); @@ -1916,6 +1925,58 @@ I830UseDDC(ScrnInfoPtr pScrn) return mon_range->max_clock; } +static void +I830SetupOutputBusses(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + /* everyone has at least a single analog output */ + pI830->num_outputs = 1; + pI830->output[0].type = I830_OUTPUT_ANALOG; + + /* setup the DDC bus for the analog output */ + I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A"); + + /* need to add the output busses for each device + * - this function is very incomplete + * - i915GM has LVDS and TVOUT for example + */ + switch(pI830->PciInfo->chipType) { + case PCI_CHIP_I830_M: + case PCI_CHIP_845_G: + case PCI_CHIP_I855_GM: + case PCI_CHIP_I865_G: + pI830->num_outputs = 2; + pI830->output[1].type = I830_OUTPUT_DVO; + I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D"); + I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E"); + break; + case PCI_CHIP_E7221_G: + /* ??? */ + break; + case PCI_CHIP_I915_G: + case PCI_CHIP_I915_GM: + pI830->num_outputs = 2; + pI830->output[1].type = I830_OUTPUT_LVDS; + I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C"); + break; +#if 0 + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: + /* SDVO ports have a single control bus */ + pI830->num_outputs = 2; + pI830->output[1].type = I830_OUTPUT_SDVO; + I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E"); + + pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus); + ret = I830I2CDetectSDVOController(pScrn, 1); + if (ret == TRUE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n"); + break; +#endif + } +} + void I830PreInitDDC(ScrnInfoPtr pScrn) { @@ -1932,41 +1993,9 @@ I830PreInitDDC(ScrnInfoPtr pScrn) /* Load I2C if we have the code to use it */ if (pI830->ddc2) { if (xf86LoadSubModule(pScrn, "i2c")) { - xf86LoaderReqSymLists(I810i2cSymbols,NULL); + xf86LoaderReqSymLists(I810i2cSymbols, NULL); - pI830->num_dvos = 1; - pI830->dvos[0].bus_type = I830_I2C_BUS_DVO; - /* setup the common CRT DVO */ - pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pDDCBus, GPIOA, "DDCGPIOA"); - if (pI830->ddc2 == FALSE) - return; - pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pI2CBus, GPIOB, "I2CGPIOB"); - if (pI830->ddc2 == FALSE) - return; - - if (!(IS_I9XX(pI830))) { - pI830->dvos[1].bus_type = I830_I2C_BUS_DVO; - pI830->num_dvos = 2; - - pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pDDCBus, GPIOD, "DDCGPIOD"); - if (pI830->ddc2 == FALSE) - return; - pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "I2CGPIOE"); - if (pI830->ddc2 == FALSE) - return; - } -#if 0 - else { - pointer ret_p; - pI830->num_dvos = 2; - pI830->dvos[1].bus_type = I830_I2C_BUS_SDVO; - /* i915 has sDVO */ - pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "SDVOCTRL"); - if (pI830->ddc2 = FALSE) - return; - pI830->sdvo=I830SDVOInit(pI830->dvos[1].pI2CBus); - } -#endif + I830SetupOutputBusses(pScrn); pI830->ddc2 = TRUE; } else { @@ -1978,42 +2007,67 @@ I830PreInitDDC(ScrnInfoPtr pScrn) void I830DetectMonitors(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int i; + int i, ret; if (!pI830->ddc2) return; - for (i=0; inum_dvos; i++) { - /* we can't do EDID on sDVO yet */ - if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO) { - pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->dvos[i].pDDCBus); + for (i=0; inum_outputs; i++) { + switch (pI830->output[i].type) { + case I830_OUTPUT_ANALOG: + case I830_OUTPUT_LVDS: + /* for an analog/LVDS output, just do DDC */ + pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->output[i].pDDCBus); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i, - pI830->dvos[i].pDDCBus->DriverPrivate.uval); - xf86PrintEDID(pI830->dvos[i].MonInfo); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08X\n", + output_type_names[pI830->output[i].type], i, + pI830->output[i].pDDCBus->DriverPrivate.uval); + xf86PrintEDID(pI830->output[i].MonInfo); + break; + case I830_OUTPUT_DVO: + /* check for DDC */ + pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->output[i].pDDCBus); -#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i, + pI830->output[i].pDDCBus->DriverPrivate.uval); + xf86PrintEDID(pI830->output[i].MonInfo); + /* if we are on an i2C bus > 0 and we see a monitor - try to * find a controller chip */ - if (i > 0 && pI830->dvos[i].MonInfo) { - ret = I830I2CDetectControllers(pScrn, pI830->dvos[i].pI2CBus, - &pI830->dvos[i].i2c_drv); + if (pI830->output[i].MonInfo) { + ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, + &pI830->output[i].i2c_drv); if (ret==TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->dvos[i].i2c_drv->modulename, pI830->dvos[i].pI2CBus->DriverPrivate.uval); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", + pI830->output[i].i2c_drv->modulename, + pI830->output[i].pI2CBus->DriverPrivate.uval); } } -#endif - } + break; #if 0 - else { - ret = I830I2CDetectSDVOController(pScrn, pI830->dvos[i].pI2CBus); - if (ret==TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n"); + case I830_OUTPUT_SDVO: + if (pI830->output[i].sdvo_drv->found) { + I830SDVOSetupDDC(pI830->output[i].sdvo_drv); + + pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->output[i].pI2CBus); + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i, + pI830->output[i].pI2CBus->DriverPrivate.uval); + xf86PrintEDID(pI830->output[i].MonInfo); } - } + break; #endif + case I830_OUTPUT_UNUSED: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown or unhandled output device at %d\n", i); + break; + } } } @@ -2502,9 +2556,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830DetectMonitors(pScrn); - for (i=0; idvos[i].MonInfo) { - pScrn->monitor->DDC = pI830->dvos[i].MonInfo; + for (i = 0; i < MAX_OUTPUTS; i++) { + if (pI830->output[i].MonInfo) { + pScrn->monitor->DDC = pI830->output[i].MonInfo; break; } } From c2d554be671f5368bd98867b8ecf9428e4560a81 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 23 Mar 2006 14:33:04 -0800 Subject: [PATCH 039/257] Save/restore a couple of important VGA plane registers, and have vgahw save/restore everything it knows about. Also moves the save to just after the other reg saves, above the VBE save stuff which may have side effects. --- src/i830.h | 4 ++++ src/i830_driver.c | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/i830.h b/src/i830.h index f971638c..eb75f453 100644 --- a/src/i830.h +++ b/src/i830.h @@ -462,6 +462,10 @@ typedef struct _I830Rec { CARD32 saveDSPBSIZE; CARD32 saveDSPBPOS; CARD32 saveDSPBBASE; + CARD32 saveVCLK_DIVISOR_VGA0; + CARD32 saveVCLK_DIVISOR_VGA1; + CARD32 saveVCLK_POST_DIV; + CARD32 saveVGACNTRL; CARD32 saveADPA; } I830Rec; diff --git a/src/i830_driver.c b/src/i830_driver.c index ee5c635b..48d2d0a0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3749,8 +3749,16 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveDSPBPOS = INREG(DSPBPOS); pI830->saveDSPBBASE = INREG(DSPBBASE); + pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0); + pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1); + pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV); + pI830->saveVGACNTRL = INREG(VGACNTRL); + pI830->saveADPA = INREG(ADPA); + vgaHWUnlock(hwp); + vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); + if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else @@ -3770,9 +3778,6 @@ SaveHWState(ScrnInfoPtr pScrn) VBEFreeModeInfo(modeInfo); } - vgaHWUnlock(hwp); - vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); - pVesa = pI830->vesa; /* * This save/restore method doesn't work for 845G BIOS, or for some @@ -3876,7 +3881,7 @@ RestoreHWState(ScrnInfoPtr pScrn) VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE); - vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); vgaHWLock(hwp); /* First, disable display planes */ @@ -3924,9 +3929,14 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBBASE, pI830->saveDSPBBASE); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); + OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); + OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); + OUTREG(PIPEACONF, pI830->savePIPEACONF); OUTREG(PIPEBCONF, pI830->savePIPEBCONF); + OUTREG(VGACNTRL, pI830->saveVGACNTRL); OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); From 64756e215016730b5cc2e174f08d47c0288c0ba4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 24 Mar 2006 11:55:01 -0800 Subject: [PATCH 040/257] Start interpreting VBT information with the goal of pulling out LVDS timings for panel fitting. --- src/Makefile.am | 2 + src/i830.h | 2 + src/i830_bios.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ src/i830_bios.h | 50 ++++++++++++++++++ src/i830_display.c | 7 +++ 5 files changed, 187 insertions(+) create mode 100644 src/i830_bios.c create mode 100644 src/i830_bios.h diff --git a/src/Makefile.am b/src/Makefile.am index 37682eb0..1b30c656 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,6 +44,8 @@ i810_drv_la_SOURCES = \ i810_video.c \ i810_wmark.c \ i830_accel.c \ + i830_bios.c \ + i830_bios.h \ i830_common.h \ i830_cursor.c \ i830_debug.c \ diff --git a/src/i830.h b/src/i830.h index eb75f453..fb868879 100644 --- a/src/i830.h +++ b/src/i830.h @@ -430,6 +430,8 @@ typedef struct _I830Rec { struct _I830OutputRec output[MAX_OUTPUTS]; I830SDVOPtr sdvo; + unsigned char *VBIOS; + CARD32 saveDSPACNTR; CARD32 saveDSPBCNTR; CARD32 savePIPEACONF; diff --git a/src/i830_bios.c b/src/i830_bios.c new file mode 100644 index 00000000..a5b7fcd7 --- /dev/null +++ b/src/i830_bios.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_ansic.h" +#include "i830.h" +#include "i830_bios.h" + +#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr]) +#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \ + (pI830->VBIOS[_addr + 1] << 8)) +#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \ + (pI830->VBIOS[_addr + 1] << 8) \ + (pI830->VBIOS[_addr + 2] << 16) \ + (pI830->VBIOS[_addr + 3] << 24)) + +/* XXX */ +#define INTEL_VBIOS_SIZE (64 * 1024) + +/** + * Loads the Video BIOS and checks that the VBT exists. + * + * VBT existence is a sanity check that is relied on by other i830_bios.c code. + * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may + * feed an updated VBT back through that, compared to what we'll fetch using + * this method of groping around in the BIOS data. + */ +static Bool +i830GetBIOS(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct vbt_header *vbt; + int vbt_off; + + if (pI830->VBIOS != NULL) + return TRUE; + + pI830->VBIOS = xalloc(INTEL_VBIOS_SIZE); + if (pI830->VBIOS == NULL) + return FALSE; + + if (pI830->pVbe != NULL) { + memcpy(pI830->VBIOS, (void *)(pI830->pVbe->pInt10->BIOSseg << 4), + INTEL_VBIOS_SIZE); + } else { + xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE); + } + + vbt_off = INTEL_BIOS_16(0x1a); + if (vbt_off >= INTEL_VBIOS_SIZE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", + vbt_off); + xfree(pI830->VBIOS); + return FALSE; + } + + vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); + + if (memcmp(vbt->signature, "$VBT", 4) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n"); + xfree(pI830->VBIOS); + return FALSE; + } + + return TRUE; +} + +Bool +i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct vbt_header *vbt; + struct bdb_header *bdb; + int vbt_off, bdb_block_off, block_size; + + if (!i830GetBIOS(pScrn)) + return FALSE; + + vbt_off = INTEL_BIOS_16(0x1a); + vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); + bdb = (struct bdb_header *)(pI830->VBIOS + vbt_off + vbt->bdb_offset); + + if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n"); + return FALSE; + } + + for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size; + bdb_block_off += block_size) + { + int start = vbt_off + vbt->bdb_offset + bdb_block_off; + int id; + + id = INTEL_BIOS_8(start); + block_size = INTEL_BIOS_16(start + 1) + 3; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id); + } + return TRUE; +} diff --git a/src/i830_bios.h b/src/i830_bios.h new file mode 100644 index 00000000..ed3f1826 --- /dev/null +++ b/src/i830_bios.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +struct vbt_header { + char signature[20]; /**< Always 'BIOS_DATA_BLOCK' */ + CARD16 version; /**< decimal */ + CARD16 header_size; /**< in bytes */ + CARD16 vbt_size; /**< in bytes */ + CARD8 vbt_checksum; + CARD8 reserved0; + CARD32 bdb_offset; /**< from beginning of VBT */ + CARD32 aim1_offset; /**< from beginning of VBT */ + CARD32 aim2_offset; /**< from beginning of VBT */ + CARD32 aim3_offset; /**< from beginning of VBT */ + CARD32 aim4_offset; /**< from beginning of VBT */ +}; + +struct bdb_header { + char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ + CARD16 version; /**< decimal */ + CARD16 header_size; /**< in bytes */ + CARD16 bdb_size; /**< in bytes */ +}; + +Bool +i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn); diff --git a/src/i830_display.c b/src/i830_display.c index 5386ac8d..57038df1 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -340,6 +340,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + if (outputs & PIPE_LCD_ACTIVE) { + /* To enable panel fitting, we need to set the pipe timings to that of + * the screen at its full resolution. So, pull the timings out of the + * BIOS tables and drop them in here. + */ + i830GetLVDSInfoFromBIOS(pScrn); + } adpa = INREG(ADPA); adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH); From f6a3243f40074aee471ec1cda2cc8e5f05116284 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 24 Mar 2006 13:49:10 -0800 Subject: [PATCH 041/257] Add more VBT reading, so we find the panel size. --- src/i830_bios.c | 27 ++++++++++++++++-- src/i830_bios.h | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index a5b7fcd7..cae76c81 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -98,14 +98,16 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); struct vbt_header *vbt; struct bdb_header *bdb; - int vbt_off, bdb_block_off, block_size; + int vbt_off, bdb_off, bdb_block_off, block_size; + int panel_type = -1; if (!i830GetBIOS(pScrn)) return FALSE; vbt_off = INTEL_BIOS_16(0x1a); vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); - bdb = (struct bdb_header *)(pI830->VBIOS + vbt_off + vbt->bdb_offset); + bdb_off = vbt_off + vbt->bdb_offset; + bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off); if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n"); @@ -115,12 +117,31 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size; bdb_block_off += block_size) { - int start = vbt_off + vbt->bdb_offset + bdb_block_off; + int start = bdb_off + bdb_block_off; int id; + struct lvds_bdb_1 *lvds1; + struct lvds_bdb_2 *lvds2; + struct lvds_bdb_2_fp_params *lvds2fpparam; id = INTEL_BIOS_8(start); block_size = INTEL_BIOS_16(start + 1) + 3; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id); + switch (id) { + case 40: + lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start); + panel_type = lvds1->panel_type; + break; + case 41: + if (panel_type == -1) + break; + lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start); + lvds2fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + bdb_off + lvds2->panels[panel_type].fp_params_offset); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Found panel of size %dx%d in BIOS VBT tables\n", + lvds2fpparam->x_res, lvds2fpparam->y_res); + break; + } } return TRUE; } diff --git a/src/i830_bios.h b/src/i830_bios.h index ed3f1826..9bd0db8a 100644 --- a/src/i830_bios.h +++ b/src/i830_bios.h @@ -26,7 +26,7 @@ */ struct vbt_header { - char signature[20]; /**< Always 'BIOS_DATA_BLOCK' */ + char signature[20]; /**< Always starts with 'VBT$' */ CARD16 version; /**< decimal */ CARD16 header_size; /**< in bytes */ CARD16 vbt_size; /**< in bytes */ @@ -37,14 +37,83 @@ struct vbt_header { CARD32 aim2_offset; /**< from beginning of VBT */ CARD32 aim3_offset; /**< from beginning of VBT */ CARD32 aim4_offset; /**< from beginning of VBT */ -}; +} __attribute__((packed)); struct bdb_header { char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ CARD16 version; /**< decimal */ CARD16 header_size; /**< in bytes */ CARD16 bdb_size; /**< in bytes */ -}; +} __attribute__((packed)); + +#define LVDS_CAP_EDID (1 << 6) +#define LVDS_CAP_DITHER (1 << 5) +#define LVDS_CAP_PFIT_AUTO_RATIO (1 << 4) +#define LVDS_CAP_PFIT_GRAPHICS_MODE (1 << 3) +#define LVDS_CAP_PFIT_TEXT_MODE (1 << 2) +#define LVDS_CAP_PFIT_GRAPHICS (1 << 1) +#define LVDS_CAP_PFIT_TEXT (1 << 0) +struct lvds_bdb_1 { + CARD8 id; /**< 40 */ + CARD16 size; + CARD8 panel_type; + CARD8 reserved0; + CARD16 caps; +} __attribute__((packed)); + +struct lvds_bdb_2_fp_params { + CARD16 x_res; + CARD16 y_res; + CARD32 lvds_reg; + CARD32 lvds_reg_val; + CARD32 pp_on_reg; + CARD32 pp_on_reg_val; + CARD32 pp_off_reg; + CARD32 pp_off_reg_val; + CARD32 pp_cycle_reg; + CARD32 pp_cycle_reg_val; + CARD32 pfit_reg; + CARD32 pfit_reg_val; + CARD16 terminator; +} __attribute__((packed)); + +struct lvds_bdb_2_fp_edid_dtd { + CARD16 dclk; /**< In 10khz */ + CARD8 hactive; + CARD8 hblank; + CARD8 high_h; /**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */ + CARD8 vactive; + CARD8 vblank; + CARD8 high_v; /**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */ + CARD8 hsync_off; + CARD8 hsync_pulse_width; + CARD8 vsync_off; + CARD8 high_hsync_off; /**< 7:6 = hsync off 9:8 */ + CARD8 h_image; + CARD8 v_image; + CARD8 max_hv; + CARD8 h_border; + CARD8 v_border; + CARD8 flags; +#define FP_EDID_FLAG_VSYNC_POSITIVE (1 << 2) +#define FP_EDID_FLAG_HSYNC_POSITIVE (1 << 1) +} __attribute__((packed)); + +struct lvds_bdb_2_entry { + CARD16 fp_params_offset; /**< From beginning of BDB */ + CARD8 fp_params_size; + CARD16 fp_edid_dtd_offset; + CARD8 fp_edid_dtd_size; + CARD16 fp_edid_pid_offset; + CARD8 fp_edid_pid_size; +} __attribute__((packed)); + +struct lvds_bdb_2 { + CARD8 id; /**< 41 */ + CARD16 size; + CARD8 table_size; /* not sure on this one */ + struct lvds_bdb_2_entry panels[16]; +} __attribute__((packed)); Bool i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn); From f86892c9163473a683ab591adeb9fb1c0be2ef99 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 24 Mar 2006 16:00:30 -0800 Subject: [PATCH 042/257] Make auto panel fitting work by pulling LVDS timing EDID info out of the static BIOS table, and always using that. --- src/i830.h | 10 ++++++++++ src/i830_bios.c | 29 ++++++++++++++++++++++++++--- src/i830_display.c | 36 ++++++++++++++++++++++++++++++------ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/i830.h b/src/i830.h index fb868879..d41da791 100644 --- a/src/i830.h +++ b/src/i830.h @@ -430,6 +430,16 @@ typedef struct _I830Rec { struct _I830OutputRec output[MAX_OUTPUTS]; I830SDVOPtr sdvo; + /* The BIOS's fixed timings for the LVDS */ + int panel_fixed_hactive; + int panel_fixed_hblank; + int panel_fixed_hsyncoff; + int panel_fixed_hsyncwidth; + int panel_fixed_vactive; + int panel_fixed_vblank; + int panel_fixed_vsyncoff; + int panel_fixed_vsyncwidth; + unsigned char *VBIOS; CARD32 saveDSPACNTR; diff --git a/src/i830_bios.c b/src/i830_bios.c index cae76c81..31e89b59 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -28,10 +28,12 @@ #include "config.h" #endif +#define _PARSE_EDID_ #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" #include "i830_bios.h" +#include "edid.h" #define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr]) #define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \ @@ -121,7 +123,9 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) int id; struct lvds_bdb_1 *lvds1; struct lvds_bdb_2 *lvds2; - struct lvds_bdb_2_fp_params *lvds2fpparam; + struct lvds_bdb_2_fp_params *fpparam; + struct lvds_bdb_2_fp_edid_dtd *fptiming; + CARD8 *timing_ptr; id = INTEL_BIOS_8(start); block_size = INTEL_BIOS_16(start + 1) + 3; @@ -134,12 +138,31 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) case 41: if (panel_type == -1) break; + lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start); - lvds2fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + bdb_off + lvds2->panels[panel_type].fp_params_offset); + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset); + timing_ptr = pI830->VBIOS + bdb_off + + lvds2->panels[panel_type].fp_edid_dtd_offset; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found panel of size %dx%d in BIOS VBT tables\n", - lvds2fpparam->x_res, lvds2fpparam->y_res); + fpparam->x_res, fpparam->y_res); + + /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing + * block, pull the contents out using EDID macros. + */ + pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr); + pI830->panel_fixed_hblank = _H_BLANK(timing_ptr); + pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr); + pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr); + + pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr); + pI830->panel_fixed_vblank = _V_BLANK(timing_ptr); + pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr); + pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr); break; } } diff --git a/src/i830_display.c b/src/i830_display.c index 57038df1..f9f596f1 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -340,13 +340,37 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); - if (outputs & PIPE_LCD_ACTIVE) { + if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) && + pI830->panel_fixed_hactive != 0) + { /* To enable panel fitting, we need to set the pipe timings to that of - * the screen at its full resolution. So, pull the timings out of the - * BIOS tables and drop them in here. + * the screen at its full resolution. So, drop the timings from the + * BIOS VBT tables here. */ - i830GetLVDSInfoFromBIOS(pScrn); + htot = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hblank = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff + + pI830->panel_fixed_hsyncwidth - 1) << 16); + + vtot = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vblank = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + + pI830->panel_fixed_vsyncwidth - 1) << 16); } +#if 0 + ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync); + ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync); +#endif adpa = INREG(ADPA); adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH); @@ -475,9 +499,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) * screen. */ /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - OUTREG(PFIT_CONTROL, PFIT_ENABLE /*| + OUTREG(PFIT_CONTROL, PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR*/); + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); } /* Then, turn the pipe on first */ From febdfa967dbe1df487db71ba5f677ef37450bf7a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Mar 2006 15:19:52 -0800 Subject: [PATCH 043/257] Remove some VBE DDC code that I believe is OBE. --- src/i830_driver.c | 78 ++--------------------------------------------- 1 file changed, 3 insertions(+), 75 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 48d2d0a0..ca46ec99 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2136,13 +2136,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830EntPtr pI830Ent = NULL; int mem, memsize; int flags24; - int defmon = 0; int i, n; - int DDCclock = 0; char *s; - DisplayModePtr p, pMon; ClockRangePtr clockRanges; - pointer pDDCModule = NULL, pVBEModule = NULL; + pointer pVBEModule = NULL; Bool enable; const char *chipname; unsigned int ver; @@ -2559,6 +2556,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) for (i = 0; i < MAX_OUTPUTS; i++) { if (pI830->output[i].MonInfo) { pScrn->monitor->DDC = pI830->output[i].MonInfo; + xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); break; } } @@ -3159,16 +3157,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) vbeDoPanelID(pI830->pVbe); - pDDCModule = xf86LoadSubModule(pScrn, "ddc"); - - pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule); - - if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) { - xf86PrintEDID(pI830->vesa->monitor); - xf86SetDDCproperties(pScrn, pI830->vesa->monitor); - } - xf86UnloadSubModule(pDDCModule); - /* XXX Move this to a header. */ #define VIDEO_BIOS_SCRATCH 0x18 @@ -3202,34 +3190,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum space available for video modes: %d kByte\n", memsize); - /* By now, we should have had some monitor settings, but if not, we - * need to setup some defaults. These are used in common/xf86Modes.c - * so we'll use them here for GetModePool, and that's all. - * We unset them after the call, so we can report 'defaults' as being - * used through the common layer. - */ -#define DEFAULT_HSYNC_LO 28 -#define DEFAULT_HSYNC_HI 33 -#define DEFAULT_VREFRESH_LO 43 -#define DEFAULT_VREFRESH_HI 72 - - if (pScrn->monitor->nHsync == 0) { - pScrn->monitor->hsync[0].lo = DEFAULT_HSYNC_LO; - pScrn->monitor->hsync[0].hi = DEFAULT_HSYNC_HI; - pScrn->monitor->nHsync = 1; - defmon |= 1; - } - - if (pScrn->monitor->nVrefresh == 0) { - pScrn->monitor->vrefresh[0].lo = DEFAULT_VREFRESH_LO; - pScrn->monitor->vrefresh[0].hi = DEFAULT_VREFRESH_HI; - pScrn->monitor->nVrefresh = 1; - defmon |= 2; - } - - DDCclock = I830UseDDC(pScrn); - -#if 1 /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. @@ -3241,7 +3201,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) clockRanges->clockIndex = -1; /* programmable */ clockRanges->interlaceAllowed = TRUE; /* XXX check this */ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ -#endif /* * XXX DDC information: There's code in xf86ValidateModes @@ -3269,38 +3228,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); return FALSE; - } - - /* Only use this if we've got DDC available */ - if (DDCclock > 0) { - p = pScrn->modes; - if (p == NULL) - return FALSE; - do { - int Clock = 100000000; /* incredible value */ - - if (p->status == MODE_OK) { - for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) { - if ((pMon->HDisplay != p->HDisplay) || - (pMon->VDisplay != p->VDisplay) || - (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - - /* Find lowest supported Clock for this resolution */ - if (Clock > pMon->Clock) - Clock = pMon->Clock; - } - - if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) { - ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", - p->name, pScrn->monitor->id, - Clock/1000.0, DDCclock); - p->status = MODE_BAD; - } - } - p = p->next; - } while (p != NULL && p != pScrn->modes); - } + } xf86PruneDriverModes(pScrn); From 33977d23830b5f9bb7d9e2e9c141f91cb127b7de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 27 Mar 2006 18:50:53 -0800 Subject: [PATCH 044/257] Port code from radeon driver for panel mode validation, which will hopefully get the right mode chosen on the VAIO. Untested. --- src/i830.h | 3 + src/i830_bios.c | 10 +- src/i830_driver.c | 313 ++++++++++++++++++++++++++++------------------ 3 files changed, 202 insertions(+), 124 deletions(-) diff --git a/src/i830.h b/src/i830.h index d41da791..3fba456c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -430,6 +430,9 @@ typedef struct _I830Rec { struct _I830OutputRec output[MAX_OUTPUTS]; I830SDVOPtr sdvo; + /* Panel size pulled from the BIOS */ + int PanelXRes, PanelYRes; + /* The BIOS's fixed timings for the LVDS */ int panel_fixed_hactive; int panel_fixed_hblank; diff --git a/src/i830_bios.c b/src/i830_bios.c index 31e89b59..47c39ec3 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -102,6 +102,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) struct bdb_header *bdb; int vbt_off, bdb_off, bdb_block_off, block_size; int panel_type = -1; + Bool found_panel_info = FALSE; if (!i830GetBIOS(pScrn)) return FALSE; @@ -147,9 +148,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) timing_ptr = pI830->VBIOS + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset; + pI830->PanelXRes = fpparam->x_res; + pI830->PanelYRes = fpparam->y_res; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found panel of size %dx%d in BIOS VBT tables\n", - fpparam->x_res, fpparam->y_res); + pI830->PanelXRes, pI830->PanelYRes); /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing * block, pull the contents out using EDID macros. @@ -163,8 +166,11 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) pI830->panel_fixed_vblank = _V_BLANK(timing_ptr); pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr); pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr); + + found_panel_info = TRUE; break; } } - return TRUE; + + return found_panel_info; } diff --git a/src/i830_driver.c b/src/i830_driver.c index ca46ec99..c6b59708 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -183,6 +183,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i830_display.h" #include "i830_debug.h" +#include "i830_bios.h" #ifdef XF86DRI #include "dri.h" @@ -591,100 +592,6 @@ struct panelid { char reserved[14]; }; -static void -I830InterpretPanelID(int scrnIndex, unsigned char *tmp) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - struct panelid *block = (struct panelid *)tmp; - -#define PANEL_DEFAULT_HZ 60 - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "PanelID returned panel resolution : %dx%d\n", - block->hsize, block->vsize); - - /* If we get bogus values from this, don't accept it */ - if (block->hsize == 0 || block->vsize == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Bad Panel resolution - ignoring panelID\n"); - - return; - } - - /* If we have monitor timings then don't overwrite them */ - if (pScrn->monitor->nHsync > 0 && - pScrn->monitor->nVrefresh > 0) - return; - - /* With panels, we're always assuming a refresh of 60Hz */ - - pScrn->monitor->nHsync = 1; - pScrn->monitor->nVrefresh = 1; - - /* Give a little tolerance for the selected panel */ - pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000; - pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000; - pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ; - pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ; -} - -/* This should probably go into the VBE layer */ -static unsigned char * -vbeReadPanelID(vbeInfoPtr pVbe) -{ - int RealOff = pVbe->real_mode_base; - pointer page = pVbe->memory; - unsigned char *tmp = NULL; - int screen = pVbe->pInt10->scrnIndex; - - pVbe->pInt10->ax = 0x4F11; - pVbe->pInt10->bx = 0x01; - pVbe->pInt10->cx = 0; - pVbe->pInt10->dx = 0; - pVbe->pInt10->es = SEG_ADDR(RealOff); - pVbe->pInt10->di = SEG_OFF(RealOff); - pVbe->pInt10->num = 0x10; - - xf86ExecX86int10(pVbe->pInt10); - - if ((pVbe->pInt10->ax & 0xff) != 0x4f) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n"); - goto error; - } - switch (pVbe->pInt10->ax & 0xff00) { - case 0x0: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n"); - tmp = (unsigned char *)xnfalloc(32); - memcpy(tmp,page,32); - break; - case 0x100: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n"); - break; - default: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n", - pVbe->pInt10->ax & 0xff00); - break; - } - - error: - return tmp; -} - -static void -vbeDoPanelID(vbeInfoPtr pVbe) -{ - unsigned char *PanelID_data; - - if (!pVbe) return; - - PanelID_data = vbeReadPanelID(pVbe); - - if (!PanelID_data) - return; - - I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data); -} - int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) { @@ -2125,6 +2032,166 @@ I830IsPrimary(ScrnInfoPtr pScrn) return TRUE; } +static void +i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pMode->HTotal = pI830->panel_fixed_hactive; + pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; + pMode->HSyncEnd = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth; + pMode->VTotal = pI830->panel_fixed_vactive; + pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; + pMode->VSyncEnd = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth; + pMode->Clock = 0; /* XXX */ +} + +/** + * This function returns a default mode for flat panels using the timing + * information provided by the BIOS. + */ +static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr new; + char stmp[32]; + + if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0) + return NULL; + + /* Add native panel size */ + new = xnfcalloc(1, sizeof (DisplayModeRec)); + sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); + new->name = xnfalloc(strlen(stmp) + 1); + strcpy(new->name, stmp); + new->HDisplay = pI830->PanelXRes; + new->VDisplay = pI830->PanelYRes; + i830SetModeToPanelParameters(pScrn, new); + new->type = M_T_USERDEF; + + pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes); + pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes); + pScrn->display->virtualX = pScrn->virtualX; + pScrn->display->virtualY = pScrn->virtualY; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No valid mode specified, force to native mode\n"); + + return new; +} + +/* FP mode validation routine for using panel fitting. + */ +static int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr last = NULL; + DisplayModePtr new = NULL; + DisplayModePtr first = NULL; + DisplayModePtr p, tmp; + int count = 0; + int i, width, height; + + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + + /* We have a flat panel connected to the primary display, and we + * don't have any DDC info. + */ + for (i = 0; ppModeName[i] != NULL; i++) { + + if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) + continue; + + /* Note: We allow all non-standard modes as long as they do not + * exceed the native resolution of the panel. Since these modes + * need the internal RMX unit in the video chips (and there is + * only one per card), this will only apply to the primary head. + */ + if (width < 320 || width > pI830->PanelXRes || + height < 200 || height > pI830->PanelYRes) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", + ppModeName[i]); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Valid modes must be between 320x200-%dx%d\n", + pI830->PanelXRes, pI830->PanelYRes); + continue; + } + + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(ppModeName[i]) + 1); + strcpy(new->name, ppModeName[i]); + new->HDisplay = width; + new->VDisplay = height; + new->type |= M_T_USERDEF; + + i830SetModeToPanelParameters(pScrn, new); + + new->next = NULL; + new->prev = last; + + if (last) + last->next = new; + last = new; + if (!first) + first = new; + + pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); + pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height); + count++; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid mode using panel fitting: %s\n", new->name); + } + + /* If all else fails, add the native mode */ + if (!count) { + first = last = i830FPNativeMode(pScrn); + if (first) + count = 1; + } + + /* add in all default vesa modes smaller than panel size, used for randr*/ + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) { + tmp = first; + while (tmp) { + if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; + tmp = tmp->next; + } + if (!tmp) { + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(p->name) + 1); + strcpy(new->name, p->name); + new->HDisplay = p->HDisplay; + new->VDisplay = p->VDisplay; + i830SetModeToPanelParameters(pScrn, new); + new->type |= M_T_DEFAULT; + + new->next = NULL; + new->prev = last; + + if (last) + last->next = new; + last = new; + if (!first) + first = new; + } + } + } + + /* Close the doubly-linked mode list, if we found any usable modes */ + if (last) { + last->next = first; + first->prev = last; + pScrn->modes = first; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total number of valid FP mode(s) found: %d\n", count); + + return count; +} + static Bool I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) { @@ -3151,12 +3218,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) SetPipeAccess(pScrn); - /* Check we have an LFP connected, before trying to - * read PanelID information. */ - if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || - (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) - vbeDoPanelID(pI830->pVbe); - /* XXX Move this to a header. */ #define VIDEO_BIOS_SCRATCH 0x18 @@ -3202,28 +3263,36 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) clockRanges->interlaceAllowed = TRUE; /* XXX check this */ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ - /* - * XXX DDC information: There's code in xf86ValidateModes - * (VBEValidateModes) to set monitor defaults based on DDC information - * where available. If we need something that does better than this, - * there's code in vesa/vesa.c. - */ - - /* XXX minPitch, minHeight are random numbers. */ - n = xf86ValidateModes(pScrn, - pScrn->monitor->Modes, /* availModes */ - pScrn->display->modes, /* modeNames */ - clockRanges, /* clockRanges */ - NULL, /* linePitches */ - 256, /* minPitch */ - MAX_DISPLAY_PITCH, /* maxPitch */ - 64, /* pitchInc */ - pScrn->bitsPerPixel, /* minHeight */ - MAX_DISPLAY_HEIGHT, /* maxHeight */ - pScrn->display->virtualX, /* virtualX */ - pScrn->display->virtualY, /* virtualY */ - pI830->FbMapSize, /* apertureSize */ - LOOKUP_BEST_REFRESH /* strategy */); + if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || + (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) { + /* If we're outputting to an LFP, use the LFP mode validation that will + * rely on the scaler so that we can display any mode smaller than or the + * same size as the panel. + */ + if (!i830GetLVDSInfoFromBIOS(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unable to locate panel information in BIOS VBT tables\n"); + PreInitCleanup(pScrn); + return FALSE; + } + n = i830ValidateFPModes(pScrn, pScrn->display->modes); + } else { + /* XXX minPitch, minHeight are random numbers. */ + n = xf86ValidateModes(pScrn, + pScrn->monitor->Modes, /* availModes */ + pScrn->display->modes, /* modeNames */ + clockRanges, /* clockRanges */ + NULL, /* linePitches */ + 256, /* minPitch */ + MAX_DISPLAY_PITCH, /* maxPitch */ + 64, /* pitchInc */ + pScrn->bitsPerPixel, /* minHeight */ + MAX_DISPLAY_HEIGHT, /* maxHeight */ + pScrn->display->virtualX, /* virtualX */ + pScrn->display->virtualY, /* virtualY */ + pI830->FbMapSize, /* apertureSize */ + LOOKUP_BEST_REFRESH /* strategy */); + } if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); From e45581cd073b23a62719f20783d617bd35316fec Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Mar 2006 13:40:32 -0800 Subject: [PATCH 045/257] Fill in clock information from VBT table, so that a good clock value gets requested for choosing divisors. --- src/i830.h | 1 + src/i830_bios.c | 1 + src/i830_driver.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i830.h b/src/i830.h index 3fba456c..019c1d32 100644 --- a/src/i830.h +++ b/src/i830.h @@ -434,6 +434,7 @@ typedef struct _I830Rec { int PanelXRes, PanelYRes; /* The BIOS's fixed timings for the LVDS */ + int panel_fixed_clock; int panel_fixed_hactive; int panel_fixed_hblank; int panel_fixed_hsyncoff; diff --git a/src/i830_bios.c b/src/i830_bios.c index 47c39ec3..eb810fca 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -157,6 +157,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing * block, pull the contents out using EDID macros. */ + pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000; pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr); pI830->panel_fixed_hblank = _H_BLANK(timing_ptr); pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr); diff --git a/src/i830_driver.c b/src/i830_driver.c index c6b59708..fccef4a7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2043,7 +2043,7 @@ i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode) pMode->VTotal = pI830->panel_fixed_vactive; pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; pMode->VSyncEnd = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth; - pMode->Clock = 0; /* XXX */ + pMode->Clock = pI830->panel_fixed_clock; } /** From 8d27f8246ed5a73f7a78043e128b47be784186c0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Mar 2006 13:49:41 -0800 Subject: [PATCH 046/257] Clean up (and I believe fix a couple of bugs in) the divisor selection code. --- src/i830_display.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index f9f596f1..224e82c8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -7,9 +7,10 @@ #include "i830.h" #include "i830_display.h" +/** Returns the pixel clock for the given refclk and divisors. */ static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) { - return (refclk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2); + return refclk * (5 * m1 + m2) / n / (p1 * p2); } static void @@ -23,6 +24,13 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) m1, m2, n, p1, p2); } +/** + * Returns whether the given set of divisors are valid for a given refclk with + * the given outputs. + * + * The equation for these divisors would be: + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) + */ static Bool i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, int n, int p1, int p2) @@ -62,9 +70,9 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, } } - p = p1 + p2; - m = 5 * (m1 + 2) + (m2 + 2); - vco = refclk * m / (n + 2); + p = p1 * p2; + m = 5 * m1 + m2; + vco = refclk * m / n; dotclock = i830_clock(refclk, m1, m2, n, p1, p2); if (p1 < 1 || p1 > 8) @@ -79,7 +87,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, return FALSE; if (m < min_m || m > max_m) return FALSE; - if (n + 2 < min_n || n + 2 > max_n) /*XXX: Is the +2 right? */ + if (n < min_n || n > max_n) return FALSE; if (vco < 1400000 || vco > 2800000) return FALSE; @@ -167,6 +175,11 @@ i830ReadAndReportPLL(ScrnInfoPtr pScrn) } #endif +/** + * Returns a set of divisors for the desired target clock with the given refclk, + * or FALSE. Divisor values are the actual divisors for + * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) + */ static Bool i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, int *outm1, int *outm2, int *outn, int *outp1, int *outp2) @@ -202,7 +215,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, for (m1 = min_m1; m1 <= max_m1; m1++) { for (m2 = min_m2; m2 < max_m2; m2++) { - for (n = 1; n <= 6; n++) { + for (n = 3; n <= 8; n++) { for (p1 = 1; p1 <= 8; p1++) { int clock, this_err; @@ -330,7 +343,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_REF_INPUT_DREFCLK; dpll |= SDV0_DEFAULT_MULTIPLIER; - fp = (n << 16) | (m1 << 8) | m2; + fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); From 4e3a4827007d624aa3da1a9f5a299837bd601a33 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 31 Mar 2006 14:05:46 -0800 Subject: [PATCH 047/257] autodetect LVDS dither. Fix 16bpp depth selection --- src/i830.h | 2 ++ src/i830_bios.c | 2 ++ src/i830_display.c | 15 ++++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/i830.h b/src/i830.h index 019c1d32..ea3d9e6a 100644 --- a/src/i830.h +++ b/src/i830.h @@ -444,6 +444,8 @@ typedef struct _I830Rec { int panel_fixed_vsyncoff; int panel_fixed_vsyncwidth; + Bool panel_wants_dither; + unsigned char *VBIOS; CARD32 saveDSPACNTR; diff --git a/src/i830_bios.c b/src/i830_bios.c index eb810fca..4264803b 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -135,6 +135,8 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) case 40: lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start); panel_type = lvds1->panel_type; + if (lvds1->caps & LVDS_CAP_DITHER) + pI830->panel_wants_dither = TRUE; break; case 41: if (panel_type == -1) diff --git a/src/i830_display.c b/src/i830_display.c index 224e82c8..ebe0aa3b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -407,9 +407,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) break; case 16: if (pScrn->depth == 15) - dspcntr |= DISPPLANE_16BPP; - else dspcntr |= DISPPLANE_15_16BPP; + else + dspcntr |= DISPPLANE_16BPP; break; case 32: dspcntr |= DISPPLANE_32BPP_NO_ALPHA; @@ -508,13 +508,18 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(PIPEBSRC, pipesrc); if (outputs & PIPE_LCD_ACTIVE) { + CARD32 pfit_control; + /* Enable automatic panel scaling so that non-native modes fill the * screen. */ /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - OUTREG(PFIT_CONTROL, PFIT_ENABLE | - VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + pfit_control = (PFIT_ENABLE | + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + if (pI830->panel_wants_dither) + pfit_control |= PANEL_8TO6_DITHER_ENABLE; + OUTREG(PFIT_CONTROL, pfit_control); } /* Then, turn the pipe on first */ From d960c3ca1512a58a53b5c24702cb5c97124817ee Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 14:12:29 -0700 Subject: [PATCH 048/257] Remove more BIOS modesetting stuff. --- src/i830.h | 4 - src/i830_driver.c | 39 +-- src/i830_modes.c | 665 ---------------------------------------------- 3 files changed, 3 insertions(+), 705 deletions(-) diff --git a/src/i830.h b/src/i830.h index ea3d9e6a..a6cd0402 100644 --- a/src/i830.h +++ b/src/i830.h @@ -570,10 +570,6 @@ extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg); extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); extern Bool I830IsPrimary(ScrnInfoPtr pScrn); -extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, - VbeInfoBlock *vbe); -extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe); -extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe); extern void I830PrintModes(ScrnInfoPtr pScrn); extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh); extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index fccef4a7..813b20ee 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -614,42 +614,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) return i; } -#if 0 -static int -GetLFPCompMode(ScrnInfoPtr pScrn) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetLFPCompMode\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f61; - pVbe->pInt10->bx = 0x100; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax)) - return pVbe->pInt10->cx & 0xffff; - else - return -1; -} - -static Bool -SetLFPCompMode(ScrnInfoPtr pScrn, int compMode) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "SetLFPCompMode: compMode %d\n", compMode); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f61; - pVbe->pInt10->bx = 0; - pVbe->pInt10->cx = compMode; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - return Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax); -} -#endif - static int GetDisplayDevices(ScrnInfoPtr pScrn) { @@ -4839,6 +4803,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags) static Bool I830DetectMonitorChange(ScrnInfoPtr pScrn) { + return FALSE; +#if 0 /* Disabled until we rewrite this natively */ I830Ptr pI830 = I830PTR(pScrn); pointer pDDCModule = NULL; DisplayModePtr p, pMon; @@ -4977,6 +4943,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) } return TRUE; +#endif /* 0 */ } Bool diff --git a/src/i830_modes.c b/src/i830_modes.c index a992bb60..617d1e63 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -40,675 +40,10 @@ #include "xf86.h" #include "xf86_ansic.h" -#include "vbe.h" -#include "vbeModes.h" #include "i830.h" -#include - -#define rint(x) floor(x) - -#define MARGIN_PERCENT 1.8 /* % of active vertical image */ -#define CELL_GRAN 8.0 /* assumed character cell granularity */ -#define MIN_PORCH 1 /* minimum front porch */ -#define V_SYNC_RQD 3 /* width of vsync in lines */ -#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */ -#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */ -#define M 600.0 /* blanking formula gradient */ -#define C 40.0 /* blanking formula offset */ -#define K 128.0 /* blanking formula scaling factor */ -#define J 20.0 /* blanking formula scaling factor */ - -/* C' and M' are part of the Blanking Duty Cycle computation */ - -#define C_PRIME (((C - J) * K/256.0) + J) -#define M_PRIME (K/256.0 * M) - extern const int i830refreshes[]; -static DisplayModePtr -I830GetGTF (int h_pixels, int v_lines, float freq, - int interlaced, int margins) -{ - float h_pixels_rnd; - float v_lines_rnd; - float v_field_rate_rqd; - float top_margin; - float bottom_margin; - float interlace; - float h_period_est; - float vsync_plus_bp; - float v_back_porch; - float total_v_lines; - float v_field_rate_est; - float h_period; - float v_field_rate; - float v_frame_rate; - float left_margin; - float right_margin; - float total_active_pixels; - float ideal_duty_cycle; - float h_blank; - float total_pixels; - float pixel_freq; - float h_freq; - - float h_sync; - float h_front_porch; - float v_odd_front_porch_lines; - char modename[20]; - DisplayModePtr m; - - m = xnfcalloc(sizeof(DisplayModeRec), 1); - - - /* 1. In order to give correct results, the number of horizontal - * pixels requested is first processed to ensure that it is divisible - * by the character size, by rounding it to the nearest character - * cell boundary: - * - * [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND]) - */ - - h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN; - - - /* 2. If interlace is requested, the number of vertical lines assumed - * by the calculation must be halved, as the computation calculates - * the number of vertical lines per field. In either case, the - * number of lines is rounded to the nearest integer. - * - * [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0), - * ROUND([V LINES],0)) - */ - - v_lines_rnd = interlaced ? - rint((float) v_lines) / 2.0 : - rint((float) v_lines); - - /* 3. Find the frame rate required: - * - * [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2, - * [I/P FREQ RQD]) - */ - - v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq); - - /* 4. Find number of lines in Top margin: - * - * [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y", - * ROUND(([MARGIN%]/100*[V LINES RND]),0), - * 0) - */ - - top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0); - - /* 5. Find number of lines in Bottom margin: - * - * [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y", - * ROUND(([MARGIN%]/100*[V LINES RND]),0), - * 0) - */ - - bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0); - - /* 6. If interlace is required, then set variable [INTERLACE]=0.5: - * - * [INTERLACE]=(IF([INT RQD?]="y",0.5,0)) - */ - - interlace = interlaced ? 0.5 : 0.0; - - /* 7. Estimate the Horizontal period - * - * [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) / - * ([V LINES RND] + (2*[TOP MARGIN (LINES)]) + - * [MIN PORCH RND]+[INTERLACE]) * 1000000 - */ - - h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0)) - / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace) - * 1000000.0); - - /* 8. Find the number of lines in V sync + back porch: - * - * [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0) - */ - - vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est); - - /* 9. Find the number of lines in V back porch alone: - * - * [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND] - * - * XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]? - */ - - v_back_porch = vsync_plus_bp - V_SYNC_RQD; - - /* 10. Find the total number of lines in Vertical field period: - * - * [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] + - * [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] + - * [MIN PORCH RND] - */ - - total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + - interlace + MIN_PORCH; - - /* 11. Estimate the Vertical field frequency: - * - * [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000 - */ - - v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0; - - /* 12. Find the actual horizontal period: - * - * [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST]) - */ - - h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est); - - /* 13. Find the actual Vertical field frequency: - * - * [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000 - */ - - v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0; - - /* 14. Find the Vertical frame frequency: - * - * [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE])) - */ - - v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate; - - /* 15. Find number of pixels in left margin: - * - * [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", - * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / - * [CELL GRAN RND]),0)) * [CELL GRAN RND], - * 0)) - */ - - left_margin = margins ? - rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : - 0.0; - - /* 16. Find number of pixels in right margin: - * - * [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", - * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / - * [CELL GRAN RND]),0)) * [CELL GRAN RND], - * 0)) - */ - - right_margin = margins ? - rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : - 0.0; - - /* 17. Find total number of active pixels in image and left and right - * margins: - * - * [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] + - * [RIGHT MARGIN (PIXELS)] - */ - - total_active_pixels = h_pixels_rnd + left_margin + right_margin; - - /* 18. Find the ideal blanking duty cycle from the blanking duty cycle - * equation: - * - * [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000) - */ - - ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0); - - /* 19. Find the number of pixels in the blanking time to the nearest - * double character cell: - * - * [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] * - * [IDEAL DUTY CYCLE] / - * (100-[IDEAL DUTY CYCLE]) / - * (2*[CELL GRAN RND])), 0)) - * * (2*[CELL GRAN RND]) - */ - - h_blank = rint(total_active_pixels * - ideal_duty_cycle / - (100.0 - ideal_duty_cycle) / - (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN); - - /* 20. Find total number of pixels: - * - * [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)] - */ - - total_pixels = total_active_pixels + h_blank; - - /* 21. Find pixel clock frequency: - * - * [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD] - */ - - pixel_freq = total_pixels / h_period; - - /* 22. Find horizontal frequency: - * - * [H FREQ] = 1000 / [H PERIOD] - */ - - h_freq = 1000.0 / h_period; - - - /* Stage 1 computations are now complete; I should really pass - the results to another function and do the Stage 2 - computations, but I only need a few more values so I'll just - append the computations here for now */ - - - - /* 17. Find the number of pixels in the horizontal sync period: - * - * [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] / - * [CELL GRAN RND]),0))*[CELL GRAN RND] - */ - - h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN; - - /* 18. Find the number of pixels in the horizontal front porch period: - * - * [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)] - */ - - h_front_porch = (h_blank / 2.0) - h_sync; - - /* 36. Find the number of lines in the odd front porch period: - * - * [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE]) - */ - - v_odd_front_porch_lines = MIN_PORCH + interlace; - - /* finally, pack the results in the DisplayMode struct */ - - m->HDisplay = (int) (h_pixels_rnd); - m->HSyncStart = (int) (h_pixels_rnd + h_front_porch); - m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync); - m->HTotal = (int) (total_pixels); - - m->VDisplay = (int) (v_lines_rnd); - m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines); - m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD); - m->VTotal = (int) (total_v_lines); - - m->Clock = (int)(pixel_freq * 1000); - m->SynthClock = m->Clock; - m->HSync = h_freq; - m->VRefresh = v_frame_rate /* freq */; - - snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay); - m->name = xnfstrdup(modename); - - return (m); -} - -static DisplayModePtr -CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, - int flags) -{ - CARD16 major, minor; - VbeModeInfoBlock *mode; - DisplayModePtr p = NULL, pMode = NULL; - VbeModeInfoData *data; - Bool modeOK = FALSE; - ModeStatus status = MODE_OK; - - major = (unsigned)(vbe->VESAVersion >> 8); - minor = vbe->VESAVersion & 0xff; - - if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) - return NULL; - - /* Does the mode match the depth/bpp? */ - /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */ - if (VBE_MODE_USABLE(mode, flags) && - ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) || - (mode->BitsPerPixel > 8 && - (mode->RedMaskSize + mode->GreenMaskSize + - mode->BlueMaskSize) == pScrn->depth && - mode->BitsPerPixel == pScrn->bitsPerPixel) || - (mode->BitsPerPixel == 15 && pScrn->depth == 15) || - (mode->BitsPerPixel <= 8 && - mode->BitsPerPixel == pScrn->bitsPerPixel))) { - modeOK = TRUE; - xf86ErrorFVerb(DEBUG_VERB, "*"); - } - - if (mode->XResolution && mode->YResolution && - !I830CheckModeSupport(pScrn, mode->XResolution, mode->YResolution, id)) - modeOK = FALSE; - - - /* - * Check if there's a valid monitor mode that this one can be matched - * up with from the 'specified' modes list. - */ - if (modeOK) { - for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { - if ((p->type != 0) || - (p->HDisplay != mode->XResolution) || - (p->VDisplay != mode->YResolution) || - (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - status = xf86CheckModeForMonitor(p, pScrn->monitor); - if (status == MODE_OK) { - modeOK = TRUE; - break; - } - } - if (p) { - pMode = xnfcalloc(sizeof(DisplayModeRec), 1); - memcpy((char*)pMode,(char*)p,sizeof(DisplayModeRec)); - pMode->name = xnfstrdup(p->name); - } - } - - /* - * Now, check if there's a valid monitor mode that this one can be matched - * up with from the default modes list. i.e. VESA modes in xf86DefModes.c - */ - if (modeOK && !pMode) { - int refresh = 0, calcrefresh = 0; - DisplayModePtr newMode = NULL; - - for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { - calcrefresh = (int)(((double)(p->Clock * 1000) / - (double)(p->HTotal * p->VTotal)) * 100); - if ((p->type != M_T_DEFAULT) || - (p->HDisplay != mode->XResolution) || - (p->VDisplay != mode->YResolution) || - (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - status = xf86CheckModeForMonitor(p, pScrn->monitor); - if (status == MODE_OK) { - if (calcrefresh > refresh) { - refresh = calcrefresh; - newMode = p; - } - modeOK = TRUE; - } - } - if (newMode) { - pMode = xnfcalloc(sizeof(DisplayModeRec), 1); - memcpy((char*)pMode,(char*)newMode,sizeof(DisplayModeRec)); - pMode->name = xnfstrdup(newMode->name); - } - } - - /* - * Check if there's a valid monitor mode that this one can be matched - * up with. The actual matching is done later. - */ - if (modeOK && !pMode) { - float vrefresh = 0.0f; - int i; - - for (i=0;imonitor->nVrefresh;i++) { - - for (vrefresh = pScrn->monitor->vrefresh[i].hi; - vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) { - - if (vrefresh != (float)0.0f) { - float best_vrefresh; - int int_vrefresh; - - /* Find the best refresh for the Intel chipsets */ - int_vrefresh = I830GetBestRefresh(pScrn, (int)vrefresh); - best_vrefresh = (float)i830refreshes[int_vrefresh]; - - /* Now, grab the best mode from the available refresh */ - pMode = I830GetGTF(mode->XResolution, mode->YResolution, - best_vrefresh, 0, 0); - - pMode->type = M_T_BUILTIN; - - status = xf86CheckModeForMonitor(pMode, pScrn->monitor); - if (status == MODE_OK) { - if (major >= 3) { - if (pMode->Clock * 1000 <= mode->MaxPixelClock) - modeOK = TRUE; - else - modeOK = FALSE; - } else - modeOK = TRUE; - } else - modeOK = FALSE; - pMode->status = status; - } else { - modeOK = FALSE; - } - if (modeOK) break; - } - if (modeOK) break; - } - } - - xf86ErrorFVerb(DEBUG_VERB, - "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution); - xf86ErrorFVerb(DEBUG_VERB, - " ModeAttributes: 0x%x\n", mode->ModeAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinAAttributes: 0x%x\n", mode->WinAAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinBAttributes: 0x%x\n", mode->WinBAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinGranularity: %d\n", mode->WinGranularity); - xf86ErrorFVerb(DEBUG_VERB, - " WinSize: %d\n", mode->WinSize); - xf86ErrorFVerb(DEBUG_VERB, - " WinASegment: 0x%x\n", mode->WinASegment); - xf86ErrorFVerb(DEBUG_VERB, - " WinBSegment: 0x%x\n", mode->WinBSegment); - xf86ErrorFVerb(DEBUG_VERB, - " WinFuncPtr: 0x%lx\n", mode->WinFuncPtr); - xf86ErrorFVerb(DEBUG_VERB, - " BytesPerScanline: %d\n", mode->BytesPerScanline); - xf86ErrorFVerb(DEBUG_VERB, - " XResolution: %d\n", mode->XResolution); - xf86ErrorFVerb(DEBUG_VERB, - " YResolution: %d\n", mode->YResolution); - xf86ErrorFVerb(DEBUG_VERB, - " XCharSize: %d\n", mode->XCharSize); - xf86ErrorFVerb(DEBUG_VERB, - " YCharSize: %d\n", mode->YCharSize); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfPlanes: %d\n", mode->NumberOfPlanes); - xf86ErrorFVerb(DEBUG_VERB, - " BitsPerPixel: %d\n", mode->BitsPerPixel); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfBanks: %d\n", mode->NumberOfBanks); - xf86ErrorFVerb(DEBUG_VERB, - " MemoryModel: %d\n", mode->MemoryModel); - xf86ErrorFVerb(DEBUG_VERB, - " BankSize: %d\n", mode->BankSize); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfImages: %d\n", mode->NumberOfImages); - xf86ErrorFVerb(DEBUG_VERB, - " RedMaskSize: %d\n", mode->RedMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " RedFieldPosition: %d\n", mode->RedFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " GreenMaskSize: %d\n", mode->GreenMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " GreenFieldPosition: %d\n", mode->GreenFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " BlueMaskSize: %d\n", mode->BlueMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " BlueFieldPosition: %d\n", mode->BlueFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " RsvdMaskSize: %d\n", mode->RsvdMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo); - if (major >= 2) { - xf86ErrorFVerb(DEBUG_VERB, - " PhysBasePtr: 0x%lx\n", mode->PhysBasePtr); - if (major >= 3) { - xf86ErrorFVerb(DEBUG_VERB, - " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine); - xf86ErrorFVerb(DEBUG_VERB, - " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages); - xf86ErrorFVerb(DEBUG_VERB, - " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages); - xf86ErrorFVerb(DEBUG_VERB, - " LinRedMaskSize: %d\n", mode->LinRedMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " MaxPixelClock: %ld\n", mode->MaxPixelClock); - } - } - - if (!modeOK) { - VBEFreeModeInfo(mode); - if (pMode) - xfree(pMode); - return NULL; - } - - pMode->status = MODE_OK; - pMode->type = M_T_BUILTIN; - - /* for adjust frame */ - pMode->HDisplay = mode->XResolution; - pMode->VDisplay = mode->YResolution; - - data = xnfcalloc(sizeof(VbeModeInfoData), 1); - data->mode = id; - data->data = mode; - pMode->PrivSize = sizeof(VbeModeInfoData); - pMode->Private = (INT32*)data; - pMode->next = NULL; - return pMode; -} - -/* - * Check the available BIOS modes, and extract those that match the - * requirements into the modePool. Note: modePool is a NULL-terminated - * list. - */ - -DisplayModePtr -I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) -{ - DisplayModePtr pMode, p = NULL, modePool = NULL; - int i = 0; - - for (i = 0; i < 0x7F; i++) { - if ((pMode = CheckMode(pScrn, pVbe, vbe, i, V_MODETYPE_VGA)) != NULL) { - ModeStatus status = MODE_OK; - - /* Check the mode against a specified virtual size (if any) */ - if (pScrn->display->virtualX > 0 && - pMode->HDisplay > pScrn->display->virtualX) { - status = MODE_VIRTUAL_X; - } - if (pScrn->display->virtualY > 0 && - pMode->VDisplay > pScrn->display->virtualY) { - status = MODE_VIRTUAL_Y; - } - if (status != MODE_OK) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Not using mode \"%dx%d\" (%s)\n", - pMode->HDisplay, pMode->VDisplay, - xf86ModeStatusToString(status)); - } else { - if (p == NULL) { - modePool = pMode; - } else { - p->next = pMode; - } - pMode->prev = NULL; - p = pMode; - } - } - } - return modePool; -} - -/* - * Go through the monitor modes and selecting the best set of - * parameters for each BIOS mode. Note: This is only supported in - * VBE version 3.0 or later. - */ -void -I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) -{ - DisplayModePtr pMode; - VbeModeInfoData *data; - - pMode = pScrn->modes; - do { - int clock; - - data = (VbeModeInfoData*)pMode->Private; - data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); - data->block->HorizontalTotal = pMode->HTotal; - data->block->HorizontalSyncStart = pMode->HSyncStart; - data->block->HorizontalSyncEnd = pMode->HSyncEnd; - data->block->VerticalTotal = pMode->VTotal; - data->block->VerticalSyncStart = pMode->VSyncStart; - data->block->VerticalSyncEnd = pMode->VSyncEnd; - data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | - ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); - data->block->PixelClock = pMode->Clock * 1000; - /* XXX May not have this. */ - clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); - if (clock) - data->block->PixelClock = clock; -#ifdef DEBUG - ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", - (double)data->block->PixelClock / 1000000.0, - (double)clock / 1000000.0); -#endif - data->mode |= (1 << 11); - if (pMode->VRefresh != 0) { - data->block->RefreshRate = pMode->VRefresh * 100; - } else { - data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/ - (double)(pMode->HTotal * pMode->VTotal)) * 100); - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n", - (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode); -#ifdef DEBUG - ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - " - " %i %i %i %i %.2f MHz Refresh: %.2f Hz\n", - data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart, - pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay, - pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal, - (double)data->block->PixelClock/1000000.0, - (double)data->block->RefreshRate/100); -#endif - pMode = pMode->next; - } while (pMode != pScrn->modes); -} - void I830PrintModes(ScrnInfoPtr scrp) { From b20b466aaed54708ae9e4676623c8c394a6f00d5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 14:28:55 -0700 Subject: [PATCH 049/257] Remove the now-unused displaySize and pipeDisplaySize. --- src/i830.h | 2 -- src/i830_driver.c | 85 +++-------------------------------------------- 2 files changed, 4 insertions(+), 83 deletions(-) diff --git a/src/i830.h b/src/i830.h index a6cd0402..d96e5aae 100644 --- a/src/i830.h +++ b/src/i830.h @@ -397,14 +397,12 @@ typedef struct _I830Rec { /* These are indexed by the display types */ Bool displayAttached[NumDisplayTypes]; Bool displayPresent[NumDisplayTypes]; - BoxRec displaySize[NumDisplayTypes]; /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; int pipeDevices[MAX_DISPLAY_PIPES]; /* [0] is display plane A, [1] is display plane B. */ Bool pipeEnabled[MAX_DISPLAY_PIPES]; - BoxRec pipeDisplaySize[MAX_DISPLAY_PIPES]; int planeEnabled[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ diff --git a/src/i830_driver.c b/src/i830_driver.c index 813b20ee..06f14d70 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1106,54 +1106,6 @@ PrintDisplayDeviceInfo(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No active displays on Pipe %c.\n", PIPE_NAME(n)); } - - if (pI830->pipeDisplaySize[n].x2 != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Lowest common panel size for pipe %c is %d x %d\n", - PIPE_NAME(n), pI830->pipeDisplaySize[n].x2, - pI830->pipeDisplaySize[n].y2); - } else if (pI830->pipeEnabled[n] && pipe & ~PIPE_CRT_ACTIVE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No display size information available for pipe %c.\n", - PIPE_NAME(n)); - } - } -} - -static void -GetPipeSizes(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int pipe, n; - DisplayType i; - - DPRINTF(PFX, "GetPipeSizes\n"); - - - for (n = 0; n < pI830->availablePipes; n++) { - pipe = (pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK; - pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0; - pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096; - for (i = 0; i < NumKnownDisplayTypes; i++) { - if (pipe & (1 << i) & PIPE_SIZED_DISP_MASK) { - if (pI830->displaySize[i].x2 != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Size of device %s is %d x %d\n", - displayDevices[i], - pI830->displaySize[i].x2, - pI830->displaySize[i].y2); - if (pI830->displaySize[i].x2 < pI830->pipeDisplaySize[n].x2) - pI830->pipeDisplaySize[n].x2 = pI830->displaySize[i].x2; - if (pI830->displaySize[i].y2 < pI830->pipeDisplaySize[n].y2) - pI830->pipeDisplaySize[n].y2 = pI830->displaySize[i].y2; - } - } - } - - if (pI830->pipeDisplaySize[n].x2 == 4096) - pI830->pipeDisplaySize[n].x2 = 0; - if (pI830->pipeDisplaySize[n].y2 == 4096) - pI830->pipeDisplaySize[n].y2 = 0; } } @@ -1172,16 +1124,15 @@ I830DetectDisplayDevice(ScrnInfoPtr pScrn) "\t\t Option \"DisplayInfo\" \"FALSE\"\n" "\t to the Device section of your XF86Config file.\n"); for (i = 0; i < NumKnownDisplayTypes; i++) { + int unusedx, unusedy; if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i], &pI830->displayPresent[i], - &pI830->displaySize[i].x2, - &pI830->displaySize[i].y2)) { + &unusedx, &unusedy)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Display Info: %s: attached: %s, present: %s, size: " + "Display Info: %s: attached: %s, present: %s: " "(%d,%d)\n", displayDevices[i], BOOLTOSTRING(pI830->displayAttached[i]), - BOOLTOSTRING(pI830->displayPresent[i]), - pI830->displaySize[i].x2, pI830->displaySize[i].y2); + BOOLTOSTRING(pI830->displayPresent[i])); } } } @@ -1195,8 +1146,6 @@ I830DetectDisplayDevice(ScrnInfoPtr pScrn) pI830->pipeEnabled[n] = FALSE; } - GetPipeSizes(pScrn); - return TRUE; } @@ -4946,32 +4895,6 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) #endif /* 0 */ } -Bool -I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool ret = TRUE; - - if (pI830->Clone) { - if (pI830->pipeDisplaySize[0].x2 != 0) { - if (x > pI830->pipeDisplaySize[0].x2 || - y > pI830->pipeDisplaySize[0].y2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n"); - return FALSE; - } - } - if (pI830->pipeDisplaySize[1].x2 != 0) { - if (x > pI830->pipeDisplaySize[1].x2 || - y > pI830->pipeDisplaySize[1].y2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n"); - return FALSE; - } - } - } - - return ret; -} - /* * This gets called when gaining control of the VT, and from ScreenInit(). */ From 1f0ba458d02f7d4777c1669aae02138f3a6628c1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 15:28:47 -0700 Subject: [PATCH 050/257] Remove more BIOS stuff, particularly Get/SetDisplayDevices. Now, if there's no hardcoding in the config file, we default to LFP if we detect it from BIOS, and LFP or CRT if we can get EDID out of them. --- src/i830.h | 2 - src/i830_driver.c | 490 +++++----------------------------------------- 2 files changed, 47 insertions(+), 445 deletions(-) diff --git a/src/i830.h b/src/i830.h index d96e5aae..1fc33369 100644 --- a/src/i830.h +++ b/src/i830.h @@ -391,7 +391,6 @@ typedef struct _I830Rec { int monitorSwitch; int operatingDevices; int toggleDevices; - int savedDevices; int lastDevice0, lastDevice1, lastDevice2; /* These are indexed by the display types */ @@ -402,7 +401,6 @@ typedef struct _I830Rec { int availablePipes; int pipeDevices[MAX_DISPLAY_PIPES]; /* [0] is display plane A, [1] is display plane B. */ - Bool pipeEnabled[MAX_DISPLAY_PIPES]; int planeEnabled[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ diff --git a/src/i830_driver.c b/src/i830_driver.c index 06f14d70..99a4c29b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -614,81 +614,6 @@ I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) return i; } -static int -GetDisplayDevices(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; - - DPRINTF(PFX, "GetDisplayDevices\n"); - -#if 0 - { - CARD32 temp; - ErrorF("ADPA is 0x%08x\n", INREG(ADPA)); - ErrorF("DVOA is 0x%08x\n", INREG(DVOA)); - ErrorF("DVOB is 0x%08x\n", INREG(DVOB)); - ErrorF("DVOC is 0x%08x\n", INREG(DVOC)); - ErrorF("LVDS is 0x%08x\n", INREG(LVDS)); - temp = INREG(DVOA_SRCDIM); - ErrorF("DVOA_SRCDIM is 0x%08x (%d x %d)\n", temp, - (temp >> 12) & 0xfff, temp & 0xfff); - temp = INREG(DVOB_SRCDIM); - ErrorF("DVOB_SRCDIM is 0x%08x (%d x %d)\n", temp, - (temp >> 12) & 0xfff, temp & 0xfff); - temp = INREG(DVOC_SRCDIM); - ErrorF("DVOC_SRCDIM is 0x%08x (%d x %d)\n", temp, - (temp >> 12) & 0xfff, temp & 0xfff); - ErrorF("SWF0 is 0x%08x\n", INREG(SWF0)); - ErrorF("SWF4 is 0x%08x\n", INREG(SWF4)); - } -#endif - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x100; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - return pVbe->pInt10->cx & 0xffff; - } else { - if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */ - return PIPE_CRT; - else - return -1; - } -} - -static int -GetBIOSPipe(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; - int pipe; - - DPRINTF(PFX, "GetBIOSPipe:\n"); - - /* single pipe machines should always return Pipe A */ - if (pI830->availablePipes == 1) return 0; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f1c; - pVbe->pInt10->bx = 0x100; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) { - if (pI830->newPipeSwitch) { - pipe = ((pVbe->pInt10->bx & 0x0001)); - } else { - pipe = ((pVbe->pInt10->cx & 0x0100) >> 8); - } - return pipe; - } - - /* failed, assume pipe A */ - return 0; -} - static Bool SetBIOSPipe(ScrnInfoPtr pScrn, int pipe) { @@ -753,185 +678,6 @@ I830Set640x480(ScrnInfoPtr pScrn) return VBESetVBEMode(pI830->pVbe, m, NULL); } -/* This is needed for SetDisplayDevices to work correctly on I915G. - * Enable for all chipsets now as it has no bad side effects, apart - * from slightly longer startup time. - */ -#define I915G_WORKAROUND - -static Bool -SetDisplayDevices(ScrnInfoPtr pScrn, int devices) -{ - I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; - CARD32 temp; - int singlepipe = 0; -#ifdef I915G_WORKAROUND - int getmode1; - Bool setmode = FALSE; -#endif - - DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices); - - if (!pI830->specifiedMonitor) - return TRUE; - -#ifdef I915G_WORKAROUND - if (pI830->preinit) - setmode = TRUE; - if (pI830->leaving) - setmode = FALSE; - if (pI830->closing) - setmode = FALSE; - - if (setmode) { - VBEGetVBEMode(pVbe, &getmode1); - I830Set640x480(pScrn); - } -#endif - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x1; - pVbe->pInt10->cx = devices; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { -#ifdef I915G_WORKAROUND - if (setmode) { - VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL); - } -#endif - pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE; - pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE; - - return TRUE; - } - -#ifdef I915G_WORKAROUND - if (setmode) - VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL); -#endif - - if (devices & 0xff) { - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x1; - pVbe->pInt10->cx = devices & 0xff; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Successfully set display devices to 0x%x.\n",devices & 0xff); - singlepipe = devices & 0xff00; /* set alternate */ - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set display devices to 0x%x.\n",devices & 0xff); - singlepipe = devices; - } - } else - singlepipe = devices; - - if (singlepipe == devices && devices & 0xff00) { - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x1; - pVbe->pInt10->cx = devices & 0xff00; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Successfully set display devices to 0x%x.\n",devices & 0xff00); - singlepipe = devices & 0xff; /* set alternate */ - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to set display devices to 0x%x.\n",devices & 0xff00); - singlepipe = devices; - } - } - - /* LVDS doesn't exist on these */ - if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830)) - singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8)); - - if (pI830->availablePipes == 1) - singlepipe &= 0xFF; - - /* Disable LVDS */ - if (singlepipe & PIPE_LFP) { - /* LFP on PipeA is unlikely! */ - i830SetLVDSPanelPower(pScrn, FALSE); - temp = INREG(LVDS) & ~LVDS_PIPEB_SELECT; - temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP; - OUTREG(LVDS, temp); - i830SetLVDSPanelPower(pScrn, TRUE); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Enabling LVDS directly. Pipe A.\n"); - } else - if (singlepipe & (PIPE_LFP << 8)) { - i830SetLVDSPanelPower(pScrn, FALSE); - temp = INREG(LVDS) | LVDS_PIPEB_SELECT; - temp |= LVDS_PORT_EN | LVDS_CLKA_POWER_UP; - OUTREG(LVDS, temp); - i830SetLVDSPanelPower(pScrn, TRUE); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Enabling LVDS directly. Pipe B.\n"); - } - else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) { - if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) { - i830SetLVDSPanelPower(pScrn, FALSE); - /* Fix up LVDS */ - temp = INREG(LVDS) | LVDS_PIPEB_SELECT; - temp &= ~(LVDS_PORT_EN | LVDS_CLKA_POWER_UP); - OUTREG(LVDS, temp); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling LVDS directly.\n"); - } - } - - /* Now try to program the registers directly if the BIOS failed. */ - temp = INREG(ADPA); - temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK); - temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE); - /* Turn on ADPA */ - if (singlepipe & PIPE_CRT) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Enabling ADPA directly. Pipe A.\n"); - temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT; - OUTREG(ADPA, temp); - } else - if (singlepipe & (PIPE_CRT << 8)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Enabling ADPA directly. Pipe B.\n"); - temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT; - OUTREG(ADPA, temp); - } - else { - if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling ADPA directly.\n"); - temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE; - OUTREG(ADPA, temp); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n"); - temp = INREG(SWF0); - OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff)); - - if (GetDisplayDevices(pScrn) != devices) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n", - GetDisplayDevices(pScrn), devices); - return FALSE; - } - - pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE; - pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE; - - return TRUE; -} - static Bool GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) { @@ -977,52 +723,6 @@ GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached, return FALSE; } -static Bool -GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present, - short *x, short *y) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetDisplayInfo: device: 0x%x\n", device); - - switch (device & 0xff) { - case 0x01: - case 0x02: - case 0x04: - case 0x08: - case 0x10: - case 0x20: - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "GetDisplayInfo: invalid device: 0x%x\n", device & 0xff); - return FALSE; - } - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x300; - pVbe->pInt10->cx = device & 0xff; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - if (attached) - *attached = ((pVbe->pInt10->bx & 0x2) != 0); - if (present) - *present = ((pVbe->pInt10->bx & 0x1) != 0); - if (pVbe->pInt10->cx != (device & 0xff)) { - if (y) { - *y = pVbe->pInt10->cx & 0xffff; - } - if (x) { - *x = (pVbe->pInt10->cx >> 16) & 0xffff; - } - } - return TRUE; - } else - return FALSE; -} - /* * Returns a string matching the device corresponding to the first bit set * in "device". savedDevice is then set to device with that bit cleared. @@ -1109,46 +809,6 @@ PrintDisplayDeviceInfo(ScrnInfoPtr pScrn) } } -static Bool -I830DetectDisplayDevice(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int pipe, n; - DisplayType i; - - /* This seems to lockup some Dell BIOS'. So it's on option to turn on */ - if (pI830->displayInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Broken BIOSes cause the system to hang here.\n" - "\t If you encounter this problem please add \n" - "\t\t Option \"DisplayInfo\" \"FALSE\"\n" - "\t to the Device section of your XF86Config file.\n"); - for (i = 0; i < NumKnownDisplayTypes; i++) { - int unusedx, unusedy; - if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i], - &pI830->displayPresent[i], - &unusedx, &unusedy)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Display Info: %s: attached: %s, present: %s: " - "(%d,%d)\n", displayDevices[i], - BOOLTOSTRING(pI830->displayAttached[i]), - BOOLTOSTRING(pI830->displayPresent[i])); - } - } - } - - /* Check for active devices connected to each display pipe. */ - for (n = 0; n < pI830->availablePipes; n++) { - pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); - if (pipe) - pI830->pipeEnabled[n] = TRUE; - else - pI830->pipeEnabled[n] = FALSE; - } - - return TRUE; -} - static int I830DetectMemory(ScrnInfoPtr pScrn) { @@ -1680,6 +1340,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, } } +#if 0 static int I830UseDDC(ScrnInfoPtr pScrn) { @@ -1744,6 +1405,7 @@ I830UseDDC(ScrnInfoPtr pScrn) return mon_range->max_clock; } +#endif static void I830SetupOutputBusses(ScrnInfoPtr pScrn) @@ -2624,7 +2286,50 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (pI830->MonType1 != PIPE_NONE) + pI830->pipe = 0; + else + pI830->pipe = 1; + + pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; pI830->specifiedMonitor = TRUE; + } else if (I830IsPrimary(pScrn)) { + /* Choose a default set of outputs to use based on what we've detected. */ + if (i830GetLVDSInfoFromBIOS(pScrn)) { + pI830->MonType2 |= PIPE_LFP; + } + + for (i=0; inum_outputs; i++) { + if (pI830->output[i].MonInfo == NULL) + continue; + + switch (pI830->output[i].type) { + case I830_OUTPUT_ANALOG: + case I830_OUTPUT_DVO: + pI830->MonType1 |= PIPE_CRT; + break; + case I830_OUTPUT_LVDS: + pI830->MonType2 |= PIPE_LFP; + break; + case I830_OUTPUT_SDVO: + /* XXX DVO */ + break; + case I830_OUTPUT_UNUSED: + break; + } + } + + if (pI830->MonType1 != PIPE_NONE) + pI830->pipe = 0; + else + pI830->pipe = 1; + pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->operatingDevices = pI8301->operatingDevices; + pI830->pipe = !pI8301->pipe; + pI830->MonType1 = pI8301->MonType1; + pI830->MonType2 = pI8301->MonType2; } if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { @@ -2955,58 +2660,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } } - /* Save old configuration of detected devices */ - pI830->savedDevices = GetDisplayDevices(pScrn); - - if (I830IsPrimary(pScrn)) { - pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn); - - /* Override */ - if (pI830->fixedPipe != -1) { - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { - pI830->pipe = pI830->fixedPipe; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Fixed Pipe setting primary to pipe %s.\n", - pI830->fixedPipe ? "B" : "A"); - } - } - - /* If the monitors aren't setup, read from the current config */ - if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) { - pI830->MonType1 = pI830->savedDevices & 0xff; - pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8; - } else { - /* Here, we've switched pipes from our primary */ - if (pI830->MonType1 == PIPE_NONE && pI830->pipe == 0) - pI830->pipe = 1; - if (pI830->MonType2 == PIPE_NONE && pI830->pipe == 1) - pI830->pipe = 0; - } - - pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; - - if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone) { - /* If we're not dual head or clone, turn off the second head, - * if monitorlayout is also specified. */ - - if (pI830->pipe == 0) - pI830->operatingDevices = pI830->MonType1; - else - pI830->operatingDevices = pI830->MonType2 << 8; - } - - if (pI830->pipe != pI830->origPipe) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Primary Pipe has been switched from original pipe (%s to %s)\n", - pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A"); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->operatingDevices = pI8301->operatingDevices; - pI830->pipe = !pI8301->pipe; - pI830->MonType1 = pI8301->MonType1; - pI830->MonType2 = pI8301->MonType2; - } - /* Buggy BIOS 3066 is known to cause this, so turn this off */ if (pI830->bios_version == 3066) { pI830->displayInfo = FALSE; @@ -3025,27 +2678,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n", pI830->displayInfo ? "enabled" : "disabled"); - if (!I830DetectDisplayDevice(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't detect display devices.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - - if (I830IsPrimary(pScrn)) { - if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to switch to monitor configuration (0x%x)\n", - pI830->operatingDevices); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Please check the devices specified in your MonitorLayout\n"); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "is configured correctly.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - } - PrintDisplayDeviceInfo(pScrn); if (xf86IsEntityShared(pScrn->entityList[0])) { @@ -4718,35 +4350,12 @@ I830BIOSLeaveVT(int scrnIndex, int flags) ResetState(pScrn, TRUE); - if (I830IsPrimary(pScrn)) { - if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to switch back to original display devices (0x%x)\n", - pI830->savedDevices); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Successfully set original devices\n"); - } - } - RestoreHWState(pScrn); RestoreBIOSMemSize(pScrn); if (I830IsPrimary(pScrn)) I830UnbindAGPMemory(pScrn); if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; - - /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */ - if (I830IsPrimary(pScrn)) { - if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to switch back to original display devices (0x%x) (2)\n", - pI830->savedDevices); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Successfully set original devices (2)\n"); - } - } } static Bool @@ -4952,13 +4561,6 @@ I830BIOSEnterVT(int scrnIndex, int flags) "Re-POSTing via int10 failed, trying to continue.\n"); } } - - /* Finally, re-setup the display devices */ - if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to switch to configured display devices\n"); - return FALSE; - } } /* Setup for device monitoring status */ @@ -5534,6 +5136,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI830->cursorOn = on; } +#if 0 /* Disable -- I'll need to look at this whole function later. */ /* double check the display devices are what's configured and try * not to do it twice because of dual heads with the code above */ if (!SetDisplayDevices(pScrn, temp)) { @@ -5552,6 +5155,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) } } } +#endif pI8301->monitorSwitch = temp; pI8301->operatingDevices = temp; From ceb08d28f4a4e9f42c9417938b8541bf1b4e8245 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 15:32:41 -0700 Subject: [PATCH 051/257] Remove the hacky-looking Set640x480. I'll be removing things it depends on (setpipe), and I suspect we'll end up with different hacks for resume, anyway. --- src/i830_driver.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 99a4c29b..20541e0f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -657,27 +657,6 @@ SetPipeAccess(ScrnInfoPtr pScrn) return TRUE; } -static Bool -I830Set640x480(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int m = 0x30; /* 640x480 8bpp */ - - switch (pScrn->depth) { - case 15: - m = 0x40; - break; - case 16: - m = 0x41; - break; - case 24: - m = 0x50; - break; - } - m |= (1 << 15) | (1 << 14); - return VBESetVBEMode(pI830->pVbe, m, NULL); -} - static Bool GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) { @@ -4542,7 +4521,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) */ /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/ CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF); - if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) { + if (temp & 0x80000000) { xf86Int10InfoPtr pInt; xf86DrvMsg(pScrn->scrnIndex, X_INFO, From 2e5d85fb83def483ab1fd96877aae4a89a962b7f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 16:27:24 -0700 Subject: [PATCH 052/257] Turn off the VGA plane when we're setting our native modes. --- src/i830_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index ebe0aa3b..6cc914d5 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -432,6 +432,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) adpa |= ADPA_PIPE_B_SELECT; } + OUTREG(VGACNTRL, VGA_DISP_DISABLE); + /* Set up display timings and PLLs for the pipe. */ if (pipe == 0) { /* First, disable display planes */ From 69083a2fc3ca4a3d06c1985c8a630d5628c1110c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Apr 2006 16:29:14 -0700 Subject: [PATCH 053/257] Remove BIOS save/restore code, fixing VT switching. Removes some other dead code, too. --- src/i830.h | 1 - src/i830_driver.c | 171 ---------------------------------------------- 2 files changed, 172 deletions(-) diff --git a/src/i830.h b/src/i830.h index 1fc33369..87dda252 100644 --- a/src/i830.h +++ b/src/i830.h @@ -567,7 +567,6 @@ extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); extern Bool I830IsPrimary(ScrnInfoPtr pScrn); extern void I830PrintModes(ScrnInfoPtr pScrn); -extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh); extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode); extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode); extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); diff --git a/src/i830_driver.c b/src/i830_driver.c index 20541e0f..eb6370c1 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -544,41 +544,6 @@ GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn) return pVbe->pInt10->cx & 0xffff; } -static int -BitToRefresh(int bits) -{ - int i; - - for (i = 0; i < nrefreshes; i++) - if (bits & (1 << i)) - return i830refreshes[i]; - return 0; -} - -static int -GetRefreshRate(ScrnInfoPtr pScrn, int mode, int *availRefresh) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetRefreshRate\n"); - - /* Only 8-bit mode numbers are supported. */ - if (mode & 0x100) - return 0; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f05; - pVbe->pInt10->bx = (mode & 0xff) | 0x100; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) { - if (availRefresh) - *availRefresh = pVbe->pInt10->bx; - return BitToRefresh(pVbe->pInt10->cx); - } else - return 0; -} - struct panelid { short hsize; short vsize; @@ -592,28 +557,6 @@ struct panelid { char reserved[14]; }; -int -I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh) -{ - int i; - - for (i = nrefreshes - 1; i >= 0; i--) { - /* - * Look for the highest value that the requested (refresh + 2) is - * greater than or equal to. - */ - if (i830refreshes[i] <= (refresh + 2)) - break; - } - /* i can be 0 if the requested refresh was higher than the max. */ - if (i == 0) { - if (refresh >= i830refreshes[nrefreshes - 1]) - i = nrefreshes - 1; - } - - return i; -} - static Bool SetBIOSPipe(ScrnInfoPtr pScrn, int pipe) { @@ -1538,8 +1481,6 @@ PreInitCleanup(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); if (I830IsPrimary(pScrn)) { - SetPipeAccess(pScrn); - pI830->entityPrivate->pScrn_1 = NULL; if (pI830->LpRing) xfree(pI830->LpRing); @@ -2740,8 +2681,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - SetPipeAccess(pScrn); - /* XXX Move this to a header. */ #define VIDEO_BIOS_SCRATCH 0x18 @@ -2963,7 +2902,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->displayWidth = pScrn->displayWidth; - SetPipeAccess(pScrn); I830PrintModes(pScrn); /* PreInit shouldn't leave any state changes, so restore this. */ @@ -3280,63 +3218,6 @@ SaveHWState(ScrnInfoPtr pScrn) vgaHWUnlock(hwp); vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); - if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) - SetBIOSPipe(pScrn, pI830->origPipe); - else - SetPipeAccess(pScrn); - - pVesa = pI830->vesa; - - /* Make sure we save at least this information in case of failure. */ - VBEGetVBEMode(pVbe, &pVesa->stateMode); - pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL); - modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode); - pVesa->savedScanlinePitch = 0; - if (modeInfo) { - if (VBE_MODE_GRAPHICS(modeInfo)) { - VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL); - } - VBEFreeModeInfo(modeInfo); - } - - pVesa = pI830->vesa; - /* - * This save/restore method doesn't work for 845G BIOS, or for some - * other platforms. Enable it in all cases. - */ - /* - * KW: This may have been because of the behaviour I've found on my - * board: The 'save' command actually modifies the interrupt - * registers, turning off the irq & breaking the kernel module - * behaviour. - */ - if (!pI830->vbeRestoreWorkaround) { - CARD16 imr = INREG16(IMR); - CARD16 ier = INREG16(IER); - CARD16 hwstam = INREG16(HWSTAM); - - if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize, - &pVesa->statePage)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n"); - return FALSE; - } - - OUTREG16(IMR, imr); - OUTREG16(IER, ier); - OUTREG16(HWSTAM, hwstam); - } - - pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256, - NULL, FALSE, FALSE); - if (!pVesa->savedPal) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "SaveHWState: VBESetGetPaletteData(GET) failed.\n"); - return FALSE; - } - - VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y); - return TRUE; } @@ -3344,64 +3225,12 @@ static Bool RestoreHWState(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; - VESAPtr pVesa; - Bool restored = FALSE; CARD32 temp; DPRINTF(PFX, "RestoreHWState\n"); - if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) - SetBIOSPipe(pScrn, pI830->origPipe); - else - SetPipeAccess(pScrn); - - pVesa = pI830->vesa; - - if (pVesa->state && pVesa->stateSize) { - CARD16 imr = INREG16(IMR); - CARD16 ier = INREG16(IER); - CARD16 hwstam = INREG16(HWSTAM); - - /* Make a copy of the state. Don't rely on it not being touched. */ - if (!pVesa->pstate) { - pVesa->pstate = xalloc(pVesa->stateSize); - if (pVesa->pstate) - memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize); - } - restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state, - &pVesa->stateSize, &pVesa->statePage); - if (!restored) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "RestoreHWState: VBESaveRestore failed.\n"); - } - /* Copy back */ - if (pVesa->pstate) - memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize); - - OUTREG16(IMR, imr); - OUTREG16(IER, ier); - OUTREG16(HWSTAM, hwstam); - } - /* If that failed, restore the original mode. */ - if (!restored) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Setting the original video mode instead of restoring\n\t" - "the saved state\n"); -#if 0 - I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL); -#endif - } - if (pVesa->savedScanlinePitch) - VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch); - - if (pVesa->savedPal) - VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE); - - VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE); - vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); vgaHWLock(hwp); From 334512e0604c208ffec914374a76d85720c1dcf9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Apr 2006 09:32:45 -0700 Subject: [PATCH 054/257] Don't try to use LVDS by default on chipsets that won't have an LVDS attached. The BIOS tables may still exist, so we can't rely on their presence to indicate LVDS attachment. --- src/i830_driver.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index eb6370c1..fa1019ff 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1702,7 +1702,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) char *s; ClockRangePtr clockRanges; pointer pVBEModule = NULL; - Bool enable; + Bool enable, has_lvds; const char *chipname; unsigned int ver; char v[5]; @@ -1845,6 +1845,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->pVbe = pI8301->pVbe; } + has_lvds = TRUE; switch (pI830->PciInfo->chipType) { case PCI_CHIP_I830_M: chipname = "830M"; @@ -1878,9 +1879,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) break; case PCI_CHIP_I865_G: chipname = "865G"; + has_lvds = FALSE; break; case PCI_CHIP_I915_G: chipname = "915G"; + has_lvds = FALSE; break; case PCI_CHIP_E7221_G: chipname = "E7221 (i915)"; @@ -1890,6 +1893,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) break; case PCI_CHIP_I945_G: chipname = "945G"; + has_lvds = FALSE; break; case PCI_CHIP_I945_GM: chipname = "945GM"; @@ -2215,7 +2219,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. */ - if (i830GetLVDSInfoFromBIOS(pScrn)) { + if (i830GetLVDSInfoFromBIOS(pScrn) && has_lvds) { pI830->MonType2 |= PIPE_LFP; } From 4217ce18cec257cad435adf9ddc9258a3c8164ec Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Apr 2006 09:37:02 -0700 Subject: [PATCH 055/257] Warnings cleanup. --- src/i830_display.c | 3 ++- src/i830_driver.c | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 6cc914d5..3b92e4fa 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -5,6 +5,7 @@ #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" +#include "i830_bios.h" #include "i830_display.h" /** Returns the pixel clock for the given refclk and divisors. */ @@ -398,7 +399,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) ErrorF("clock settings for chosen look %s\n", i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ? "good" : "bad"); - ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, fp); + ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); dspcntr = DISPLAY_PLANE_ENABLE; switch (pScrn->bitsPerPixel) { diff --git a/src/i830_driver.c b/src/i830_driver.c index fa1019ff..7d9bfc22 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1424,7 +1424,7 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->output[i].pDDCBus); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08X\n", + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n", output_type_names[pI830->output[i].type], i, pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); @@ -1445,7 +1445,7 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, &pI830->output[i].i2c_drv); if (ret==TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", pI830->output[i].i2c_drv->modulename, pI830->output[i].pI2CBus->DriverPrivate.uval); } @@ -3167,11 +3167,8 @@ static Bool SaveHWState(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; - VbeModeInfoBlock *modeInfo; - VESAPtr pVesa; DPRINTF(PFX, "SaveHWState\n"); From 11ad8a590d65849be00e1be4e9dd52c1159a4f24 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Apr 2006 09:39:24 -0700 Subject: [PATCH 056/257] Remove the int10 POST on EnterVT. It has been reported to cause crashes now, and I believe it is the responsibility of the kernel to bring the device back to a mostly-sane state on resume anyway. --- src/i830_driver.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 7d9bfc22..23a06317 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4341,37 +4341,6 @@ I830BIOSEnterVT(int scrnIndex, int flags) pScrn->virtualY * pScrn->displayWidth * pI830->cpp); #endif - if (I830IsPrimary(pScrn)) { - /* - * This is needed for restoring from ACPI modes (especially S3) - * so that we warmboot the Video BIOS. Some platforms have problems, - * warm booting when we don't need to, so check that we can call - * the Video BIOS with our saved devices, and only when that fails, - * we'll warm boot it. - */ - /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/ - CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF); - if (temp & 0x80000000) { - xf86Int10InfoPtr pInt; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected resume, re-POSTing.\n"); - - pInt = xf86InitInt10(pI830->pEnt->index); - - /* Now perform our warm boot */ - if (pInt) { - pInt->num = 0xe6; - xf86ExecX86int10 (pInt); - xf86FreeInt10 (pInt); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Re-POSTing via int10.\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-POSTing via int10 failed, trying to continue.\n"); - } - } - } - /* Setup for device monitoring status */ pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF; From 3de82ff3938c6559c90079be0c28dc507d62f79e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Apr 2006 15:10:15 -0700 Subject: [PATCH 057/257] Improve LVDS modes when outputting a CRT+LVDS combo at larger than the LVDS's panel size. This is a hack until we get better clone mode, but it correctly displays a subset of the root on the LVDS by using a correct pixel clock and pipe/display size. --- src/i830_display.c | 100 +++++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 3b92e4fa..681ba2c3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -282,7 +282,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize, adpa; Bool ok; - int refclk = 96000; + int refclk = 96000, pixel_clock; int outputs; ErrorF("Requested pix clock: %d\n", pMode->Clock); @@ -309,7 +309,56 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) return FALSE; } - ok = i830FindBestPLL(pScrn, outputs, pMode->Clock, refclk, &m1, &m2, &n, + htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); + hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); + hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16); + vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); + vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); + vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); + pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); + dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + pixel_clock = pMode->Clock; + if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) && + pI830->panel_fixed_hactive != 0) + { + /* To enable panel fitting, we need to set the pipe timings to that of + * the screen at its full resolution. So, drop the timings from the + * BIOS VBT tables here. + */ + htot = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hblank = (pI830->panel_fixed_hactive - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) + << 16); + hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) | + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff + + pI830->panel_fixed_hsyncwidth - 1) << 16); + + vtot = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vblank = (pI830->panel_fixed_vactive - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) + << 16); + vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | + ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + + pI830->panel_fixed_vsyncwidth - 1) << 16); + /* Hack until we get better clone-mode modesetting. If the mode to be + * programmed is larger than the size of the panel, only display the + * size of the panel. + */ + if (pMode->HDisplay > pI830->panel_fixed_hactive || + pMode->VDisplay > pI830->panel_fixed_vactive) { + dspsize = ((pI830->panel_fixed_vactive - 1) << 16) | + (pI830->panel_fixed_hactive - 1); + pipesrc = ((pI830->panel_fixed_hactive - 1) << 16) | + (pI830->panel_fixed_vactive - 1); + } + pixel_clock = pI830->panel_fixed_clock; + } + + ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -346,44 +395,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); - htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); - hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); - hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16); - vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); - vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); - vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); - pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); - dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); - if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) && - pI830->panel_fixed_hactive != 0) - { - /* To enable panel fitting, we need to set the pipe timings to that of - * the screen at its full resolution. So, drop the timings from the - * BIOS VBT tables here. - */ - htot = (pI830->panel_fixed_hactive - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) - << 16); - hblank = (pI830->panel_fixed_hactive - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1) - << 16); - hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) | - ((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff + - pI830->panel_fixed_hsyncwidth - 1) << 16); - - vtot = (pI830->panel_fixed_vactive - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) - << 16); - vblank = (pI830->panel_fixed_vactive - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1) - << 16); - vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | - ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + - pI830->panel_fixed_vsyncwidth - 1) << 16); - } -#if 0 - ErrorF("htot: 0x%08x, hblank: 0x%08x, hsync: 0x%08x\n", htot, hblank, hsync); - ErrorF("vtot: 0x%08x, vblank: 0x%08x, vsync: 0x%08x\n", vtot, vblank, vsync); +#if 1 + ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n", + (int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1, + (int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1, + (int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1); + ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n", + (int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1, + (int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1, + (int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1); #endif adpa = INREG(ADPA); From c0a2dc608d95f92b0f5a151c623745f09df3afc5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 10 Apr 2006 20:09:37 -0700 Subject: [PATCH 058/257] Save/restore PFIT_CONTROL. Eliminate compiler warnings --- src/i830.h | 3 +- src/i830_bios.c | 1 + src/i830_driver.c | 8 +- src/xvmc/I810XvMC.c | 309 ++++++++++++++++++++++---------------------- 4 files changed, 166 insertions(+), 155 deletions(-) diff --git a/src/i830.h b/src/i830.h index 743a72b8..babbe08d 100644 --- a/src/i830.h +++ b/src/i830.h @@ -268,7 +268,7 @@ typedef struct _I830Rec { I830MemRange *OverlayMem; I830MemRange LinearMem; #endif - unsigned int LinearAlloc; + unsigned long LinearAlloc; XF86ModReqInfo shadowReq; /* to test for later libshadow */ I830MemRange RotatedMem; @@ -481,6 +481,7 @@ typedef struct _I830Rec { CARD32 saveVCLK_POST_DIV; CARD32 saveVGACNTRL; CARD32 saveADPA; + CARD32 savePFIT_CONTROL; } I830Rec; diff --git a/src/i830_bios.c b/src/i830_bios.c index 4264803b..8e575df7 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -26,6 +26,7 @@ */ #ifdef HAVE_CONFIG_H #include "config.h" +#undef VERSION /* XXX edid.h has a VERSION too */ #endif #define _PARSE_EDID_ diff --git a/src/i830_driver.c b/src/i830_driver.c index 61faad07..5ba11085 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2107,9 +2107,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) #endif pI830->LinearAlloc = 0; - if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC, + if (xf86GetOptValULong(pI830->Options, OPTION_LINEARALLOC, &(pI830->LinearAlloc))) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n", + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %luKbytes of memory\n", pI830->LinearAlloc); } @@ -3252,6 +3252,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveADPA = INREG(ADPA); + pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); + vgaHWUnlock(hwp); vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); @@ -3316,6 +3318,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBBASE, pI830->saveDSPBBASE); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); diff --git a/src/xvmc/I810XvMC.c b/src/xvmc/I810XvMC.c index 89aa3ea4..03be2514 100644 --- a/src/xvmc/I810XvMC.c +++ b/src/xvmc/I810XvMC.c @@ -1558,6 +1558,11 @@ static __inline__ void renderDualPrimeinField(uint **datay,uint **datau, // Description: inline function that sets hardware parameters for a Field // encoded macroblock in a frame picture. ***************************************************************************/ +typedef union { + short s[4]; + uint u[2]; +} su_t; + static __inline__ void renderFieldinFrame(uint **datay,uint **datau, uint **datav, XvMCMacroBlock *mb,short *block_ptr, @@ -1568,8 +1573,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[4]; - short bmv[4]; + su_t fmv; + su_t bmv; /* gfxblock dword 1 */ uint dw1[2]; @@ -1589,23 +1594,23 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, (((mb->coded_block_pattern & 0x3) | ((mb->coded_block_pattern & 0xc)<<2))<<22); - fmv[0] = mb->PMV[0][0][1]/2; - fmv[1] = mb->PMV[0][0][0]; - fmv[2] = mb->PMV[1][0][1]/2; - fmv[3] = mb->PMV[1][0][0]; + fmv.s[0] = mb->PMV[0][0][1]/2; + fmv.s[1] = mb->PMV[0][0][0]; + fmv.s[2] = mb->PMV[1][0][1]/2; + fmv.s[3] = mb->PMV[1][0][0]; - bmv[0] = mb->PMV[0][1][1]/2; - bmv[1] = mb->PMV[0][1][0]; - bmv[2] = mb->PMV[1][1][1]/2; - bmv[3] = mb->PMV[1][1][0]; + bmv.s[0] = mb->PMV[0][1][1]/2; + bmv.s[1] = mb->PMV[0][1][0]; + bmv.s[2] = mb->PMV[1][1][1]/2; + bmv.s[3] = mb->PMV[1][1][0]; /* First Y Block */ *dy++ = GFXBLOCK + 4 + (y1size>>2); *dy++ = (1<<30) | (2<<28) | dw1[0]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[0]; - *dy++ = *(uint *)&bmv[0]; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; PACK_CORR_DATA(dy,block_ptr,y1size); block_ptr = (short *)((unsigned long)block_ptr + y1size); @@ -1614,21 +1619,21 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[1]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[2]; - *dy++ = *(uint *)&bmv[2]; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; PACK_CORR_DATA(dy,block_ptr,y2size); block_ptr = (short *)((unsigned long)block_ptr + y2size); /* End Y Blocks */ - fmv[0] /= 2; - fmv[1] /= 2; - fmv[2] /= 2; - fmv[3] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; - bmv[2] /= 2; - bmv[3] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; xy >>= 1; @@ -1637,8 +1642,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[0]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[0]; - *du++ = *(uint *)&bmv[0]; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; if(usize) { PACK_CORR_DATA_SHORT(du,block_ptr); } @@ -1648,8 +1653,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[1]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[2]; - *du++ = *(uint *)&bmv[2]; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; if(usize) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(du,block_ptr); @@ -1662,8 +1667,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[0]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[0]; - *dv++ = *(uint *)&bmv[0]; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; if(vsize) { PACK_CORR_DATA_SHORT(dv,block_ptr); } @@ -1673,8 +1678,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[1]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[2]; - *dv++ = *(uint *)&bmv[2]; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; if(vsize) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(dv,block_ptr); @@ -1701,8 +1706,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[4]; - short bmv[4]; + su_t fmv; + su_t bmv; /* CBP */ uint cbp = (uint)mb->coded_block_pattern; /* gfxblock dword 1 */ @@ -1728,15 +1733,15 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, ((cbp | ((cbp<<2) & 0x30))<<22); - fmv[0] = mb->PMV[0][0][1]/2; - fmv[1] = mb->PMV[0][0][0]; - fmv[2] = mb->PMV[1][0][1]/2; - fmv[3] = mb->PMV[1][0][0]; + fmv.s[0] = mb->PMV[0][0][1]/2; + fmv.s[1] = mb->PMV[0][0][0]; + fmv.s[2] = mb->PMV[1][0][1]/2; + fmv.s[3] = mb->PMV[1][0][0]; - bmv[0] = mb->PMV[0][1][1]/2; - bmv[1] = mb->PMV[0][1][0]; - bmv[2] = mb->PMV[1][1][1]/2; - bmv[3] = mb->PMV[1][1][0]; + bmv.s[0] = mb->PMV[0][1][1]/2; + bmv.s[1] = mb->PMV[0][1][0]; + bmv.s[2] = mb->PMV[1][1][1]/2; + bmv.s[3] = mb->PMV[1][1][0]; /* The i810 cannot use DCT0 directly with field motion, we have to @@ -1772,8 +1777,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[0]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[0]; - *dy++ = *(uint *)&bmv[0]; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; if(dw1[0] & (1<<27)) { PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); } @@ -1786,8 +1791,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[1]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[2]; - *dy++ = *(uint *)&bmv[2]; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; if(dw1[1] & (1<<27)) { top_left_b = (short *)((unsigned long)top_left_b + 16); bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); @@ -1800,15 +1805,15 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, } /* End Y Blocks */ - fmv[0] /= 2; - fmv[1] /= 2; - fmv[2] /= 2; - fmv[3] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; - bmv[2] /= 2; - bmv[3] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; xy >>= 1; @@ -1817,8 +1822,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[0]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[0]; - *du++ = *(uint *)&bmv[0]; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; if(usize) { PACK_CORR_DATA_SHORT(du,block_ptr); } @@ -1828,8 +1833,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[1]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[2]; - *du++ = *(uint *)&bmv[2]; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; if(usize) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(du,block_ptr); @@ -1842,8 +1847,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[0]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[0]; - *dv++ = *(uint *)&bmv[0]; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; if(vsize) { PACK_CORR_DATA_SHORT(dv,block_ptr); } @@ -1853,8 +1858,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[1]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[2]; - *dv++ = *(uint *)&bmv[2]; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; if(vsize) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(dv,block_ptr); @@ -1882,8 +1887,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[2]; - short bmv[2]; + su_t fmv; + su_t bmv; /* gfxblock dword 1 */ uint dw1; @@ -1897,28 +1902,28 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau, (((uint)mb->coded_block_pattern)<<22); - fmv[0] = mb->PMV[0][0][1]; - fmv[1] = mb->PMV[0][0][0]; + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; - bmv[0] = mb->PMV[0][1][1]; - bmv[1] = mb->PMV[0][1][0]; + bmv.s[0] = mb->PMV[0][1][1]; + bmv.s[1] = mb->PMV[0][1][0]; /* Y Block */ *dy++ = GFXBLOCK + 4 + (ysize>>2); *dy++ = (1<<30) | (3<<28) | dw1; *dy++ = xy; *dy++ = (16<<16) | 16; - *dy++ = *(uint *)fmv; - *dy++ = *(uint *)bmv; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; PACK_CORR_DATA(dy,block_ptr,ysize); block_ptr = (short *)((unsigned long)block_ptr + ysize); /* End Y Blocks */ - fmv[0] /= 2; - fmv[1] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; xy >>= 1; @@ -1927,8 +1932,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1; *du++ = xy; *du++ = (8<<16) | 8; - *du++ = *(uint *)fmv; - *du++ = *(uint *)bmv; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; PACK_CORR_DATA(du,block_ptr,usize); block_ptr = (short *)((unsigned long)block_ptr + usize); /* End U Block */ @@ -1938,8 +1943,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1; *dv++ = xy; *dv++ = (8<<16) | 8; - *dv++ = *(uint *)fmv; - *dv++ = *(uint *)bmv; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; PACK_CORR_DATA(dv,block_ptr,vsize); block_ptr = (short *)((unsigned long)block_ptr + vsize); /* End V Block */ @@ -1963,8 +1968,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[4]; - short bmv[4]; + su_t fmv; + su_t bmv; short * top_left_b = NULL; short * top_right_b = NULL; @@ -1982,11 +1987,11 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, uint dw1 = type_table[mb->macroblock_type & 0xf] | (((uint)mb->coded_block_pattern)<<22); - fmv[0] = mb->PMV[0][0][1]; - fmv[1] = mb->PMV[0][0][0]; + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; - bmv[0] = mb->PMV[0][1][1]; - bmv[1] = mb->PMV[0][1][0]; + bmv.s[0] = mb->PMV[0][1][1]; + bmv.s[1] = mb->PMV[0][1][0]; /* It is easiest to find out what blocks are in need of reading first @@ -2026,8 +2031,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, *dy++ = (1<<30) | (3<<28) | dw1; *dy++ = xy; *dy++ = (16<<16) | 16; - *dy++ = *(uint *)fmv; - *dy++ = *(uint *)bmv; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; if(dw1 & (1<<27)) { PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b); top_left_b = (short *)((unsigned long)top_left_b + 64); @@ -2046,11 +2051,11 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, } /* End Y Block */ - fmv[0] /= 2; - fmv[1] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; xy >>= 1; @@ -2059,8 +2064,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1; *du++ = xy; *du++ = (8<<16) | 8; - *du++ = *(uint *)fmv; - *du++ = *(uint *)bmv; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; PACK_CORR_DATA(du,block_ptr,usize); block_ptr = (short *)((unsigned long)block_ptr + usize); @@ -2069,8 +2074,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1; *dv++ = xy; *dv++ = (8<<16) | 8; - *dv++ = *(uint *)fmv; - *dv++ = *(uint *)bmv; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; PACK_CORR_DATA(dv,block_ptr,vsize); block_ptr = (short *)((unsigned long)block_ptr + vsize); @@ -2093,8 +2098,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[4]; - short bmv[4]; + su_t fmv; + su_t bmv; /* gfxblock dword 1 */ uint dw1[2]; @@ -2115,23 +2120,23 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, ((mb->coded_block_pattern & 0xc)<<2))<<22) | 3<<12 | 3<<6 | 3<<3 | 2; - fmv[0] = mb->PMV[0][0][1]; - fmv[1] = mb->PMV[0][0][0]; - bmv[0] = mb->PMV[1][0][1]; - bmv[1] = mb->PMV[1][0][0]; + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + bmv.s[0] = mb->PMV[1][0][1]; + bmv.s[1] = mb->PMV[1][0][0]; - fmv[2] = mb->PMV[0][0][1]; - fmv[3] = mb->PMV[0][0][0]; - bmv[2] = mb->PMV[1][1][1]; - bmv[3] = mb->PMV[1][1][0]; + fmv.s[2] = mb->PMV[0][0][1]; + fmv.s[3] = mb->PMV[0][0][0]; + bmv.s[2] = mb->PMV[1][1][1]; + bmv.s[3] = mb->PMV[1][1][0]; /* First Y Block */ *dy++ = GFXBLOCK + 4 + (y1size>>2); *dy++ = (1<<30) | (2<<28) | dw1[0]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)fmv; - *dy++ = *(uint *)bmv;; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0];; PACK_CORR_DATA(dy,block_ptr,y1size); block_ptr = (short *)((unsigned long)block_ptr + y1size); @@ -2140,20 +2145,20 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[1]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[2]; - *dy++ = *(uint *)&bmv[2]; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; PACK_CORR_DATA(dy,block_ptr,y2size); block_ptr = (short *)((unsigned long)block_ptr + y2size); - fmv[0] /= 2; - fmv[1] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; - fmv[2] /= 2; - fmv[3] /= 2; - bmv[2] /= 2; - bmv[3] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; xy >>= 1; @@ -2162,8 +2167,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[0]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)fmv; - *du++ = *(uint *)bmv; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; if(dw1[0] & (1<<23)) { PACK_CORR_DATA_SHORT(du,block_ptr); } @@ -2173,8 +2178,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[1]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[2]; - *du++ = *(uint *)&bmv[2]; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; if(dw1[1] & (1<<23)) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(du,block_ptr); @@ -2187,8 +2192,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[0]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)fmv; - *dv++ = *(uint *)bmv; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; if(dw1[0] & (1<<22)) { PACK_CORR_DATA_SHORT(dv,block_ptr); } @@ -2198,8 +2203,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[1]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[2]; - *dv++ = *(uint *)&bmv[2]; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; if(dw1[1] & (1<<22)) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(dv,block_ptr); @@ -2228,8 +2233,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, register uint *dv = *datav; /* Motion Vectors */ - short fmv[4]; - short bmv[4]; + su_t fmv; + su_t bmv; /* gfxblock dword 1 */ uint dw1[2]; @@ -2255,15 +2260,15 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) | 3<<12 | 3<<6 | 3<<3 | 2; - fmv[0] = mb->PMV[0][0][1]; - fmv[1] = mb->PMV[0][0][0]; - bmv[0] = mb->PMV[1][0][1]; - bmv[1] = mb->PMV[1][0][0]; + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + bmv.s[0] = mb->PMV[1][0][1]; + bmv.s[1] = mb->PMV[1][0][0]; - fmv[2] = mb->PMV[0][0][1]; - fmv[3] = mb->PMV[0][0][0]; - bmv[2] = mb->PMV[1][1][1]; - bmv[3] = mb->PMV[1][1][0]; + fmv.s[2] = mb->PMV[0][0][1]; + fmv.s[3] = mb->PMV[0][0][0]; + bmv.s[2] = mb->PMV[1][1][1]; + bmv.s[3] = mb->PMV[1][1][0]; /* The i810 cannot use DCT0 directly with field motion, we have to @@ -2299,8 +2304,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[0]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)fmv; - *dy++ = *(uint *)bmv; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; if(cbp & 0x20) { PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); } @@ -2313,8 +2318,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *dy++ = (1<<30) | (2<<28) | dw1[1]; *dy++ = xy; *dy++ = (8<<16) | 16; - *dy++ = *(uint *)&fmv[2]; - *dy++ = *(uint *)&bmv[2]; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; if(cbp & 0x20) { top_left_b = (short *)((unsigned long)top_left_b + 16); bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); @@ -2328,15 +2333,15 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, /* End Y Blocks */ - fmv[0] /= 2; - fmv[1] /= 2; - bmv[0] /= 2; - bmv[1] /= 2; + fmv.s[0] /= 2; + fmv.s[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; - fmv[2] /= 2; - fmv[3] /= 2; - bmv[2] /= 2; - bmv[3] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; xy >>= 1; @@ -2345,8 +2350,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[0]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)fmv; - *du++ = *(uint *)bmv; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; if(cbp & (1<<23)) { PACK_CORR_DATA_SHORT(du,block_ptr); } @@ -2356,8 +2361,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *du++ = (2<<30) | (1<<28) | dw1[1]; *du++ = xy; *du++ = (4<<16) | 8; - *du++ = *(uint *)&fmv[2]; - *du++ = *(uint *)&bmv[2]; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; if(cbp & (1<<23)) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(du,block_ptr); @@ -2370,8 +2375,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[0]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)fmv; - *dv++ = *(uint *)bmv; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; if(cbp & (1<<22)) { PACK_CORR_DATA_SHORT(dv,block_ptr); } @@ -2381,8 +2386,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, *dv++ = (3<<30) | (1<<28) | dw1[1]; *dv++ = xy; *dv++ = (4<<16) | 8; - *dv++ = *(uint *)&fmv[2]; - *dv++ = *(uint *)&bmv[2]; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; if(cbp & (1<<22)) { block_ptr = (short *)((unsigned long)block_ptr + 16); PACK_CORR_DATA_SHORT(dv,block_ptr); From 185b5251419724fa9377421d67981daa674908c8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Apr 2006 20:25:13 -0700 Subject: [PATCH 059/257] Add missing MIT copyright licenses, which should have been on all versions. --- src/i830_debug.c | 27 +++++++++++++++++++++++++++ src/i830_debug.h | 27 +++++++++++++++++++++++++++ src/i830_display.c | 27 +++++++++++++++++++++++++++ src/i830_display.h | 27 +++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/src/i830_debug.c b/src/i830_debug.c index 96426c46..b5442577 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -1,3 +1,30 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/i830_debug.h b/src/i830_debug.h index c02ff256..269f03ea 100644 --- a/src/i830_debug.h +++ b/src/i830_debug.h @@ -1,2 +1,29 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + void i830TakeRegSnapshot(ScrnInfoPtr pScrn); void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn); diff --git a/src/i830_display.c b/src/i830_display.c index e76c5810..8b2c881d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1,3 +1,30 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/i830_display.h b/src/i830_display.h index 101d65bd..d8e4e5e8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -1,3 +1,30 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); From 59f88955f57cf0f98458b57418dae25cf53ca180 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 12 Apr 2006 11:11:14 -0700 Subject: [PATCH 060/257] Automatically enable clone mode if we detect two active outputs. --- src/i830_driver.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 5ba11085..4d29907e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2256,6 +2256,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) else pI830->pipe = 1; pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; + + if (pI830->MonType1 != 0 && pI830->MonType2 != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Enabling clone mode by default\n"); + pI830->Clone = TRUE; + } } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); pI830->operatingDevices = pI8301->operatingDevices; @@ -2296,13 +2302,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) { - if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout " - "defined for use in a DualHead or Clone setup.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 " "cannot be type NONE in Dual or Clone setup.\n"); From d6edffee7d987ef551e1a94d9fac21beb72a9598 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 12 Apr 2006 12:16:51 -0700 Subject: [PATCH 061/257] Initial support for pre-i915 PLL programming. Untested. --- src/i810_reg.h | 22 ++++--- src/i830_display.c | 148 ++++++++++++++++++++++++++++----------------- 2 files changed, 104 insertions(+), 66 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 6976553f..92d9cf9e 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -705,16 +705,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define DPLL_DVO_HIGH_SPEED (1 << 30) # define DPLL_SYNCLOCK_ENABLE (1 << 29) # define DPLL_VGA_MODE_DIS (1 << 28) -# define DPLLB_MODE_DAC_SERIAL (1 << 26) -# define DPLLB_MODE_LVDS (2 << 26) -# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) -# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) -# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) -# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) -# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 -# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 +# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +# define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */ +# define DPLL_FPA01_P1_POS_DIV_MASK_I830 0x001f0000 /* i830 */ +# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ # define PLL_REF_INPUT_DREFCLK (0 << 13) -# define PLL_REF_INPUT_TVCLKIN (2 << 13) +# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +# define PLL_REF_INPUT_TVCLKINBC (2 << 13) # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) # define SDVO_MULTIPLIER_MASK 0x000000ff diff --git a/src/i830_display.c b/src/i830_display.c index 8b2c881d..c55609d5 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -66,10 +66,8 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, I830Ptr pI830 = I830PTR(pScrn); int p, m, vco, dotclock; int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n; - int min_p, max_p; + int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot; - min_p = 5; - max_p = 80; if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { min_m1 = 10; max_m1 = 20; @@ -79,23 +77,36 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, max_m = 120; min_n = 3; max_n = 8; + min_p1 = 1; + max_p1 = 8; if (outputs & PIPE_LCD_ACTIVE) { min_p = 7; max_p = 98; + } else { + min_p = 5; + max_p = 80; } + min_vco = 1400000; + max_vco = 2800000; + min_dot = 20000; + max_dot = 400000; } else { - min_m1 = 16; - max_m1 = 24; - min_m2 = 7; - max_m2 = 11; - min_m = 90; - max_m = 130; - min_n = 4; - max_n = 8; - if (outputs & PIPE_LCD_ACTIVE) { - min_n = 3; - min_m = 88; - } + min_m1 = 18; + max_m1 = 26; + min_m2 = 6; + max_m2 = 16; + min_m = 96; + max_m = 140; + min_n = 3; + max_n = 16; + min_p1 = 2; + max_p1 = 18; + min_vco = 930000; + max_vco = 1400000; + min_dot = 20000; + max_dot = 350000; + min_p = 4; + max_p = 128; } p = p1 * p2; @@ -103,7 +114,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, vco = refclk * m / n; dotclock = i830_clock(refclk, m1, m2, n, p1, p2); - if (p1 < 1 || p1 > 8) + if (p1 < min_p1 || p1 > max_p1) return FALSE; if (p < min_p || p > max_p) return FALSE; @@ -117,12 +128,12 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, return FALSE; if (n < min_n || n > max_n) return FALSE; - if (vco < 1400000 || vco > 2800000) + if (vco < min_vco || vco > max_vco) return FALSE; /* XXX: We may need to be checking "Dot clock" depending on the multiplier, * output, etc., rather than just a single range. */ - if (dotclock < 20000 || dotclock > 400000) + if (dotclock < min_dot || dotclock > max_dot) return FALSE; return TRUE; @@ -215,36 +226,48 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; int err = target; - int min_m1, max_m1, min_m2, max_m2; + int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1; if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { min_m1 = 10; max_m1 = 20; min_m2 = 5; max_m2 = 9; + min_n = 3; + max_n = 8; + min_p1 = 1; + max_p1 = 8; + if (outputs & PIPE_LCD_ACTIVE) { + if (target < 200000) /* XXX: Is this the right cutoff? */ + p2 = 14; + else + p2 = 7; + } else { + if (target < 200000) + p2 = 10; + else + p2 = 5; + } } else { - min_m1 = 16; - max_m1 = 24; - min_m2 = 7; - max_m2 = 11; + min_m1 = 18; + max_m1 = 26; + min_m2 = 6; + max_m2 = 16; + min_n = 3; + max_n = 16; + min_p1 = 2; + max_p1 = 18; + if (target < 165000) + p2 = 4; + else + p2 = 2; } - if (outputs & PIPE_LCD_ACTIVE) { - if (target < 200000) /* XXX: Is this the right cutoff? */ - p2 = 14; - else - p2 = 7; - } else { - if (target < 200000) - p2 = 10; - else - p2 = 5; - } for (m1 = min_m1; m1 <= max_m1; m1++) { for (m2 = min_m2; m2 < max_m2; m2++) { - for (n = 3; n <= 8; n++) { - for (p1 = 1; p1 <= 8; p1++) { + for (n = min_n; n <= max_n; n++) { + for (p1 = min_p1; p1 <= max_p1; p1++) { int clock, this_err; if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, @@ -309,7 +332,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize, adpa; Bool ok; - int refclk = 96000, pixel_clock; + int refclk, pixel_clock; int outputs; ErrorF("Requested pix clock: %d\n", pMode->Clock); @@ -385,6 +408,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pixel_clock = pI830->panel_fixed_clock; } + if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + refclk = 96000; + } else { + refclk = 48000; + } ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) { @@ -394,28 +422,34 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) } dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; - if (outputs & PIPE_LCD_ACTIVE) - dpll |= DPLLB_MODE_LVDS; - else - dpll |= DPLLB_MODE_DAC_SERIAL; - - dpll |= (1 << (p1 - 1)) << 16; - switch (p2) { - case 5: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; - break; - case 7: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; - break; - case 10: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; - break; - case 14: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; - break; + if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + if (outputs & PIPE_LCD_ACTIVE) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + dpll |= (1 << (p1 - 1)) << 16; + switch (p2) { + case 5: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; + } + } else { + dpll |= (p1 - 2) << 16; + if (p2 == 4) + dpll |= PLL_P2_DIVIDE_BY_4; } + if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE)) - dpll |= PLL_REF_INPUT_TVCLKIN; + dpll |= PLL_REF_INPUT_TVCLKINBC; else dpll |= PLL_REF_INPUT_DREFCLK; dpll |= SDV0_DEFAULT_MULTIPLIER; From 830fa81792a613fe2127a2b89a3eaa326f56114c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 12 Apr 2006 21:55:31 +0100 Subject: [PATCH 062/257] fix typo --- src/i830_video.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index afdc99aa..0ae68607 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -1390,9 +1390,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* When in dual head with different bpp setups we need to refresh the * color key, so let's reset the video parameters and refresh here */ -#if 0 if (pI830->entityPrivate) -#endif I830ResetVideo(pScrn); /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ From 62652127cd12f5a0fc9364285b81d2661372148a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 15 Apr 2006 12:16:46 -0700 Subject: [PATCH 063/257] Check for LVDS BIOS tables exactly once at startup. While there, dump the BIOS data to /tmp/xf86-video-intel-VBIOS, for offline debugging. --- src/i830_bios.c | 22 ++++++++++++++++++++++ src/i830_display.c | 3 +-- src/i830_driver.c | 11 +++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 8e575df7..c9ca8819 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -47,6 +47,27 @@ /* XXX */ #define INTEL_VBIOS_SIZE (64 * 1024) +static void +i830DumpBIOSToFile(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + const char *filename = "/tmp/xf86-video-intel-VBIOS"; + FILE *f; + + f = fopen(filename, "w"); + if (f == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename); + return; + } + if (fwrite(pI830->VBIOS, INTEL_VBIOS_SIZE, 1, f) != 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n"); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Wrote BIOS contents to %s\n", + filename); + fclose(f); +} + /** * Loads the Video BIOS and checks that the VBT exists. * @@ -76,6 +97,7 @@ i830GetBIOS(ScrnInfoPtr pScrn) xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE); } + i830DumpBIOSToFile(pScrn); vbt_off = INTEL_BIOS_16(0x1a); if (vbt_off >= INTEL_VBIOS_SIZE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", diff --git a/src/i830_display.c b/src/i830_display.c index c55609d5..4cdc2b1b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -368,8 +368,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); pixel_clock = pMode->Clock; - if (outputs & PIPE_LCD_ACTIVE && i830GetLVDSInfoFromBIOS(pScrn) && - pI830->panel_fixed_hactive != 0) + if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0) { /* To enable panel fitting, we need to set the pipe timings to that of * the screen at its full resolution. So, drop the timings from the diff --git a/src/i830_driver.c b/src/i830_driver.c index 4d29907e..8930db06 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2139,6 +2139,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType2 = PIPE_NONE; pI830->specifiedMonitor = FALSE; + /* Always check for LVDS info once at startup. We hook in the BIOS data + * dumping here (this should be cleaner) and we get to rely on having the + * LVDS info later on. + */ + if (!i830GetLVDSInfoFromBIOS(pScrn)) + has_lvds = FALSE; + if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { char *Mon1; @@ -2227,7 +2234,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. */ - if (i830GetLVDSInfoFromBIOS(pScrn) && has_lvds) { + if (has_lvds) { pI830->MonType2 |= PIPE_LFP; } @@ -2743,7 +2750,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * rely on the scaler so that we can display any mode smaller than or the * same size as the panel. */ - if (!i830GetLVDSInfoFromBIOS(pScrn)) { + if (!has_lvds) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to locate panel information in BIOS VBT tables\n"); PreInitCleanup(pScrn); From 786ee3df1726f08953167d05f7fa1930452703bb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 16 Apr 2006 13:05:35 -0500 Subject: [PATCH 064/257] Add a standalone program for parsing VBT. --- configure.ac | 1 + src/Makefile.am | 2 +- src/bios_reader/.gitignore | 1 + src/bios_reader/Makefile.am | 4 + src/bios_reader/bios_reader.c | 163 ++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 src/bios_reader/.gitignore create mode 100644 src/bios_reader/Makefile.am create mode 100644 src/bios_reader/bios_reader.c diff --git a/configure.ac b/configure.ac index 78824330..34672969 100644 --- a/configure.ac +++ b/configure.ac @@ -116,5 +116,6 @@ AC_OUTPUT([ Makefile src/Makefile src/xvmc/Makefile + src/bios_reader/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 1b30c656..1789af23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = xvmc +SUBDIRS = xvmc bios_reader # this is obnoxious: # -module lets us name the module exactly how we want # -avoid-version prevents gratuitous .0.0.0 version numbers on the end diff --git a/src/bios_reader/.gitignore b/src/bios_reader/.gitignore new file mode 100644 index 00000000..3e325072 --- /dev/null +++ b/src/bios_reader/.gitignore @@ -0,0 +1 @@ +bios_reader diff --git a/src/bios_reader/Makefile.am b/src/bios_reader/Makefile.am new file mode 100644 index 00000000..f18a00c3 --- /dev/null +++ b/src/bios_reader/Makefile.am @@ -0,0 +1,4 @@ +AM_CFLAGS = @XORG_CFLAGS@ + +noinst_PROGRAMS = bios_reader + diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c new file mode 100644 index 00000000..a52bcc72 --- /dev/null +++ b/src/bios_reader/bios_reader.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#include +#include +#include +#include + +#define _PARSE_EDID_ +#include "edid.h" + +/* Define some types so we can reuse i830_bios.h */ +typedef void *ScrnInfoPtr; +typedef int Bool; +#define TRUE 1 +#define FALSE 0 +#include "../i830_bios.h" + + +/* Make a fake pI830 so we can easily pull i830_bios.c code in here. */ +struct _fake_i830 { + CARD8 *VBIOS; +}; +struct _fake_i830 I830; +struct _fake_i830 *pI830 = &I830; + +#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr]) +#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \ + (pI830->VBIOS[_addr + 1] << 8)) +#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \ + (pI830->VBIOS[_addr + 1] << 8) \ + (pI830->VBIOS[_addr + 2] << 16) \ + (pI830->VBIOS[_addr + 3] << 24)) + +int main(int argc, char **argv) +{ + FILE *f; + int bios_size = 65536; + struct vbt_header *vbt; + struct bdb_header *bdb; + int vbt_off, bdb_off, bdb_block_off, block_size; + int panel_type = -1, i; + char *filename = "bios"; + + if (argc == 2) + filename = argv[1]; + + f = fopen(filename, "r"); + if (!f) { + printf("Couldn't open %s\n", filename); + return 1; + } + + pI830->VBIOS = calloc(1, bios_size); + if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size) + return 1; + + vbt_off = INTEL_BIOS_16(0x1a); + printf("VBT offset: %08x\n", vbt_off); + vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); + printf("VBT sig: %20s\n", vbt->signature); + printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100); + + bdb_off = vbt_off + vbt->bdb_offset; + bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off); + printf("BDB sig: %16s\n", bdb->signature); + printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100); + for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size; + bdb_block_off += block_size) + { + int start = bdb_off + bdb_block_off; + int id; + struct lvds_bdb_1 *lvds1; + struct lvds_bdb_2 *lvds2; + struct lvds_bdb_2_fp_params *fpparam; + struct lvds_bdb_2_fp_edid_dtd *fptiming; + CARD8 *timing_ptr; + + id = INTEL_BIOS_8(start); + block_size = INTEL_BIOS_16(start + 1) + 3; + printf("BDB block type %03d size %d\n", id, block_size); + switch (id) { + case 40: + lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start); + panel_type = lvds1->panel_type; + printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps); + break; + case 41: + if (panel_type == -1) { + printf("Found panel block with no panel type\n"); + break; + } + + lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start); + + printf("Entries per table: %d\n", lvds2->table_size); + for (i = 0; i < 16; i++) { + char marker; + fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + bdb_off + lvds2->panels[i].fp_params_offset); + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + bdb_off + lvds2->panels[i].fp_edid_dtd_offset); + timing_ptr = pI830->VBIOS + bdb_off + + lvds2->panels[i].fp_edid_dtd_offset; + if (fpparam->terminator != 0xffff) { + /* Apparently the offsets are wrong for some BIOSes, so we + * try the other offsets if we find a bad terminator. + */ + fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + bdb_off + lvds2->panels[i].fp_params_offset + 8); + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8); + timing_ptr = pI830->VBIOS + bdb_off + + lvds2->panels[i].fp_edid_dtd_offset + 8; + + if (fpparam->terminator != 0xffff) + continue; + } + if (i == panel_type) + marker = '*'; + else + marker = ' '; + printf("%c Panel index %02i xres %d yres %d clock %d\n", marker, + i, fpparam->x_res, fpparam->y_res, + _PIXEL_CLOCK(timing_ptr)); + printf(" %d %d %d %d %d %d %d %d\n", + _H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr), + _H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr), + _V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr), + _V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr)); + } + + printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res); + break; + } + } + + return 0; +} From ee7be006b63b6b1ce7f786b045fb8f26d337433c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 16 Apr 2006 13:13:42 -0500 Subject: [PATCH 065/257] Bug #6589: Use alternate offsets to successfully get at the panel data for some broken video BIOSes. --- src/i830_bios.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/i830_bios.c b/src/i830_bios.c index c9ca8819..00cec522 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -173,6 +173,21 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) timing_ptr = pI830->VBIOS + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset; + if (fpparam->terminator != 0xffff) { + /* Apparently the offsets are wrong for some BIOSes, so we + * try the other offsets if we find a bad terminator. + */ + fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + bdb_off + lvds2->panels[panel_type].fp_params_offset + 8); + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8); + timing_ptr = pI830->VBIOS + bdb_off + + lvds2->panels[panel_type].fp_edid_dtd_offset + 8; + + if (fpparam->terminator != 0xffff) + continue; + } + pI830->PanelXRes = fpparam->x_res; pI830->PanelYRes = fpparam->y_res; xf86DrvMsg(pScrn->scrnIndex, X_INFO, From 365b4a53ee965002a5452e6f6016b528e51cee69 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 17 Apr 2006 01:12:28 -0500 Subject: [PATCH 066/257] Disable the BIOS dump-to-file since it's a trivial local DOS, and I can just ask people to turn it on and recompile when I need to. --- src/i830_bios.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 00cec522..19b1b5ad 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -97,7 +97,9 @@ i830GetBIOS(ScrnInfoPtr pScrn) xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE); } - i830DumpBIOSToFile(pScrn); + if (0) + i830DumpBIOSToFile(pScrn); + vbt_off = INTEL_BIOS_16(0x1a); if (vbt_off >= INTEL_VBIOS_SIZE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", From 33413a3cf34b06e3207fe1cdb733d586d55a4337 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 17 Apr 2006 13:42:57 -0700 Subject: [PATCH 067/257] Remove some dead code and one particularly useless debug printf. --- src/i830_display.c | 87 ---------------------------------------------- 1 file changed, 87 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 4cdc2b1b..0e3bb471 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -139,81 +139,6 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, return TRUE; } -#if 0 -int -i830ReadAndReportPLL(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp, dpll; - int refclk, m1, m2, n, p1, p2; - - refclk = 96000; /* XXX: The refclk may be 100000 for the LVDS */ - - dpll = INREG(DPLL_A); - switch ((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> 16) { - case 0x01: - p1 = 1; - break; - case 0x02: - p1 = 2; - break; - case 0x04: - p1 = 3; - break; - case 0x08: - p1 = 4; - break; - case 0x10: - p1 = 5; - break; - case 0x20: - p1 = 6; - break; - case 0x40: - p1 = 7; - break; - case 0x80: - p1 = 8; - break; - default: - FatalError("Unknown p1 clock div: 0x%x\n", - dpll & DPLL_FPA01_P1_POST_DIV_MASK); - } - - switch (dpll & DPLL_P2_CLOCK_DIV_MASK) { - case DPLL_DAC_SERIAL_P2_CLOCK_DIV_5: - p2 = 5; - break; - case DPLL_DAC_SERIAL_P2_CLOCK_DIV_10: - p2 = 10; - break; -/* XXX: - case DPLLB_LVDS_P2_CLOCK_DIV_7: - p2 = 7; - break; - case DPLLB_LVDS_P2_CLOCK_DIV_14: - p2 = 14; - break; -*/ - default: - FatalError("Unknown p2 clock div: 0x%x\n", dpll & DPLL_P2_CLOCK_DIV_MASK); - } - - if (dpll & DISPLAY_RATE_SELECT_FPA1) - temp = INREG(FPA1); - else - temp = INREG(FPA0); - n = (temp & FP_N_DIV_MASK) >> 16; - m1 = (temp & FP_M1_DIV_MASK) >> 8; - m2 = (temp & FP_M2_DIV_MASK); - - i830PrintPll("FPA", refclk, m1, m2, n, p1, p2); - ErrorF("clock settings for FPA0 look %s\n", - i830PllIsValid(refclk, m1, m2, n, p1, p2) ? "good" : "bad"); - ErrorF("clock regs: 0x%08x, 0x%08x\n", dpll, temp); -} -#endif - /** * Returns a set of divisors for the desired target clock with the given refclk, * or FALSE. Divisor values are the actual divisors for @@ -466,19 +391,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) (int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1); #endif - adpa = INREG(ADPA); - adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH); - adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE); - adpa |= ADPA_DAC_ENABLE; - if (pMode->Flags & V_PHSYNC) - adpa |= ADPA_HSYNC_ACTIVE_HIGH; - if (pMode->Flags & V_PVSYNC) - adpa |= ADPA_VSYNC_ACTIVE_HIGH; - i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); - ErrorF("clock settings for chosen look %s\n", - i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, p1, p2) ? - "good" : "bad"); ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); dspcntr = DISPLAY_PLANE_ENABLE; From a371a04a57620b7128e3c4395bc7c2ac55effe19 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 17 Apr 2006 14:10:50 -0700 Subject: [PATCH 068/257] Use the IS_I9XX macro intead of >= i915G, since by PCI ID number, 855GM > 915. --- src/i830_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 0e3bb471..8eebfca3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -68,7 +68,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n; int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot; - if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + if (IS_I9XX(pI830)) { min_m1 = 10; max_m1 = 20; min_m2 = 5; @@ -153,7 +153,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, int err = target; int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1; - if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + if (IS_I9XX(pI830)) { min_m1 = 10; max_m1 = 20; min_m2 = 5; @@ -332,7 +332,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pixel_clock = pI830->panel_fixed_clock; } - if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + if (IS_I9XX(pI830)) { refclk = 96000; } else { refclk = 48000; @@ -346,7 +346,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) } dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; - if (pI830->PciInfo->chipType >= PCI_CHIP_I915_G) { + if (IS_I9XX(pI830)) { if (outputs & PIPE_LCD_ACTIVE) dpll |= DPLLB_MODE_LVDS; else From d8f7dfac769d7b03f069306b1296bb2e1e08b009 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 19 Apr 2006 10:45:13 -0700 Subject: [PATCH 069/257] Start bringing in some SDVO code, mostly from airlied. --- src/Makefile.am | 3 +- src/i810_reg.h | 17 ++++++++ src/i830.h | 6 ++- src/i830_display.c | 27 +++++++++++- src/i830_driver.c | 67 +++++++++++++++++------------ src/i830_sdvo.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 src/i830_sdvo.c diff --git a/src/Makefile.am b/src/Makefile.am index 1789af23..da48149e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,7 +61,8 @@ i810_drv_la_SOURCES = \ i830_modes.c \ i830_video.c \ i830_rotate.c \ - i830_randr.c + i830_randr.c \ + i830_sdvo.c if DRI i810_drv_la_SOURCES += \ diff --git a/src/i810_reg.h b/src/i810_reg.h index 92d9cf9e..82571e03 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -745,6 +745,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define SDVOC_HOTPLUG_INT_STATUS (1 << 7) # define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +#define SDVOB 0x61140 +#define SDVOC 0x61160 +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_B_SELECT (1 << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/* Programmed value is multiplier - 1, up to 5x. alv, gdg only */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PHASE_SELECT_MASK (15 << 23) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 23) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) +#define SDVO_BORDER_ENABLE (1 << 7) +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVO_PRESERVE_MASK (1 << 17) + #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff diff --git a/src/i830.h b/src/i830.h index babbe08d..a631258e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -202,7 +202,7 @@ struct _I830OutputRec { I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; struct _I830DVODriver *i2c_drv; - struct _I830SDVODriver *sdvo_drv; + I830SDVOPtr sdvo_drv; }; typedef struct _I830Rec { @@ -580,6 +580,10 @@ extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* i830_sdvo.c */ +extern I830SDVOPtr I830SDVOInit(I2CBusPtr b); +extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index); + /* * 12288 is set as the maximum, chosen because it is enough for * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. diff --git a/src/i830_display.c b/src/i830_display.c index 8eebfca3..fd3c3527 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -255,8 +255,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; - CARD32 pipesrc, dspsize, adpa; - Bool ok; + CARD32 pipesrc, dspsize, adpa, sdvoc = 0; + Bool ok, is_sdvo; int refclk, pixel_clock; int outputs; @@ -283,6 +283,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) "Can't support LVDS on pipe A\n"); return FALSE; } + if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) { + /* We'll change how we control outputs soon, but to get the SDVO code up + * and running, just check for these two possibilities. + */ + is_sdvo = TRUE; + } else { + is_sdvo = FALSE; + } htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); @@ -378,6 +386,19 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_REF_INPUT_DREFCLK; dpll |= SDV0_DEFAULT_MULTIPLIER; + if (is_sdvo) { + dpll |= DPLL_DVO_HIGH_SPEED; + + ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC)); + + sdvoc = INREG(SDVOC) & SDVO_PRESERVE_MASK; + sdvoc |= SDVO_ENABLE; + if (pipe == 1) + sdvoc |= SDVO_PIPE_B_SELECT; + sdvoc |= SDVO_PHASE_SELECT_DEFAULT; + sdvoc |= SDVO_BORDER_ENABLE; + } + fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); #if 1 @@ -532,6 +553,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & PIPE_CRT_ACTIVE) OUTREG(ADPA, adpa); + if (is_sdvo) + OUTREG(SDVOC, sdvoc); return TRUE; } diff --git a/src/i830_driver.c b/src/i830_driver.c index 8930db06..591605af 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1338,13 +1338,15 @@ static void I830SetupOutputBusses(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + int i = 0; + Bool ret; /* everyone has at least a single analog output */ - pI830->num_outputs = 1; - pI830->output[0].type = I830_OUTPUT_ANALOG; + pI830->output[i].type = I830_OUTPUT_ANALOG; /* setup the DDC bus for the analog output */ - I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A"); + I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A"); + i++; /* need to add the output busses for each device * - this function is very incomplete @@ -1355,35 +1357,44 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) case PCI_CHIP_845_G: case PCI_CHIP_I855_GM: case PCI_CHIP_I865_G: - pI830->num_outputs = 2; - pI830->output[1].type = I830_OUTPUT_DVO; - I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D"); - I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E"); + pI830->output[i].type = I830_OUTPUT_DVO; + I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); + I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); + i++; break; case PCI_CHIP_E7221_G: /* ??? */ break; - case PCI_CHIP_I915_G: case PCI_CHIP_I915_GM: - pI830->num_outputs = 2; - pI830->output[1].type = I830_OUTPUT_LVDS; - I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOC, "LVDSDDC_C"); - break; -#if 0 - case PCI_CHIP_I945_G: case PCI_CHIP_I945_GM: - /* SDVO ports have a single control bus */ - pI830->num_outputs = 2; - pI830->output[1].type = I830_OUTPUT_SDVO; - I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E"); - - pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus); - ret = I830I2CDetectSDVOController(pScrn, 1); - if (ret == TRUE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n"); + pI830->output[i].type = I830_OUTPUT_LVDS; + I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C"); + i++; + break; + case PCI_CHIP_I915_G: + case PCI_CHIP_I945_G: + /* Set up SDVOB */ + pI830->output[i].type = I830_OUTPUT_SDVO; + I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); + + pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus); + ret = I830I2CDetectSDVOController(pScrn, i); + if (ret == TRUE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOB\n"); + i++; + + /* Set up SDVOC */ + pI830->output[i].type = I830_OUTPUT_SDVO; + I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); + + pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus); + ret = I830I2CDetectSDVOController(pScrn, i); + if (ret == TRUE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOC\n"); + i++; break; -#endif } + pI830->num_outputs = i; } void @@ -1442,8 +1453,8 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i, pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); - -#if 0 + +#if 0 /* if we are on an i2C bus > 0 and we see a monitor - try to * find a controller chip */ @@ -1459,9 +1470,9 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) } #endif break; -#if 0 case I830_OUTPUT_SDVO: if (pI830->output[i].sdvo_drv->found) { +#if 0 I830SDVOSetupDDC(pI830->output[i].sdvo_drv); pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, @@ -1470,9 +1481,9 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i, pI830->output[i].pI2CBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); +#endif } break; -#endif case I830_OUTPUT_UNUSED: break; default: diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c new file mode 100644 index 00000000..7f5549c9 --- /dev/null +++ b/src/i830_sdvo.c @@ -0,0 +1,103 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "i830.h" + +/* SDVO support for i9xx chipsets */ +static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch) +{ + if (!xf86I2CReadByte(&s->d, addr, ch)) { + xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", s->d.pI2CBus->BusName, + s->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +#if 0 +static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) +{ + if (!xf86I2CWriteByte(&s->d, addr, ch)) { + xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", s->d.pI2CBus->BusName, + s->d.SlaveAddr); + return FALSE; + } + return TRUE; +} +#endif + +I830SDVOPtr +I830SDVOInit(I2CBusPtr b) +{ + I830SDVOPtr sdvo; + + sdvo = xcalloc(1, sizeof(I830SDVORec)); + if (sdvo == NULL) + return NULL; + + sdvo->d.DevName = "SDVO Controller"; + sdvo->d.SlaveAddr = 0x39 << 1; + sdvo->d.pI2CBus = b; + sdvo->d.StartTimeout = b->StartTimeout; + sdvo->d.BitTimeout = b->BitTimeout; + sdvo->d.AcknTimeout = b->AcknTimeout; + sdvo->d.ByteTimeout = b->ByteTimeout; + sdvo->d.DriverPrivate.ptr = sdvo; + + if (!xf86I2CDevInit(&sdvo->d)) + goto out; + return sdvo; + +out: + xfree(sdvo); + return NULL; +} + +Bool +I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned char ch[64]; + int i; + I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + + if (sdvo == NULL) + return FALSE; + + for (i=0; i<0x40; i++) { + if (!sReadByte(sdvo, i, &ch[i])) + return FALSE; + } + + pI830->output[output_index].sdvo_drv->found = 1; + + return TRUE; +} From 88bb4b578857588f34ac84b7a20577139eccab6d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 19 Apr 2006 14:23:45 -0700 Subject: [PATCH 070/257] Add more SDVO code. It's taken from airlied's driver, but with magic numbers replaced by symbolic names in many places. I tried to restrain myself from functional changes in airlied's code in this pass. --- src/i830.h | 4 - src/i830_display.c | 10 + src/i830_display.h | 7 + src/i830_sdvo.c | 479 ++++++++++++++++++++++++++++++++++++++++++- src/i830_sdvo_regs.h | 173 ++++++++++++++++ 5 files changed, 667 insertions(+), 6 deletions(-) create mode 100644 src/i830_sdvo_regs.h diff --git a/src/i830.h b/src/i830.h index a631258e..fa1f017a 100644 --- a/src/i830.h +++ b/src/i830.h @@ -580,10 +580,6 @@ extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); -/* i830_sdvo.c */ -extern I830SDVOPtr I830SDVOInit(I2CBusPtr b); -extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index); - /* * 12288 is set as the maximum, chosen because it is enough for * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. diff --git a/src/i830_display.c b/src/i830_display.c index fd3c3527..6fef4257 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -571,6 +571,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) #ifdef XF86DRI Bool didLock = FALSE; #endif + int i; DPRINTF(PFX, "i830SetMode\n"); @@ -590,6 +591,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) pI830->planeEnabled[1] = 0; } + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found) + I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode); + } + if (pI830->planeEnabled[0]) { ok = i830PipeSetMode(pScrn, pMode, 0); if (!ok) @@ -600,6 +606,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) if (!ok) goto done; } + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found) + I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode); + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", (int)(pMode->HDisplay * pMode->VDisplay * diff --git a/src/i830_display.h b/src/i830_display.h index d8e4e5e8..9f07ba16 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -25,7 +25,14 @@ * */ +/* i830_display.c */ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); + +/* i830_sdvo.c */ +I830SDVOPtr I830SDVOInit(I2CBusPtr b); +Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index); +Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); +Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 7f5549c9..3b3efa15 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -28,6 +28,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86_OSproc.h" #include "compiler.h" #include "i830.h" +#include "i830_sdvo_regs.h" + +CARD16 curr_table[6]; /* SDVO support for i9xx chipsets */ static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch) @@ -41,7 +44,6 @@ static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch) return TRUE; } -#if 0 static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) { if (!xf86I2CWriteByte(&s->d, addr, ch)) { @@ -52,8 +54,481 @@ static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) } return TRUE; } + +/* following on from tracing the intel BIOS i2c routines */ +static void +I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) +{ + int i; + + ErrorF("SDVO: W: "); + for (i = num_out; i <= SDVO_I2C_ARG_0; i++) + ErrorF("%02X ", s->sdvo_regs[i]); + ErrorF("\n"); + + /* blast the output regs */ + for (i = SDVO_I2C_ARG_0; i >= num_out; i--) { + sWriteByte(s, i, s->sdvo_regs[i]); + } + /* blast the command reg */ + sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]); +} + +static void +I830SDVOReadInputRegs(I830SDVOPtr s) +{ + int i; + + /* follow BIOS ordering */ + sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]); + + sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]); + sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]); + sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]); + sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]); + sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]); + sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]); + sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]); + sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]); + + ErrorF("SDVO: R: "); + for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++) + ErrorF("%02X ", s->sdvo_regs[i]); + ErrorF("\n"); +} + +Bool +I830SDVOSetupDDC(I830SDVOPtr s, int enable) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2; + + I830SDVOWriteOutputs(s, 7); + + sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]); + + ErrorF("SDVO: R: "); + ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]); + ErrorF("\n"); + return TRUE; +} + +static Bool +I830SDVOSetTargetInput(I830SDVOPtr s) +{ + /* write out 0x10 */ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; + + I830SDVOWriteOutputs(s, 0); + + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOGetTrainedInputs(I830SDVOPtr s, int on) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS; + + /* XXX: I don't believe we need to set anything here --anholt */ + s->sdvo_regs[0x07] = on ? 0x80 : 0x00; + s->sdvo_regs[0x04] = on ? 0x80 : 0x00; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOGetActiveOutputs(I830SDVOPtr s, int on) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS; + + s->sdvo_regs[0x07] = on ? 0x01 : 0x00; + s->sdvo_regs[0x03] = 0x1; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOSetActiveOutputs(I830SDVOPtr s, int on) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS; + + /* XXX: This should be touching args 0,1, I believe. --anholt */ + s->sdvo_regs[0x07] = on ? 0x01 : 0x00; + s->sdvo_regs[0x03] = on ? 0x01 : 0x00; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE; + + /* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */ + + /* set clock regs */ + s->sdvo_regs[0x06] = (clock >> 8) & 0xff; + s->sdvo_regs[0x07] = clock & 0xff; + + /* set height regs */ + s->sdvo_regs[0x02] = (height >> 8) & 0xff; + s->sdvo_regs[0x03] = height & 0xff; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOSetTargetOutput(I830SDVOPtr s) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT; + + s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1; /* Enable */ + s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */ + + I830SDVOWriteOutputs(s, 0); /* XXX: Only write these two */ + I830SDVOReadInputRegs(s); + + return TRUE; +} + +#if 0 +static Bool +I830SDVOGetOutputTimingsPart1(I830SDVOPtr s) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1; + + /* XXX: No args */ + s->sdvo_regs[0x07] = 0x0; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOGetOutputTimingsPart2(I830SDVOPtr s) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2; + + /* XXX: No args */ + s->sdvo_regs[0x07] = 0x0; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} #endif +static Bool +I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1, + CARD16 magic2, CARD16 magic3) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + + /* set clock regs */ + s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock, + CARD16 magic1, CARD16 magic2, CARD16 magic3) +{ + return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1, + clock, magic1, magic2, magic3); +} + +static Bool +I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1, + CARD16 magic2, CARD16 magic3) +{ + return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, + clock, magic1, magic2, magic3); +} + +static Bool +I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock, + CARD16 magic1, CARD16 magic2, + CARD16 magic3) +{ + Bool ok; + + /* XXX: This is a rather different command */ + ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, + clock, magic1, magic2, magic3); + + curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] | + (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] | + (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + curr_table[5] = 0x1e; + + return ok; +} + +static Bool +I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5, + CARD16 magic6) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + + /* set clock regs */ + s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5, + CARD16 magic6) +{ + return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4, + magic5, magic6); +} + +static Bool +I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5, + CARD16 magic6) +{ + return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4, + magic5, magic6); +} + +static Bool +I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width, + CARD16 height) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING; + + s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +static Bool +I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] | + (s->sdvo_regs[SDVO_I2C_RETURN_7] << 8); + curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] | + (s->sdvo_regs[SDVO_I2C_RETURN_5] << 8); + curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] | + (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + + return TRUE; +} + +static Bool +I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT; + + s->sdvo_regs[SDVO_I2C_ARG_0] = val; + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + return TRUE; +} + +Bool +I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) +{ + CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay; + CARD16 height = mode->CrtcVDisplay; + CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; + CARD16 h_sync_offset, v_sync_offset; + CARD16 sync_flags; + CARD8 c16a[8]; + CARD8 c17a[8]; + CARD16 out_timings[6]; + + /* do some mode translations */ + h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; + h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; + + v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart; + v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + + h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart; + v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart; + + sync_flags = 0x18; + if (mode->Flags & V_PHSYNC) + sync_flags |= 0x2; + if (mode->Flags & V_PVSYNC) + sync_flags |= 0x4; + /* high bits of 0 */ + c16a[7] = clock & 0xff; + c16a[6] = (clock >> 8) & 0xff; + c16a[5] = (width & 0xff); + c16a[4] = (h_blank_len & 0xff); + c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf); + c16a[2] = (height & 0xff); + c16a[1] = (v_blank_len & 0xff); + c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf); + + c17a[7] = h_sync_offset; + c17a[6] = h_sync_len & 0xff; + c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf); + c17a[4] = 0; + c17a[3] = sync_flags; + c17a[2] = 0; + out_timings[0] = c16a[1] | ((short)c16a[0] << 8); + out_timings[1] = c16a[3] | ((short)c16a[2] << 8); + out_timings[2] = c16a[5] | ((short)c16a[4] << 8); + out_timings[3] = c17a[7] | ((short)c17a[6] << 8); + out_timings[4] = c17a[5] | ((short)c17a[4] << 8); + out_timings[5] = c17a[3] | ((short)c17a[2] << 8); + + I830SDVOSetTargetInput(s); + I830SDVOGetInputPixelClockRange(s, clock, height); + + I830SDVOGetActiveOutputs(s, 0); + I830SDVOSetActiveOutputs(s, 0); + + I830SDVOSetTargetOutput(s); + I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1], + out_timings[2]); + + I830SDVOSetTargetOutput(s); + I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4], + out_timings[5]); + + I830SDVOSetTargetInput(s); + + I830SDVOCreatePreferredInputTiming(s, clock, width, height); + I830SDVOSetTargetInput(s); + + I830SDVOGetPreferredInputTimingPart1(s); + I830SDVOSetTargetInput(s); + + I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1], + out_timings[2]); + I830SDVOSetTargetInput(s); + + I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1], + curr_table[2]); + + I830SDVOSetTargetInput(s); + I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4], + out_timings[5]); + + I830SDVOSetTargetInput(s); + /*if (mode->PrivFlags & I830_MFLAG_DOUBLE) + I830SDVOSetClockRateMult(s, 0x02); + else */ + I830SDVOSetClockRateMult(s, 0x01); + + return TRUE; +} + +Bool +I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) +{ + int clock = mode->Clock/10, height=mode->CrtcVDisplay; + Bool ret = TRUE; + + /* the BIOS writes out 6 commands post mode set */ + /* two 03s, 04 05, 10, 1d */ + /* these contain the height and mode clock / 10 by the looks of it */ + + I830SDVOGetTrainedInputs(s, 1); + I830SDVOGetTrainedInputs(s, 0); + + /* THIS IS A DIRTY HACK - sometimes for some reason on startup + * the BIOS doesn't find my DVI monitor - + * without this hack the driver doesn't work.. this causes the modesetting + * to be re-run + */ + if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) { + ret = FALSE; + } + + I830SDVOGetActiveOutputs(s, 1); + I830SDVOSetActiveOutputs(s, 1); + + I830SDVOSetTargetInput(s); + I830SDVOGetInputPixelClockRange(s, clock, height); + + return ret; +} + I830SDVOPtr I830SDVOInit(I2CBusPtr b) { @@ -92,7 +567,7 @@ I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index) if (sdvo == NULL) return FALSE; - for (i=0; i<0x40; i++) { + for (i = 0; i < 0x40; i++) { if (!sReadByte(sdvo, i, &ch[i])) return FALSE; } diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h new file mode 100644 index 00000000..5ad4ac99 --- /dev/null +++ b/src/i830_sdvo_regs.h @@ -0,0 +1,173 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/* I2C registers for SDVO */ +#define SDVO_I2C_ARG_0 0x07 +#define SDVO_I2C_ARG_1 0x06 +#define SDVO_I2C_ARG_2 0x05 +#define SDVO_I2C_ARG_3 0x04 +#define SDVO_I2C_ARG_4 0x03 +#define SDVO_I2C_ARG_5 0x02 +#define SDVO_I2C_ARG_6 0x01 +#define SDVO_I2C_ARG_7 0x00 +#define SDVO_I2C_OPCODE 0x08 +#define SDVO_I2C_CMD_STATUS 0x09 +#define SDVO_I2C_RETURN_0 0x0a +#define SDVO_I2C_RETURN_1 0x0b +#define SDVO_I2C_RETURN_2 0x0c +#define SDVO_I2C_RETURN_3 0x0d +#define SDVO_I2C_RETURN_4 0x0e +#define SDVO_I2C_RETURN_5 0x0f +#define SDVO_I2C_RETURN_6 0x10 +#define SDVO_I2C_RETURN_7 0x11 +#define SDVO_I2C_VENDOR_BEGIN 0x20 + +/* Status results */ +#define SDVO_CMD_STATUS_POWER_ON 0x0 +#define SDVO_CMD_STATUS_SUCCESS 0x1 +#define SDVO_CMD_STATUS_NOTSUPP 0x2 +#define SDVO_CMD_STATUS_INVALID_ARG 0x3 +#define SDVO_CMD_STATUS_PENDING 0x4 +#define SDVO_CMD_STATUS_TARGET_NOT_SUPP 0x5 +#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 + +/* SDVO commands, argument/result registers */ +#define SDVO_CMD_RESET 0x01 +#define SDVO_CMD_GET_DEVICE_CAPS 0x02 +# define SDVO_DEVICE_CAPS_VENDOR_ID SDVO_I2C_RETURN_0 +# define SDVO_DEVICE_CAPS_DEVICE_ID SDVO_I2C_RETURN_1 +# define SDVO_DEVICE_CAPS_DEVICE_REV_ID SDVO_I2C_RETURN_2 +# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR SDVO_I2C_RETURN_3 +# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR SDVO_I2C_RETURN_4 +# define SDVO_DEVICE_CAPS_CAPS SDVO_I2C_RETURN_5 +# define SDVO_DEVICE_CAPS_INPUTS_MASK (3 << 0) +# define SDVO_DEVICE_CAPS_SMOOTH_SCALING (1 << 2) +# define SDVO_DEVICE_CAPS_SHARP_SCALING (1 << 3) +# define SDVO_DEVICE_CAPS_UP_SCALING (1 << 4) +# define SDVO_DEVICE_CAPS_DOWN_SCALING (1 << 5) +# define SDVO_DEVICE_CAPS_STALL_SUPPORT (1 << 6) +# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED SDVO_I2C_RETURN_6 +# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED SDVO_I2C_RETURN_7 + +#define SDVO_CMD_GET_FIRMWARE_REV 0x86 +# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 +# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 + +#define SDVO_CMD_GET_TRAINED_INPUTS 0x03 + +#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 + +#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 + +#define SDVO_CMD_GET_IN_OUT_MAP 0x06 + +#define SDVO_CMD_SET_IN_OUT_MAP 0x07 + +#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b + +#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c + +#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d + +#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e + +#define SDVO_CMD_GET_INTR_EVENT_SOURCE 0x0f + +#define SDVO_CMD_SET_TARGET_INPUT 0x10 + +#define SDVO_CMD_SET_TARGET_OUTPUT 0x11 + +#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 +#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 +#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 +#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 +#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 +#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 +#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 +#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 +/* Part 1 */ +# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 +# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 +# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 +# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 +# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 +# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 +# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 +# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 +/* Part 2 */ +# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 +# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 +# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 +# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 +# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 +# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) +# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) +# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) +# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) +# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 +# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) +# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED (1 << 6) +# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) +# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 + +#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a +# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 +# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 +# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 +# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 +# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 +# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) +# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) + +#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b +#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c + +#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d +#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e + +#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f + +#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 + +#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 + +#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 + +#define SDVO_CMD_GET_TV_FORMAT 0x28 + +#define SDVO_CMD_SET_TV_FORMAT 0x29 + +#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 + +#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a +# define SDVO_CONTROL_BUS_PROM 0x0 +# define SDVO_CONTROL_BUS_DDC1 0x1 +# define SDVO_CONTROL_BUS_DDC2 0x2 +# define SDVO_CONTROL_BUS_DDC3 0x3 + From 132dc0599cf44389c4cc03919f1da8d3a0762b44 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 19 Apr 2006 15:04:17 -0700 Subject: [PATCH 071/257] Whine if SDVO I2C device init fails, rather than be silent. --- src/i830_sdvo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 3b3efa15..b656bc67 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -547,13 +547,13 @@ I830SDVOInit(I2CBusPtr b) sdvo->d.ByteTimeout = b->ByteTimeout; sdvo->d.DriverPrivate.ptr = sdvo; - if (!xf86I2CDevInit(&sdvo->d)) - goto out; + if (!xf86I2CDevInit(&sdvo->d)) { + xf86DrvMsg(b->scrnIndex, X_ERROR, + "Failed to initialize SDVO I2C device\n"); + xfree(sdvo); + return NULL; + } return sdvo; - -out: - xfree(sdvo); - return NULL; } Bool From 32a0ad570d9c010e7d26d980830f719782d9f2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejtmanek?= Date: Wed, 19 Apr 2006 19:43:45 -0300 Subject: [PATCH 072/257] Add more registers to save/restore. Save/restore palette as well --- .gitignore | 1 + src/i810_reg.h | 4 ++ src/i830.h | 11 +++++ src/i830_driver.c | 115 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 101 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index c7bcbee1..094379b3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ Makefile Makefile.in *.la *.lo +*.o aclocal.m4 autom4te.cache compile diff --git a/src/i810_reg.h b/src/i810_reg.h index 92d9cf9e..14327eb8 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -681,6 +681,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PP_CONTROL 0x61204 # define POWER_TARGET_ON (1 << 0) +#define LVDSPP_ON 0x61208 +#define LVDSPP_OFF 0x6120c +#define PP_CYCLE 0x61210 + #define PFIT_CONTROL 0x61230 # define PFIT_ENABLE (1 << 31) # define VERT_INTERP_DISABLE (0 << 10) diff --git a/src/i830.h b/src/i830.h index babbe08d..9fe70996 100644 --- a/src/i830.h +++ b/src/i830.h @@ -481,7 +481,18 @@ typedef struct _I830Rec { CARD32 saveVCLK_POST_DIV; CARD32 saveVGACNTRL; CARD32 saveADPA; + CARD32 saveLVDS; + CARD32 saveDVOA; + CARD32 saveDVOB; + CARD32 saveDVOC; + CARD32 savePP_ON; + CARD32 savePP_OFF; + CARD32 savePP_CONTROL; + CARD32 savePP_CYCLE; CARD32 savePFIT_CONTROL; + CARD32 savePaletteA[256]; + CARD32 savePaletteB[256]; + CARD32 saveSWF[17]; } I830Rec; diff --git a/src/i830_driver.c b/src/i830_driver.c index 8930db06..37829e91 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3201,6 +3201,7 @@ SaveHWState(ScrnInfoPtr pScrn) vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; CARD32 temp; + int i; /* * Print out the PIPEACONF and PIPEBCONF registers. @@ -3218,11 +3219,8 @@ SaveHWState(ScrnInfoPtr pScrn) /* Save video mode information for native mode-setting. */ pI830->saveDSPACNTR = INREG(DSPACNTR); - pI830->saveDSPBCNTR = INREG(DSPBCNTR); pI830->savePIPEACONF = INREG(PIPEACONF); - pI830->savePIPEBCONF = INREG(PIPEBCONF); pI830->savePIPEASRC = INREG(PIPEASRC); - pI830->savePIPEBSRC = INREG(PIPEBSRC); pI830->saveFPA0 = INREG(FPA0); pI830->saveFPA1 = INREG(FPA1); pI830->saveDPLL_A = INREG(DPLL_A); @@ -3237,19 +3235,31 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveDSPAPOS = INREG(DSPAPOS); pI830->saveDSPABASE = INREG(DSPABASE); - pI830->saveFPB0 = INREG(FPB0); - pI830->saveFPB1 = INREG(FPB1); - pI830->saveDPLL_B = INREG(DPLL_B); - pI830->saveHTOTAL_B = INREG(HTOTAL_B); - pI830->saveHBLANK_B = INREG(HBLANK_B); - pI830->saveHSYNC_B = INREG(HSYNC_B); - pI830->saveVTOTAL_B = INREG(VTOTAL_B); - pI830->saveVBLANK_B = INREG(VBLANK_B); - pI830->saveVSYNC_B = INREG(VSYNC_B); - pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); - pI830->saveDSPBSIZE = INREG(DSPBSIZE); - pI830->saveDSPBPOS = INREG(DSPBPOS); - pI830->saveDSPBBASE = INREG(DSPBBASE); + for(i= 0; i < 256; i++) { + pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); + } + + if(pI830->availablePipes == 2) { + pI830->savePIPEBCONF = INREG(PIPEBCONF); + pI830->savePIPEBSRC = INREG(PIPEBSRC); + pI830->saveDSPBCNTR = INREG(DSPBCNTR); + pI830->saveFPB0 = INREG(FPB0); + pI830->saveFPB1 = INREG(FPB1); + pI830->saveDPLL_B = INREG(DPLL_B); + pI830->saveHTOTAL_B = INREG(HTOTAL_B); + pI830->saveHBLANK_B = INREG(HBLANK_B); + pI830->saveHSYNC_B = INREG(HSYNC_B); + pI830->saveVTOTAL_B = INREG(VTOTAL_B); + pI830->saveVBLANK_B = INREG(VBLANK_B); + pI830->saveVSYNC_B = INREG(VSYNC_B); + pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); + pI830->saveDSPBSIZE = INREG(DSPBSIZE); + pI830->saveDSPBPOS = INREG(DSPBPOS); + pI830->saveDSPBBASE = INREG(DSPBBASE); + for(i= 0; i < 256; i++) { + pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2)); + } + } pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0); pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1); @@ -3259,6 +3269,23 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveADPA = INREG(ADPA); pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); + pI830->savePP_ON = INREG(LVDSPP_ON); + pI830->savePP_OFF = INREG(LVDSPP_OFF); + pI830->saveLVDS = INREG(LVDS); + pI830->savePP_CONTROL = INREG(PP_CONTROL); + pI830->savePP_CYCLE = INREG(PP_CYCLE); + + pI830->saveDVOA = INREG(DVOA); + pI830->saveDVOB = INREG(DVOB); + pI830->saveDVOC = INREG(DVOC); + + for(i = 0; i < 7; i++) { + pI830->saveSWF[i] = INREG(SWF0 + (i << 2)); + pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2)); + } + pI830->saveSWF[14] = INREG(SWF30); + pI830->saveSWF[15] = INREG(SWF31); + pI830->saveSWF[16] = INREG(SWF32); vgaHWUnlock(hwp); vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); @@ -3273,6 +3300,7 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; CARD32 temp; + int i; DPRINTF(PFX, "RestoreHWState\n"); @@ -3294,6 +3322,8 @@ RestoreHWState(ScrnInfoPtr pScrn) /* XXX: Wait for a vblank */ sleep(1); + i830SetLVDSPanelPower(pScrn, FALSE); + OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); OUTREG(DPLL_A, pI830->saveDPLL_A); @@ -3308,22 +3338,33 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPAPOS, pI830->saveDSPAPOS); OUTREG(DSPABASE, pI830->saveDSPABASE); OUTREG(PIPEASRC, pI830->savePIPEASRC); + for(i = 0; i < 256; i++) { + OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); + } - OUTREG(FPB0, pI830->saveFPB0); - OUTREG(FPB1, pI830->saveFPB1); - OUTREG(DPLL_B, pI830->saveDPLL_B); - OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); - OUTREG(HBLANK_B, pI830->saveHBLANK_B); - OUTREG(HSYNC_B, pI830->saveHSYNC_B); - OUTREG(VTOTAL_B, pI830->saveVTOTAL_B); - OUTREG(VBLANK_B, pI830->saveVBLANK_B); - OUTREG(VSYNC_B, pI830->saveVSYNC_B); - OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); - OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); - OUTREG(DSPBPOS, pI830->saveDSPBPOS); - OUTREG(DSPBBASE, pI830->saveDSPBBASE); - OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + if(pI830->availablePipes == 2) { + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); + OUTREG(DPLL_B, pI830->saveDPLL_B); + OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); + OUTREG(HBLANK_B, pI830->saveHBLANK_B); + OUTREG(HSYNC_B, pI830->saveHSYNC_B); + OUTREG(VTOTAL_B, pI830->saveVTOTAL_B); + OUTREG(VBLANK_B, pI830->saveVBLANK_B); + OUTREG(VSYNC_B, pI830->saveVSYNC_B); + OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); + OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); + OUTREG(DSPBPOS, pI830->saveDSPBPOS); + OUTREG(DSPBBASE, pI830->saveDSPBBASE); + OUTREG(PIPEBSRC, pI830->savePIPEBSRC); + for(i= 0; i < 256; i++) { + OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); + } + } + OUTREG(LVDSPP_ON, pI830->savePP_ON); + OUTREG(LVDSPP_OFF, pI830->savePP_OFF); + OUTREG(PP_CYCLE, pI830->savePP_CYCLE); OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); @@ -3338,6 +3379,20 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); OUTREG(ADPA, pI830->saveADPA); + OUTREG(LVDS, pI830->saveLVDS); + OUTREG(DVOA, pI830->saveDVOA); + OUTREG(DVOB, pI830->saveDVOB); + OUTREG(DVOC, pI830->saveDVOC); + OUTREG(PP_CONTROL, pI830->savePP_CONTROL); + + for(i = 0; i < 7; i++) { + OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); + OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); + } + + OUTREG(SWF30, pI830->saveSWF[14]); + OUTREG(SWF31, pI830->saveSWF[15]); + OUTREG(SWF32, pI830->saveSWF[16]); i830CompareRegsToSnapshot(pScrn); From 2909802de63756972b38651a496b4ff1b36ac8a2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 19 Apr 2006 16:29:06 -0700 Subject: [PATCH 073/257] Clean up SDVO initialization, include config.h, and make it check the right slave address on the first device as well. This gets me to the point of bringing up some modes on my device. --- src/i830.h | 2 +- src/i830_display.c | 4 ++-- src/i830_display.h | 4 ++-- src/i830_driver.c | 15 +++----------- src/i830_sdvo.c | 49 ++++++++++++++++++++++------------------------ 5 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/i830.h b/src/i830.h index fa1f017a..08eae708 100644 --- a/src/i830.h +++ b/src/i830.h @@ -189,9 +189,9 @@ struct _I830DVODriver { }; typedef struct _I830SDVODriver { - int found; I2CDevRec d; unsigned char sdvo_regs[20]; + CARD32 output_device; /* SDVOB or SDVOC */ } I830SDVORec, *I830SDVOPtr; struct _I830OutputRec { diff --git a/src/i830_display.c b/src/i830_display.c index 6fef4257..f8bd0d88 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -592,7 +592,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found) + if (pI830->output[i].sdvo_drv) I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode); } @@ -607,7 +607,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) goto done; } for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found) + if (pI830->output[i].sdvo_drv) I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode); } diff --git a/src/i830_display.h b/src/i830_display.h index 9f07ba16..aecf8dcd 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -32,7 +32,7 @@ void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); /* i830_sdvo.c */ -I830SDVOPtr I830SDVOInit(I2CBusPtr b); -Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index); +I830SDVOPtr I830SDVOInit(ScrnInfoPtr pScrn, int output_index, + CARD32 output_device); Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 591605af..61cc231c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1339,7 +1339,6 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int i = 0; - Bool ret; /* everyone has at least a single analog output */ pI830->output[i].type = I830_OUTPUT_ANALOG; @@ -1376,21 +1375,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) /* Set up SDVOB */ pI830->output[i].type = I830_OUTPUT_SDVO; I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); - - pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus); - ret = I830I2CDetectSDVOController(pScrn, i); - if (ret == TRUE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOB\n"); + I830SDVOInit(pScrn, i, SDVOB); i++; /* Set up SDVOC */ pI830->output[i].type = I830_OUTPUT_SDVO; I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); - - pI830->output[i].sdvo_drv = I830SDVOInit(pI830->output[i].pI2CBus); - ret = I830I2CDetectSDVOController(pScrn, i); - if (ret == TRUE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVOC\n"); + I830SDVOInit(pScrn, i, SDVOC); i++; break; } @@ -1471,7 +1462,7 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) #endif break; case I830_OUTPUT_SDVO: - if (pI830->output[i].sdvo_drv->found) { + if (pI830->output[i].sdvo_drv != NULL) { #if 0 I830SDVOSetupDDC(pI830->output[i].sdvo_drv); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index b656bc67..bbf2b936 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -23,6 +23,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "xf86.h" #include "xf86_ansic.h" #include "xf86_OSproc.h" @@ -530,49 +533,43 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) } I830SDVOPtr -I830SDVOInit(I2CBusPtr b) +I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) { + I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo; + int i; + unsigned char ch[0x40]; sdvo = xcalloc(1, sizeof(I830SDVORec)); if (sdvo == NULL) return NULL; sdvo->d.DevName = "SDVO Controller"; - sdvo->d.SlaveAddr = 0x39 << 1; - sdvo->d.pI2CBus = b; - sdvo->d.StartTimeout = b->StartTimeout; - sdvo->d.BitTimeout = b->BitTimeout; - sdvo->d.AcknTimeout = b->AcknTimeout; - sdvo->d.ByteTimeout = b->ByteTimeout; + if (output_device == SDVOB) + sdvo->d.SlaveAddr = 0x70; + else + sdvo->d.SlaveAddr = 0x72; + sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus; sdvo->d.DriverPrivate.ptr = sdvo; + sdvo->output_device = output_device; if (!xf86I2CDevInit(&sdvo->d)) { - xf86DrvMsg(b->scrnIndex, X_ERROR, - "Failed to initialize SDVO I2C device\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize SDVO I2C device %s\n", + output_device == SDVOB ? "SDVOB" : "SDVOC"); xfree(sdvo); return NULL; } - return sdvo; -} - -Bool -I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned char ch[64]; - int i; - I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; - - if (sdvo == NULL) - return FALSE; + /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { - if (!sReadByte(sdvo, i, &ch[i])) - return FALSE; + if (!sReadByte(sdvo, i, &ch[i])) { + xfree(sdvo); + return NULL; + } } - pI830->output[output_index].sdvo_drv->found = 1; + pI830->output[output_index].sdvo_drv = sdvo; - return TRUE; + return sdvo; } From b5f099e03a9f58b6b99933fb06526bce4db72bd3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Apr 2006 09:50:36 +1000 Subject: [PATCH 074/257] cleanup sDVO for device on C only This destroys the i2c device properly if the device isn't detected, and allows sDVO to work on GM chipsets, and doesn't initialise the i2c bus twice for sDVO. --- src/i830_driver.c | 3 +-- src/i830_sdvo.c | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 61cc231c..e0bb55a2 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1369,7 +1369,6 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) pI830->output[i].type = I830_OUTPUT_LVDS; I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C"); i++; - break; case PCI_CHIP_I915_G: case PCI_CHIP_I945_G: /* Set up SDVOB */ @@ -1380,7 +1379,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) /* Set up SDVOC */ pI830->output[i].type = I830_OUTPUT_SDVO; - I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); + pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus; I830SDVOInit(pScrn, i, SDVOC); i++; break; diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index bbf2b936..4d760449 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -544,11 +544,13 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) if (sdvo == NULL) return NULL; - sdvo->d.DevName = "SDVO Controller"; - if (output_device == SDVOB) + if (output_device == SDVOB) { + sdvo->d.DevName = "SDVO Controller B"; sdvo->d.SlaveAddr = 0x70; - else + } else { + sdvo->d.DevName = "SDVO Controller C"; sdvo->d.SlaveAddr = 0x72; + } sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus; sdvo->d.DriverPrivate.ptr = sdvo; sdvo->output_device = output_device; @@ -564,6 +566,7 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { if (!sReadByte(sdvo, i, &ch[i])) { + xf86DestroyI2CDevRec(&sdvo->d, 0); xfree(sdvo); return NULL; } From 2991d81a3b643161babab6b8f44c057aaaf351c3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Apr 2006 12:27:47 +1000 Subject: [PATCH 075/257] correct height parameter in sdvo packet --- src/i830_sdvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 4d760449..05784617 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -366,8 +366,8 @@ I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width, s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff; s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff; I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); From 0ba7b13fb4410c6a48b2fb098d2033e040eca6d2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Apr 2006 12:29:06 +1000 Subject: [PATCH 076/257] fix type 0 instead of O --- src/i810_reg.h | 2 +- src/i830_display.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 82571e03..2a03f32c 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -722,7 +722,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) # define SDVO_MULTIPLIER_MASK 0x000000ff -# define SDV0_DEFAULT_MULTIPLIER 0x00000003 +# define SDVO_DEFAULT_MULTIPLIER 0x00000003 #define FPA0 0x06040 #define FPA1 0x06044 diff --git a/src/i830_display.c b/src/i830_display.c index f8bd0d88..471b87e9 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -384,7 +384,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_REF_INPUT_TVCLKINBC; else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= SDV0_DEFAULT_MULTIPLIER; + dpll |= SDVO_DEFAULT_MULTIPLIER; if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; From 729c373121ce2bbb0d813cc923f1254e8b37a025 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Apr 2006 13:34:55 +1000 Subject: [PATCH 077/257] move sdvo output setting we have to set the sdvo register a lot earlier in order for them to sync properly otherwise my monitor doesn't sync unfortunately, also disable the sdvo while tweaking the PLLs. This also comments out a setting that seems to break my system here for Eric to look at later. --- src/i830_display.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 471b87e9..95fa936d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -395,8 +395,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) sdvoc |= SDVO_ENABLE; if (pipe == 1) sdvoc |= SDVO_PIPE_B_SELECT; - sdvoc |= SDVO_PHASE_SELECT_DEFAULT; + // sdvoc |= SDVO_PHASE_SELECT_DEFAULT; sdvoc |= SDVO_BORDER_ENABLE; + OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); } fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); @@ -464,6 +465,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(FPA0, fp); OUTREG(DPLL_A, dpll); + + if (is_sdvo) + OUTREG(SDVOC, sdvoc); + OUTREG(HTOTAL_A, htot); OUTREG(HBLANK_A, hblank); OUTREG(HSYNC_A, hsync); @@ -553,8 +558,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & PIPE_CRT_ACTIVE) OUTREG(ADPA, adpa); - if (is_sdvo) - OUTREG(SDVOC, sdvoc); return TRUE; } From bcb441225d1365435bc3373901180de944298e86 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 10:54:45 -0700 Subject: [PATCH 078/257] Simplify the i2c code by using the GetBits/PutBits interface rather than reimplementing it. --- src/i810_reg.h | 4 +- src/i830_i2c.c | 221 +++++-------------------------------------------- 2 files changed, 21 insertions(+), 204 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index c790e8b6..dee39cef 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -267,12 +267,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define GPIOG 0x5028 #define GPIOH 0x502c # define GPIO_CLOCK_DIR_MASK (1 << 0) -# define GPIO_CLOCK_DIR (1 << 1) +# define GPIO_CLOCK_DIR_OUT (1 << 1) # define GPIO_CLOCK_VAL_MASK (1 << 2) # define GPIO_CLOCK_VAL_OUT (1 << 3) # define GPIO_CLOCK_VAL_IN (1 << 4) # define GPIO_DATA_DIR_MASK (1 << 8) -# define GPIO_DATA_DIR (1 << 9) +# define GPIO_DATA_DIR_OUT (1 << 9) # define GPIO_DATA_VAL_MASK (1 << 10) # define GPIO_DATA_VAL_OUT (1 << 11) # define GPIO_DATA_VAL_IN (1 << 12) diff --git a/src/i830_i2c.c b/src/i830_i2c.c index 8c80a0a1..fa0ca301 100644 --- a/src/i830_i2c.c +++ b/src/i830_i2c.c @@ -49,215 +49,35 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "shadow.h" #include "i830.h" -#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ -#define I2C_TRACE(x) /*(x)*/ /* Report progress */ - -static void i830_setscl(I2CBusPtr b, int state) +static void +i830I2CGetBits(I2CBusPtr b, int *clock, int *data) { - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); CARD32 val; - OUTREG(b->DriverPrivate.uval, - (state ? GPIO_CLOCK_VAL_OUT : 0) | - GPIO_CLOCK_DIR | - GPIO_CLOCK_DIR_MASK | - GPIO_CLOCK_VAL_MASK); val = INREG(b->DriverPrivate.uval); -} - -static void i830_setsda(I2CBusPtr b, int state) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - I830Ptr pI830 = I830PTR(pScrn); - CARD32 val; - - OUTREG(b->DriverPrivate.uval, (state ? GPIO_DATA_VAL_OUT : 0) | - GPIO_DATA_DIR | - GPIO_DATA_DIR_MASK | - GPIO_DATA_VAL_MASK); - val = INREG(b->DriverPrivate.uval); -} - -static void i830_getscl(I2CBusPtr b, int *state) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - I830Ptr pI830 = I830PTR(pScrn); - CARD32 val; - - OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_MASK); - OUTREG(b->DriverPrivate.uval, 0); - val = INREG(b->DriverPrivate.uval); - *state = ((val & GPIO_CLOCK_VAL_IN) != 0); -} - -static int i830_getsda(I2CBusPtr b) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - I830Ptr pI830 = I830PTR(pScrn); - CARD32 val; - - OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_MASK); - OUTREG(b->DriverPrivate.uval, 0); - val = INREG(b->DriverPrivate.uval); - return ((val & GPIO_DATA_VAL_IN) != 0); -} - -static inline void sdalo(I2CBusPtr b) -{ - i830_setsda(b, 0); - b->I2CUDelay(b, b->RiseFallTime); -} - -static inline void sdahi(I2CBusPtr b) -{ - i830_setsda(b, 1); - b->I2CUDelay(b, b->RiseFallTime); -} - -static inline void scllo(I2CBusPtr b) -{ - i830_setscl(b, 0); - b->I2CUDelay(b, b->RiseFallTime); -} - -static inline int sclhi(I2CBusPtr b, int timeout) -{ - int scl = 0; - int i; - - i830_setscl(b, 1); - b->I2CUDelay(b, b->RiseFallTime); - - for (i = timeout; i > 0; i -= b->RiseFallTime) { - i830_getscl(b, &scl); - if (scl) break; - b->I2CUDelay(b, b->RiseFallTime); - } - - if (i <= 0) { - I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]", b->BusName, timeout)); - return FALSE; - } - return TRUE; -} - -static Bool -I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) -{ - I2CBusPtr b = d->pI2CBus; - int i; - unsigned char indata = 0; - - sdahi(b); - - for (i = 0; i < 8; i++) { - if (sclhi(b, d->BitTimeout)==FALSE) { - I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i)); - return FALSE; - } - indata*=2; - if ( i830_getsda (b) ) { - indata |= 0x01; - } - scllo(b); - } - - if (last) - sdahi(b); - else - sdalo(b); - - if (sclhi(b, d->BitTimeout) == FALSE) { - sdahi(b); - return FALSE; - } - - scllo(b); - sdahi(b); - - *data = indata & 0xff; - I2C_TRACE(ErrorF("R%02x ", (int) *data)); - - return TRUE; -} - -static Bool -I830I2CPutByte(I2CDevPtr d, I2CByte c) -{ - int i; - int sb, ack; - I2CBusPtr b = d->pI2CBus; - - for (i = 7; i>=0; i--) { - sb = c & (1 << i); - i830_setsda(b, sb); - b->I2CUDelay(b, b->RiseFallTime); - - if (sclhi(b, d->ByteTimeout) == FALSE) { - sdahi(b); - return FALSE; - } - - i830_setscl(b, 0); - b->I2CUDelay(b, b->RiseFallTime); - } - sdahi(b); - if (sclhi(b, d->ByteTimeout) == FALSE) { - I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", - b->BusName, c, d->BitTimeout, - d->ByteTimeout, d->AcknTimeout)); - return FALSE; - } - ack = i830_getsda(b); - I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack)); - - scllo(b); - return 0 == ack; -} - -static Bool -I830I2CStart(I2CBusPtr b, int timeout) -{ - if (sclhi(b, timeout) == FALSE) - return FALSE; - - sdalo(b); - scllo(b); - - return TRUE; + *data = (val & GPIO_DATA_VAL_IN) != 0; + *clock = (val & GPIO_CLOCK_VAL_IN) != 0; } static void -I830I2CStop(I2CDevPtr d) +i830I2CPutBits(I2CBusPtr b, int clock, int data) { - I2CBusPtr b = d->pI2CBus; + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); - sdalo(b); - sclhi(b, d->ByteTimeout); - sdahi(b); + OUTREG(b->DriverPrivate.uval, + (data ? GPIO_DATA_VAL_OUT : 0) | + (clock ? GPIO_CLOCK_VAL_OUT : 0) | + GPIO_CLOCK_DIR_OUT | + GPIO_DATA_DIR_OUT | + GPIO_CLOCK_DIR_MASK | + GPIO_CLOCK_VAL_MASK | + GPIO_DATA_DIR_MASK | + GPIO_DATA_VAL_MASK); } -static Bool -I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) -{ - if (I830I2CStart(d->pI2CBus, d->StartTimeout)) { - if (I830I2CPutByte(d, addr & 0xFF)) { - if ((addr & 0xF8) != 0xF0 && - (addr & 0xFE) != 0x00) - return TRUE; - - if (I830I2CPutByte(d, (addr >> 8) & 0xFF)) - return TRUE; - } - - I830I2CStop(d); - } - - return FALSE; -} - - /* the i830 has a number of I2C Buses */ Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) @@ -271,11 +91,8 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) pI2CBus->BusName = name; pI2CBus->scrnIndex = pScrn->scrnIndex; - pI2CBus->I2CGetByte = I830I2CGetByte; - pI2CBus->I2CPutByte = I830I2CPutByte; - pI2CBus->I2CStart = I830I2CStart; - pI2CBus->I2CStop = I830I2CStop; - pI2CBus->I2CAddress = I830I2CAddress; + pI2CBus->I2CGetBits = i830I2CGetBits; + pI2CBus->I2CPutBits = i830I2CPutBits; pI2CBus->DriverPrivate.uval = i2c_reg; if (!xf86I2CBusInit(pI2CBus)) From effab21c3d108fac7a4e28ae4dabb0b5f74a5380 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 11:42:24 -0700 Subject: [PATCH 079/257] Set displayWidth to a sufficient value for the modes we come up with for LVDS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by: Lukáš Hejtmánek --- src/i830_driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/i830_driver.c b/src/i830_driver.c index 8fba83cc..3f671066 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1693,6 +1693,10 @@ static int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Total number of valid FP mode(s) found: %d\n", count); + /* Adjust the display pitch to fit the modes we've come up with. */ + pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX); + pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63; + return count; } From d32514aee4b00b035652830e8b5e6c0b43cf159c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 12:21:45 -0700 Subject: [PATCH 080/257] Start trying to implement DDC over SDVO. It's slightly tricky because the control bus will reset from DDC mode to internal-registers mode after every Stop afer a Start on the DDC bus. The xf86 DDC code causes multiple Start/Stops in one probe. So, we create a wrapper bus that does the control bus switch at every Start. It's not working yet on my hardware, but I'm pretty sure this is the right way to go. --- src/i830_driver.c | 10 ++-- src/i830_sdvo.c | 122 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3f671066..7c6de99a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1462,16 +1462,12 @@ void I830DetectMonitors(ScrnInfoPtr pScrn) break; case I830_OUTPUT_SDVO: if (pI830->output[i].sdvo_drv != NULL) { -#if 0 - I830SDVOSetupDDC(pI830->output[i].sdvo_drv); - pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[i].pI2CBus); + pI830->output[i].pDDCBus); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i, - pI830->output[i].pI2CBus->DriverPrivate.uval); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i, + pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); -#endif } break; case I830_OUTPUT_UNUSED: diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 05784617..412d798c 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -100,21 +100,19 @@ I830SDVOReadInputRegs(I830SDVOPtr s) ErrorF("\n"); } +/* Sets the control bus switch to either point at one of the DDC buses or the + * PROM. It resets from the DDC bus back to internal registers at the next I2C + * STOP. PROM access is terminated by accessing an internal register. + */ Bool -I830SDVOSetupDDC(I830SDVOPtr s, int enable) +I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; - s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2; + s->sdvo_regs[SDVO_I2C_ARG_0] = target; I830SDVOWriteOutputs(s, 7); - - sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]); - - ErrorF("SDVO: R: "); - ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]); - ErrorF("\n"); return TRUE; } @@ -532,6 +530,80 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) return ret; } +static Bool +I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +{ + I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + Bool ret; + + savebus = d->pI2CBus; + d->pI2CBus = i2cbus; + ret = i2cbus->I2CGetByte(d, data, last); + d->pI2CBus = savebus; + + return ret; +} + +static Bool +I830SDVODDCI2CPutByte(I2CDevPtr d, I2CByte c) +{ + I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + Bool ret; + + savebus = d->pI2CBus; + d->pI2CBus = i2cbus; + ret = i2cbus->I2CPutByte(d, c); + d->pI2CBus = savebus; + + return ret; +} + +static Bool +I830SDVODDCI2CStart(I2CBusPtr b, int timeout) +{ + I830SDVOPtr sdvo = b->DriverPrivate.ptr; + I2CBusPtr i2cbus = sdvo->d.pI2CBus; + + I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC1); + return i2cbus->I2CStart(i2cbus, timeout); +} + +static void +I830SDVODDCI2CStop(I2CDevPtr d) +{ + I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + + savebus = d->pI2CBus; + d->pI2CBus = i2cbus; + i2cbus->I2CStop(d); + d->pI2CBus = savebus; +} + +/* It's a shame that xf86i2c.c's I2CAddress() doesn't use the bus's pointers, + * so it's useless to us here. + */ +static Bool +I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + if (d->pI2CBus->I2CStart(d->pI2CBus, d->StartTimeout)) { + if (d->pI2CBus->I2CPutByte(d, addr & 0xFF)) { + if ((addr & 0xF8) != 0xF0 && + (addr & 0xFE) != 0x00) + return TRUE; + + if (d->pI2CBus->I2CPutByte(d, (addr >> 8) & 0xFF)) + return TRUE; + } + + d->pI2CBus->I2CStop(d); + } + + return FALSE; +} + I830SDVOPtr I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) { @@ -539,6 +611,9 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) I830SDVOPtr sdvo; int i; unsigned char ch[0x40]; + I2CBusPtr i2cbus, ddcbus; + + i2cbus = pI830->output[output_index].pI2CBus; sdvo = xcalloc(1, sizeof(I830SDVORec)); if (sdvo == NULL) @@ -551,7 +626,7 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) sdvo->d.DevName = "SDVO Controller C"; sdvo->d.SlaveAddr = 0x72; } - sdvo->d.pI2CBus = pI830->output[output_index].pI2CBus; + sdvo->d.pI2CBus = i2cbus; sdvo->d.DriverPrivate.ptr = sdvo; sdvo->output_device = output_device; @@ -563,9 +638,38 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) return NULL; } + /* Set up our wrapper I2C bus for DDC. It acts just like the regular I2C + * bus, except that it does the control bus switch to DDC mode before every + * Start. While we only need to do it at Start after every Stop after a + * Start, extra attempts should be harmless. + */ + ddcbus = xf86CreateI2CBusRec(); + if (ddcbus == NULL) { + xf86DestroyI2CDevRec(&sdvo->d, 0); + xfree(sdvo); + return NULL; + } + ddcbus->BusName = "SDVO DDC Bus"; + ddcbus->scrnIndex = i2cbus->scrnIndex; + ddcbus->I2CGetByte = I830SDVODDCI2CGetByte; + ddcbus->I2CPutByte = I830SDVODDCI2CPutByte; + ddcbus->I2CStart = I830SDVODDCI2CStart; + ddcbus->I2CStop = I830SDVODDCI2CStop; + ddcbus->I2CAddress = I830SDVODDCI2CAddress; + ddcbus->DriverPrivate.ptr = sdvo; + if (!xf86I2CBusInit(ddcbus)) { + xf86DestroyI2CDevRec(&sdvo->d, 0); + xfree(sdvo); + return NULL; + } + + pI830->output[output_index].pDDCBus = ddcbus; + /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { if (!sReadByte(sdvo, i, &ch[i])) { + xf86DestroyI2CBusRec(pI830->output[output_index].pDDCBus, FALSE, + FALSE); xf86DestroyI2CDevRec(&sdvo->d, 0); xfree(sdvo); return NULL; From 9ba5319b36e7286e33cf0dcdd804dfc0458a81f5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 13:55:05 -0700 Subject: [PATCH 081/257] Only write out as many arguments as the commands need, and fix up the numbers in some cases. Pretty-print the return status. --- src/i830_sdvo.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 412d798c..172a9be9 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -64,19 +64,29 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) { int i; - ErrorF("SDVO: W: "); - for (i = num_out; i <= SDVO_I2C_ARG_0; i++) + ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]); + for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) ErrorF("%02X ", s->sdvo_regs[i]); ErrorF("\n"); /* blast the output regs */ - for (i = SDVO_I2C_ARG_0; i >= num_out; i--) { + for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) { sWriteByte(s, i, s->sdvo_regs[i]); } /* blast the command reg */ sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]); } +static const char *cmd_status_names[] = { + "Power on", + "Success", + "Not supported", + "Invalid arg", + "Pending", + "Target not supported", + "Scaling not supported" +}; + static void I830SDVOReadInputRegs(I830SDVOPtr s) { @@ -95,8 +105,12 @@ I830SDVOReadInputRegs(I830SDVOPtr s) sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]); ErrorF("SDVO: R: "); - for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++) + for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++) ErrorF("%02X ", s->sdvo_regs[i]); + if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) + ErrorF("(%s)", cmd_status_names[s->sdvo_regs[SDVO_I2C_CMD_STATUS]]); + else + ErrorF("(??? %d)", s->sdvo_regs[SDVO_I2C_CMD_STATUS]); ErrorF("\n"); } @@ -112,7 +126,7 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target) s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; s->sdvo_regs[SDVO_I2C_ARG_0] = target; - I830SDVOWriteOutputs(s, 7); + I830SDVOWriteOutputs(s, 1); return TRUE; } @@ -124,7 +138,7 @@ I830SDVOSetTargetInput(I830SDVOPtr s) s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 1); I830SDVOReadInputRegs(s); @@ -175,7 +189,7 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, int on) s->sdvo_regs[0x07] = on ? 0x01 : 0x00; s->sdvo_regs[0x03] = on ? 0x01 : 0x00; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 2); I830SDVOReadInputRegs(s); return TRUE; @@ -214,7 +228,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s) s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1; /* Enable */ s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */ - I830SDVOWriteOutputs(s, 0); /* XXX: Only write these two */ + I830SDVOWriteOutputs(s, 1); /* XXX: Only write these two */ I830SDVOReadInputRegs(s); return TRUE; @@ -272,7 +286,7 @@ I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1, s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff; s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 8); I830SDVOReadInputRegs(s); return TRUE; @@ -330,7 +344,7 @@ I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5, s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff; s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 8); I830SDVOReadInputRegs(s); return TRUE; @@ -367,7 +381,7 @@ I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width, s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff; s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 7); I830SDVOReadInputRegs(s); return TRUE; @@ -401,7 +415,7 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT; s->sdvo_regs[SDVO_I2C_ARG_0] = val; - I830SDVOWriteOutputs(s, 0); + I830SDVOWriteOutputs(s, 1); I830SDVOReadInputRegs(s); return TRUE; From 56c1f8b0de9b6acc50f51561caf14d3e6bac09ec Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 14:10:20 -0700 Subject: [PATCH 082/257] Clean up some argument passing, and remove extra SetTarget{In,Out}Puts that had no effect. Note that we are currently trying to program both outputs of any SDVO device the same way. --- src/i830_sdvo.c | 127 ++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 80 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 172a9be9..e8898fc5 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -131,12 +131,13 @@ I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target) } static Bool -I830SDVOSetTargetInput(I830SDVOPtr s) +I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2) { - /* write out 0x10 */ memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; + s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; + s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; I830SDVOWriteOutputs(s, 1); @@ -146,16 +147,12 @@ I830SDVOSetTargetInput(I830SDVOPtr s) } static Bool -I830SDVOGetTrainedInputs(I830SDVOPtr s, int on) +I830SDVOGetTrainedInputs(I830SDVOPtr s) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS; - /* XXX: I don't believe we need to set anything here --anholt */ - s->sdvo_regs[0x07] = on ? 0x80 : 0x00; - s->sdvo_regs[0x04] = on ? 0x80 : 0x00; - I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); @@ -163,15 +160,12 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s, int on) } static Bool -I830SDVOGetActiveOutputs(I830SDVOPtr s, int on) +I830SDVOGetActiveOutputs(I830SDVOPtr s) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS; - s->sdvo_regs[0x07] = on ? 0x01 : 0x00; - s->sdvo_regs[0x03] = 0x1; - I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); @@ -179,15 +173,13 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s, int on) } static Bool -I830SDVOSetActiveOutputs(I830SDVOPtr s, int on) +I830SDVOSetActiveOutputs(I830SDVOPtr s, Bool on_1, Bool on_2) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS; - - /* XXX: This should be touching args 0,1, I believe. --anholt */ - s->sdvo_regs[0x07] = on ? 0x01 : 0x00; - s->sdvo_regs[0x03] = on ? 0x01 : 0x00; + s->sdvo_regs[SDVO_I2C_ARG_0] = on_1; + s->sdvo_regs[SDVO_I2C_ARG_1] = on_2; I830SDVOWriteOutputs(s, 2); I830SDVOReadInputRegs(s); @@ -196,39 +188,34 @@ I830SDVOSetActiveOutputs(I830SDVOPtr s, int on) } static Bool -I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height) +I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 *clock_min, + CARD16 *clock_max) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE; - /* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */ - - /* set clock regs */ - s->sdvo_regs[0x06] = (clock >> 8) & 0xff; - s->sdvo_regs[0x07] = clock & 0xff; - - /* set height regs */ - s->sdvo_regs[0x02] = (height >> 8) & 0xff; - s->sdvo_regs[0x03] = height & 0xff; - I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); + *clock_min = s->sdvo_regs[SDVO_I2C_RETURN_0] | + (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + *clock_max = s->sdvo_regs[SDVO_I2C_RETURN_2] | + (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + return TRUE; } static Bool -I830SDVOSetTargetOutput(I830SDVOPtr s) +I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2) { memset(s->sdvo_regs, 0, 9); s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT; + s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; + s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; - s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1; /* Enable */ - s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */ - - I830SDVOWriteOutputs(s, 1); /* XXX: Only write these two */ + I830SDVOWriteOutputs(s, 1); I830SDVOReadInputRegs(s); return TRUE; @@ -308,26 +295,6 @@ I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1, clock, magic1, magic2, magic3); } -static Bool -I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock, - CARD16 magic1, CARD16 magic2, - CARD16 magic3) -{ - Bool ok; - - /* XXX: This is a rather different command */ - ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, - clock, magic1, magic2, magic3); - - curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] | - (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] | - (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); - curr_table[5] = 0x1e; - - return ok; -} - static Bool I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5, CARD16 magic6) @@ -407,6 +374,23 @@ I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s) return TRUE; } +static Bool +I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s) +{ + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] | + (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] | + (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + curr_table[5] = 0x1e; + + return TRUE; +} + static Bool I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) { @@ -432,6 +416,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) CARD8 c16a[8]; CARD8 c17a[8]; CARD16 out_timings[6]; + CARD16 clock_min, clock_max; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -471,40 +456,27 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) out_timings[4] = c17a[5] | ((short)c17a[4] << 8); out_timings[5] = c17a[3] | ((short)c17a[2] << 8); - I830SDVOSetTargetInput(s); - I830SDVOGetInputPixelClockRange(s, clock, height); + I830SDVOSetTargetInput(s, TRUE, TRUE); + I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max); + ErrorF("clock min/max: %d %d\n", clock_min, clock_max); - I830SDVOGetActiveOutputs(s, 0); - I830SDVOSetActiveOutputs(s, 0); + I830SDVOGetActiveOutputs(s); + I830SDVOSetActiveOutputs(s, FALSE, FALSE); - I830SDVOSetTargetOutput(s); + I830SDVOSetTargetOutput(s, TRUE, TRUE); I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1], out_timings[2]); - - I830SDVOSetTargetOutput(s); I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4], out_timings[5]); - I830SDVOSetTargetInput(s); - I830SDVOCreatePreferredInputTiming(s, clock, width, height); - I830SDVOSetTargetInput(s); - I830SDVOGetPreferredInputTimingPart1(s); - I830SDVOSetTargetInput(s); - - I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1], - out_timings[2]); - I830SDVOSetTargetInput(s); - + I830SDVOGetPreferredInputTimingPart2(s); I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1], curr_table[2]); - - I830SDVOSetTargetInput(s); I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4], out_timings[5]); - I830SDVOSetTargetInput(s); /*if (mode->PrivFlags & I830_MFLAG_DOUBLE) I830SDVOSetClockRateMult(s, 0x02); else */ @@ -516,15 +488,13 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) { - int clock = mode->Clock/10, height=mode->CrtcVDisplay; Bool ret = TRUE; /* the BIOS writes out 6 commands post mode set */ /* two 03s, 04 05, 10, 1d */ /* these contain the height and mode clock / 10 by the looks of it */ - I830SDVOGetTrainedInputs(s, 1); - I830SDVOGetTrainedInputs(s, 0); + I830SDVOGetTrainedInputs(s); /* THIS IS A DIRTY HACK - sometimes for some reason on startup * the BIOS doesn't find my DVI monitor - @@ -535,11 +505,8 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) ret = FALSE; } - I830SDVOGetActiveOutputs(s, 1); - I830SDVOSetActiveOutputs(s, 1); - - I830SDVOSetTargetInput(s); - I830SDVOGetInputPixelClockRange(s, clock, height); + I830SDVOGetActiveOutputs(s); + I830SDVOSetActiveOutputs(s, TRUE, TRUE); return ret; } From b498d2b1d1170123595ada65353428578b59a361 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 15:42:46 -0700 Subject: [PATCH 083/257] Start trying to save/restore SDVO state on VT switches. --- src/i830.h | 8 ++- src/i830_driver.c | 43 ++++++++++-- src/i830_sdvo.c | 161 +++++++++++++++++++++++++++++++++++++------ src/i830_sdvo.h | 54 +++++++++++++++ src/i830_sdvo_regs.h | 4 +- 5 files changed, 239 insertions(+), 31 deletions(-) create mode 100644 src/i830_sdvo.h diff --git a/src/i830.h b/src/i830.h index 3b81c920..d72b72bb 100644 --- a/src/i830.h +++ b/src/i830.h @@ -69,6 +69,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif #include "common.h" +#include "i830_sdvo.h" /* I830 Video BIOS support */ @@ -192,6 +193,12 @@ typedef struct _I830SDVODriver { I2CDevRec d; unsigned char sdvo_regs[20]; CARD32 output_device; /* SDVOB or SDVOC */ + + int save_sdvo_mult; + Bool save_sdvo_active_1, save_sdvo_active_2; + i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; + i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; + CARD32 save_SDVOX; } I830SDVORec, *I830SDVOPtr; struct _I830OutputRec { @@ -493,7 +500,6 @@ typedef struct _I830Rec { CARD32 savePaletteA[256]; CARD32 savePaletteB[256]; CARD32 saveSWF[17]; - } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) diff --git a/src/i830_driver.c b/src/i830_driver.c index 7c6de99a..dcb1acfb 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3276,9 +3276,11 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePP_CONTROL = INREG(PP_CONTROL); pI830->savePP_CYCLE = INREG(PP_CYCLE); - pI830->saveDVOA = INREG(DVOA); - pI830->saveDVOB = INREG(DVOB); - pI830->saveDVOC = INREG(DVOC); + if (!IS_I9XX(pI830)) { + pI830->saveDVOA = INREG(DVOA); + pI830->saveDVOB = INREG(DVOB); + pI830->saveDVOC = INREG(DVOC); + } for(i = 0; i < 7; i++) { pI830->saveSWF[i] = INREG(SWF0 + (i << 2)); @@ -3287,7 +3289,15 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveSWF[14] = INREG(SWF30); pI830->saveSWF[15] = INREG(SWF31); pI830->saveSWF[16] = INREG(SWF32); - + + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO && + pI830->output[i].sdvo_drv != NULL) + { + i830SDVOSave(pScrn, i); + } + } + vgaHWUnlock(hwp); vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); @@ -3325,6 +3335,14 @@ RestoreHWState(ScrnInfoPtr pScrn) i830SetLVDSPanelPower(pScrn, FALSE); + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO && + pI830->output[i].sdvo_drv != NULL) + { + i830SDVOPreRestore(pScrn, i); + } + } + OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); OUTREG(DPLL_A, pI830->saveDPLL_A); @@ -3381,9 +3399,20 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(ADPA, pI830->saveADPA); OUTREG(LVDS, pI830->saveLVDS); - OUTREG(DVOA, pI830->saveDVOA); - OUTREG(DVOB, pI830->saveDVOB); - OUTREG(DVOC, pI830->saveDVOC); + if (!IS_I9XX(pI830)) { + OUTREG(DVOA, pI830->saveDVOA); + OUTREG(DVOB, pI830->saveDVOB); + OUTREG(DVOC, pI830->saveDVOC); + } + + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO && + pI830->output[i].sdvo_drv != NULL) + { + i830SDVOPostRestore(pScrn, i); + } + } + OUTREG(PP_CONTROL, pI830->savePP_CONTROL); for(i = 0; i < 7; i++) { diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index e8898fc5..e58b659d 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -160,7 +160,7 @@ I830SDVOGetTrainedInputs(I830SDVOPtr s) } static Bool -I830SDVOGetActiveOutputs(I830SDVOPtr s) +I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2) { memset(s->sdvo_regs, 0, 9); @@ -169,6 +169,9 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s) I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); + *on_1 = s->sdvo_regs[SDVO_I2C_ARG_0]; + *on_2 = s->sdvo_regs[SDVO_I2C_ARG_1]; + return TRUE; } @@ -221,39 +224,73 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2) return TRUE; } -#if 0 -static Bool -I830SDVOGetOutputTimingsPart1(I830SDVOPtr s) +/* Fetches either input or output timings to *dtd, depending on cmd. */ +Bool +I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) { memset(s->sdvo_regs, 0, 9); - - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1; - - /* XXX: No args */ - s->sdvo_regs[0x07] = 0x0; - + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); - + + dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] | + (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2]; + dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3]; + dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4]; + dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5]; + dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6]; + dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7]; + + memset(s->sdvo_regs, 0, 9); + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0]; + dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1]; + dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2]; + dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3]; + dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4]; + dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5]; + dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6]; + dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7]; + return TRUE; } -static Bool -I830SDVOGetOutputTimingsPart2(I830SDVOPtr s) +/* Fetches either input or output timings to *dtd, depending on cmd. */ +Bool +I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) { memset(s->sdvo_regs, 0, 9); + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff; + s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8; + s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active; + s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank; + s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high; + s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active; + s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank; + s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high; + I830SDVOWriteOutputs(s, 8); + I830SDVOReadInputRegs(s); - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2; - - /* XXX: No args */ - s->sdvo_regs[0x07] = 0x0; - - I830SDVOWriteOutputs(s, 0); + memset(s->sdvo_regs, 0, 9); + s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; + s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off; + s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width; + s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width; + s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high; + s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags; + s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags; + s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high; + s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved; + I830SDVOWriteOutputs(s, 8); I830SDVOReadInputRegs(s); return TRUE; } -#endif static Bool I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1, @@ -391,6 +428,29 @@ I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s) return TRUE; } +static int +I830SDVOGetClockRateMult(I830SDVOPtr s) +{ + memset(s->sdvo_regs, 0, 9); + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT; + + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) { + xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, + "Couldn't get SDVO clock rate multiplier\n"); + return SDVO_CLOCK_RATE_MULT_1X; + } else { + xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO, + "Current clock rate multiplier: %d\n", + s->sdvo_regs[SDVO_I2C_RETURN_0]); + } + + return s->sdvo_regs[SDVO_I2C_RETURN_0]; +} + static Bool I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) { @@ -460,7 +520,6 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max); ErrorF("clock min/max: %d %d\n", clock_min, clock_max); - I830SDVOGetActiveOutputs(s); I830SDVOSetActiveOutputs(s, FALSE, FALSE); I830SDVOSetTargetOutput(s, TRUE, TRUE); @@ -505,12 +564,70 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) ret = FALSE; } - I830SDVOGetActiveOutputs(s); I830SDVOSetActiveOutputs(s, TRUE, TRUE); return ret; } +void +i830SDVOSave(ScrnInfoPtr pScrn, int output_index) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + + sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo); + I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1, + &sdvo->save_sdvo_active_2); + + I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); + I830SDVOSetTargetInput(sdvo, FALSE, TRUE); + I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); + + I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); + I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); + I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); +} + +void +i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + + I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); +} + +void +i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + + I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); + I830SDVOSetTargetInput(sdvo, FALSE, TRUE); + I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); + + I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); + I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); + I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + + I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult); + I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1, + sdvo->save_sdvo_active_2); +} + static Bool I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) { diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h new file mode 100644 index 00000000..ec4b538b --- /dev/null +++ b/src/i830_sdvo.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +typedef struct _i830_sdvo_dtd { + CARD16 clock; + CARD8 h_active; + CARD8 h_blank; + CARD8 h_high; + CARD8 v_active; + CARD8 v_blank; + CARD8 v_high; + + CARD8 h_sync_off; + CARD8 h_sync_width; + CARD8 v_sync_off_width; + CARD8 sync_off_width_high; + CARD8 dtd_flags; + CARD8 sdvo_flags; + CARD8 v_sync_off_high; + CARD8 reserved; +} __attribute__((packed)) i830_sdvo_dtd; + +void +i830SDVOSave(ScrnInfoPtr pScrn, int output_index); + +void +i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index); + +void +i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index); diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index 5ad4ac99..9165c394 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -154,8 +154,10 @@ #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 - #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 +# define SDVO_CLOCK_RATE_MULT_1X 0 +# define SDVO_CLOCK_RATE_MULT_2X 1 +# define SDVO_CLOCK_RATE_MULT_4X 3 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 From cc70e6b789a1901bbe4e3501b6b654542d3cdc20 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 16:49:48 -0700 Subject: [PATCH 084/257] Save/restore the output's SDVO reg. Note that we might be programming the other SDVO reg instead of the one assigned to the output. When trying to fix that, I ended up getting no output at all. --- src/i830_sdvo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index e58b659d..99cdc6ac 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -438,7 +438,7 @@ I830SDVOGetClockRateMult(I830SDVOPtr s) I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); - if (s->sdvo_regs[SDVO_CMD_GET_CLOCK_RATE_MULT] != SDVO_CMD_STATUS_SUCCESS) { + if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) { xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, "Couldn't get SDVO clock rate multiplier\n"); return SDVO_CLOCK_RATE_MULT_1X; @@ -592,6 +592,8 @@ i830SDVOSave(ScrnInfoPtr pScrn, int output_index) I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + + sdvo->save_SDVOX = INREG(sdvo->output_device); } void @@ -624,6 +626,9 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult); + + OUTREG(sdvo->output_device, sdvo->save_SDVOX); + I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1, sdvo->save_sdvo_active_2); } From a555e28e5afc81969ef7b28482e654cc26b3a446 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Apr 2006 16:55:44 -0700 Subject: [PATCH 085/257] Correct some SDVO-related register definitions. --- src/i810_reg.h | 5 +++-- src/i830_sdvo_regs.h | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index dee39cef..53c65bbf 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -757,11 +757,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVO_INTERRUPT_ENABLE (1 << 26) /* Programmed value is multiplier - 1, up to 5x. alv, gdg only */ #define SDVO_PORT_MULTIPLY_MASK (7 << 23) -#define SDVO_PHASE_SELECT_MASK (15 << 23) -#define SDVO_PHASE_SELECT_DEFAULT (6 << 23) +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) #define SDVOC_GANG_MODE (1 << 16) #define SDVO_BORDER_ENABLE (1 << 7) +#define SDVOB_PCIE_CONCURRENCY (1 << 3) #define SDVO_DETECTED (1 << 2) /* Bits to be preserved when writing */ #define SDVO_PRESERVE_MASK (1 << 17) diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index 9165c394..37cfcf2e 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -122,7 +122,7 @@ # define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 # define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 # define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 -# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 +# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 # define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 # define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) # define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) @@ -155,9 +155,9 @@ #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 -# define SDVO_CLOCK_RATE_MULT_1X 0 -# define SDVO_CLOCK_RATE_MULT_2X 1 -# define SDVO_CLOCK_RATE_MULT_4X 3 +# define SDVO_CLOCK_RATE_MULT_1X (1 << 0) +# define SDVO_CLOCK_RATE_MULT_2X (1 << 1) +# define SDVO_CLOCK_RATE_MULT_4X (1 << 3) #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 From a66f2c01f7d557d860883346671fb864807dbdca Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 1 May 2006 12:35:21 -0700 Subject: [PATCH 086/257] Stop doing the BIOS memory size tweaking now that we don't ask the BIOS about what modes are available. --- src/i830.h | 8 -- src/i830_driver.c | 360 ---------------------------------------------- src/i830_memory.c | 17 +-- 3 files changed, 1 insertion(+), 384 deletions(-) diff --git a/src/i830.h b/src/i830.h index d72b72bb..7c4d50c8 100644 --- a/src/i830.h +++ b/src/i830.h @@ -245,8 +245,6 @@ typedef struct _I830Rec { long FbMapSize; long TotalVideoRam; I830MemRange StolenMemory; /* pre-allocated memory */ - long BIOSMemorySize; /* min stolen pool size */ - int BIOSMemSizeLoc; /* These change according to what has been allocated. */ long FreeMemory; @@ -384,12 +382,6 @@ typedef struct _I830Rec { VbeInfoBlock *vbeInfo; VESAPtr vesa; - Bool overrideBIOSMemSize; - int saveBIOSMemSize; - int newBIOSMemSize; - Bool useSWF1; - int saveSWF1; - Bool swfSaved; CARD32 saveSWF0; CARD32 saveSWF4; diff --git a/src/i830_driver.c b/src/i830_driver.c index dcb1acfb..3eb32056 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -871,291 +871,6 @@ I830UnmapMem(ScrnInfoPtr pScrn) return TRUE; } -#ifndef HAVE_GET_PUT_BIOSMEMSIZE -#define HAVE_GET_PUT_BIOSMEMSIZE 1 -#endif - -#if HAVE_GET_PUT_BIOSMEMSIZE -/* - * Tell the BIOS how much video memory is available. The BIOS call used - * here won't always be available. - */ -static Bool -PutBIOSMemSize(ScrnInfoPtr pScrn, int memSize) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "PutBIOSMemSize: %d kB\n", memSize / 1024); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f11; - pVbe->pInt10->bx = 0; - pVbe->pInt10->cx = memSize / GTT_PAGE_SIZE; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - return Check5fStatus(pScrn, 0x5f11, pVbe->pInt10->ax); -} - -/* - * This reports what the previous VBEGetVBEInfo() found. Be sure to call - * VBEGetVBEInfo() after changing the BIOS memory size view. If - * a separate BIOS call is added for this, it can be put here. Only - * return a valid value if the funtionality for PutBIOSMemSize() - * is available. - */ -static int -GetBIOSMemSize(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int memSize = KB(pI830->vbeInfo->TotalMemory * 64); - - DPRINTF(PFX, "GetBIOSMemSize\n"); - - if (PutBIOSMemSize(pScrn, memSize)) - return memSize; - else - return -1; -} -#endif - -/* - * These three functions allow the video BIOS's view of the available video - * memory to be changed. This is currently implemented only for the 830 - * and 845G, which can do this via a BIOS scratch register that holds the - * BIOS's view of the (pre-reserved) memory size. If another mechanism - * is available in the future, it can be plugged in here. - * - * The mapping used for the 830/845G scratch register's low 4 bits is: - * - * 320k => 0 - * 832k => 1 - * 8000k => 8 - * - * The "unusual" values are the 512k, 1M, 8M pre-reserved memory, less - * overhead, rounded down to the BIOS-reported 64k granularity. - */ - -static Bool -SaveBIOSMemSize(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - DPRINTF(PFX, "SaveBIOSMemSize\n"); - - if (!I830IsPrimary(pScrn)) - return FALSE; - - pI830->useSWF1 = FALSE; - -#if HAVE_GET_PUT_BIOSMEMSIZE - if ((pI830->saveBIOSMemSize = GetBIOSMemSize(pScrn)) != -1) - return TRUE; -#endif - - if (IS_I830(pI830) || IS_845G(pI830)) { - pI830->useSWF1 = TRUE; - pI830->saveSWF1 = INREG(SWF1) & 0x0f; - - /* - * This is for sample purposes only. pI830->saveBIOSMemSize isn't used - * when pI830->useSWF1 is TRUE. - */ - switch (pI830->saveSWF1) { - case 0: - pI830->saveBIOSMemSize = KB(320); - break; - case 1: - pI830->saveBIOSMemSize = KB(832); - break; - case 8: - pI830->saveBIOSMemSize = KB(8000); - break; - default: - pI830->saveBIOSMemSize = 0; - break; - } - return TRUE; - } - return FALSE; -} - -/* - * TweakMemorySize() tweaks the BIOS image to set the correct size. - * Original implementation by Christian Zietz in a stand-alone tool. - */ -static CARD32 -TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) -{ -#define SIZE 0x10000 -#define _855_IDOFFSET (-23) -#define _845_IDOFFSET (-19) - - const char *MAGICstring = "Total time for VGA POST:"; - const int len = strlen(MAGICstring); - I830Ptr pI830 = I830PTR(pScrn); - volatile char *position; - char *biosAddr; - CARD32 oldsize; - CARD32 oldpermission; - CARD32 ret = 0; - int i,j = 0; - int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL - : _855_DRAM_RW_CONTROL; - - PCITAG tag =pciTag(0,0,0); - - if (!I830IsPrimary(pScrn)) - return 0; - - if(!pI830->PciInfo - || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830))) - return 0; - - if (!pI830->pVbe) - return 0; - - biosAddr = xf86int10Addr(pI830->pVbe->pInt10, - pI830->pVbe->pInt10->BIOSseg << 4); - - if (!pI830->BIOSMemSizeLoc) { - if (!preinit) - return 0; - - /* Search for MAGIC string */ - for (i = 0; i < SIZE; i++) { - if (biosAddr[i] == MAGICstring[j]) { - if (++j == len) - break; - } else { - i -= j; - j = 0; - } - } - if (j < len) return 0; - - pI830->BIOSMemSizeLoc = (i - j + 1 + (IS_845G(pI830) - ? _845_IDOFFSET : _855_IDOFFSET)); - } - - position = biosAddr + pI830->BIOSMemSizeLoc; - oldsize = *(CARD32 *)position; - - ret = oldsize - 0x21000; - - /* verify that register really contains current size */ - if (preinit && ((ret >> 16) != pI830->vbeInfo->TotalMemory)) - return 0; - - oldpermission = pciReadLong(tag, reg); - pciWriteLong(tag, reg, DRAM_WRITE | (oldpermission & 0xffff)); - - *(CARD32 *)position = newsize + 0x21000; - - if (preinit) { - /* reinitialize VBE for new size */ - if (I830IsPrimary(pScrn)) { - VBEFreeVBEInfo(pI830->vbeInfo); - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->pVbe = pI8301->pVbe; - pI830->vbeInfo = pI8301->vbeInfo; - } - - /* verify that change was successful */ - if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){ - ret = 0; - *(CARD32 *)position = oldsize; - } else { - pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Tweak BIOS image to %d kB VideoRAM\n", - (int)(pI830->BIOSMemorySize / 1024)); - } - } - - pciWriteLong(tag, reg, oldpermission); - - return ret; -} - -static void -RestoreBIOSMemSize(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 swf1; - - DPRINTF(PFX, "RestoreBIOSMemSize\n"); - - if (!I830IsPrimary(pScrn)) - return; - - if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE)) - return; - - if (!pI830->overrideBIOSMemSize) - return; - -#if HAVE_GET_PUT_BIOSMEMSIZE - if (!pI830->useSWF1) { - PutBIOSMemSize(pScrn, pI830->saveBIOSMemSize); - return; - } -#endif - - if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) { - swf1 = INREG(SWF1); - swf1 &= ~0x0f; - swf1 |= (pI830->saveSWF1 & 0x0f); - OUTREG(SWF1, swf1); - } -} - -static void -SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize) -{ - I830Ptr pI830 = I830PTR(pScrn); - unsigned long swf1; - Bool mapped; - - DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024); - - if (!pI830->overrideBIOSMemSize) - return; - -#if HAVE_GET_PUT_BIOSMEMSIZE - if (!pI830->useSWF1) { - PutBIOSMemSize(pScrn, newSize); - return; - } -#endif - - if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) { - unsigned long newSWF1; - - /* Need MMIO access here. */ - mapped = (pI830->MMIOBase != NULL); - if (!mapped) - I830MapMMIO(pScrn); - - if (newSize <= KB(832)) - newSWF1 = 1; - else - newSWF1 = 8; - - swf1 = INREG(SWF1); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08lx\n", swf1); - swf1 &= ~0x0f; - swf1 |= (newSWF1 & 0x0f); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1); - OUTREG(SWF1, swf1); - if (!mapped) - I830UnmapMMIO(pScrn); - } -} - static CARD32 val8[256]; static void @@ -1509,7 +1224,6 @@ PreInitCleanup(ScrnInfoPtr pScrn) if (pI830->entityPrivate) pI830->entityPrivate->pScrn_2 = NULL; } - RestoreBIOSMemSize(pScrn); if (pI830->swfSaved) { OUTREG(SWF0, pI830->saveSWF0); OUTREG(SWF4, pI830->saveSWF4); @@ -2423,67 +2137,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam); } - if (mem > 0) { - /* - * If the reserved (BIOS accessible) memory is less than the desired - * amount, try to increase it. So far this is only implemented for - * the 845G and 830, but those details are handled in SetBIOSMemSize(). - * - * The BIOS-accessible amount is only important for setting video - * modes. The maximum amount we try to set is limited to what would - * be enough for 1920x1440 with a 2048 pitch. - * - * If ALLOCATE_ALL_BIOSMEM is enabled in i830_memory.c, all of the - * BIOS-aware memory will get allocated. If it isn't then it may - * not be, and in that case there is an assumption that the video - * BIOS won't attempt to access memory beyond what is needed for - * modes that are actually used. ALLOCATE_ALL_BIOSMEM is enabled by - * default. - */ - - /* Try to keep HW cursor and Overlay amounts separate from this. */ - int reserve = (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB + OVERLAY_SIZE) / 1024; - - if (pScrn->videoRam - reserve >= I830_MAXIMUM_VBIOS_MEM) - pI830->newBIOSMemSize = KB(I830_MAXIMUM_VBIOS_MEM); - else - pI830->newBIOSMemSize = - KB(ROUND_DOWN_TO(pScrn->videoRam - reserve, 64)); - if (pI830->vbeInfo->TotalMemory * 64 < pI830->newBIOSMemSize / 1024) { - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will attempt to tell the BIOS that there is " - "%d kB VideoRAM\n", pI830->newBIOSMemSize / 1024); - if (SaveBIOSMemSize(pScrn)) { - pI830->overrideBIOSMemSize = TRUE; - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); - - if (I830IsPrimary(pScrn)) { - VBEFreeVBEInfo(pI830->vbeInfo); - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->pVbe = pI8301->pVbe; - pI830->vbeInfo = pI8301->vbeInfo; - } - - pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS now sees %ld kB VideoRAM\n", - pI830->BIOSMemorySize / 1024); - } else if ((pI830->saveBIOSMemSize - = TweakMemorySize(pScrn, pI830->newBIOSMemSize,TRUE)) != 0) - pI830->overrideBIOSMemSize = TRUE; - else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS view of memory size can't be changed " - "(this is not an error).\n"); - } - } - } - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Pre-allocated VideoRAM: %ld kByte\n", pI830->StolenMemory.Size / 1024); @@ -2923,9 +2576,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830PrintModes(pScrn); - /* PreInit shouldn't leave any state changes, so restore this. */ - RestoreBIOSMemSize(pScrn); - /* Don't need MMIO access anymore. */ if (pI830->swfSaved) { OUTREG(SWF0, pI830->saveSWF0); @@ -3870,11 +3520,6 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->pVbe = pI8301->pVbe; } - if (I830IsPrimary(pScrn)) { - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); - } - if (!pI830->pVbe) return FALSE; @@ -4298,7 +3943,6 @@ I830BIOSLeaveVT(int scrnIndex, int flags) ResetState(pScrn, TRUE); RestoreHWState(pScrn); - RestoreBIOSMemSize(pScrn); if (I830IsPrimary(pScrn)) I830UnbindAGPMemory(pScrn); if (pI830->AccelInfoRec) @@ -4487,10 +4131,6 @@ I830BIOSEnterVT(int scrnIndex, int flags) return FALSE; CheckInheritedState(pScrn); - if (I830IsPrimary(pScrn)) { - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); - } ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); diff --git a/src/i830_memory.c b/src/i830_memory.c index 433aa47d..2d8610af 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -65,10 +65,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. static int nextTile = 0; static unsigned int tileGeneration = -1; -#ifndef ALLOCATE_ALL_BIOSMEM -#define ALLOCATE_ALL_BIOSMEM 1 -#endif - static unsigned long GetBestTileAlignment(unsigned long size) { @@ -252,11 +248,7 @@ I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range) * USE CAUTION when changing anything here... */ I830MemPool *Pool = range->Pool; - if (pI830->overrideBIOSMemSize && - pI830->BIOSMemorySize > pI830->StolenMemory.Size) - Pool->Total.End = pI830->BIOSMemorySize; - else - Pool->Total.End = pI830->StolenMemory.End; + Pool->Total.End = pI830->StolenMemory.End; if (pI830->StolenOnly) Pool->Free.End += range->Size; @@ -1078,13 +1070,6 @@ I830ResetAllocations(ScrnInfoPtr pScrn, const int flags) pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size; pI830->StolenPool.Fixed = pI830->StolenMemory; pI830->StolenPool.Total = pI830->StolenMemory; -#if ALLOCATE_ALL_BIOSMEM - if (pI830->overrideBIOSMemSize && - pI830->BIOSMemorySize > pI830->StolenMemory.Size) { - pI830->StolenPool.Total.End = pI830->BIOSMemorySize; - pI830->StolenPool.Total.Size = pI830->BIOSMemorySize; - } -#endif pI830->StolenPool.Free = pI830->StolenPool.Total; pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size; pI830->allocatedMemory = 0; From fb10966e9f43f44488097b0daf2fbe10c6a804dc Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 4 May 2006 18:52:08 -0700 Subject: [PATCH 087/257] Use xf86int10Addr() when calculating an address to read the video BIOS from, out of int10's copy. Fixes a crash on FreeBSD. --- src/i830_bios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 19b1b5ad..4b87351c 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -91,7 +91,8 @@ i830GetBIOS(ScrnInfoPtr pScrn) return FALSE; if (pI830->pVbe != NULL) { - memcpy(pI830->VBIOS, (void *)(pI830->pVbe->pInt10->BIOSseg << 4), + memcpy(pI830->VBIOS, xf86int10Addr(pI830->pVbe->pInt10, + pI830->pVbe->pInt10->BIOSseg << 4), INTEL_VBIOS_SIZE); } else { xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE); From 190f9ad0606e96e684e0b028d576d822dc9aa3cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 May 2006 13:51:25 -0700 Subject: [PATCH 088/257] Video overlay gamma bounds checking must be done bytewise. Also, pend bound computations to register writes to allow updates to individual values that are 'out of spec' so the client can update multiple values. --- src/i830_video.c | 59 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 0ae68607..a608a7e3 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -592,18 +592,53 @@ I830SetOneLineModeRatio(ScrnInfoPtr pScrn) pPriv->oneLineMode = FALSE; } +static CARD32 I830BoundGammaElt (CARD32 elt, CARD32 eltPrev) +{ + elt &= 0xff; + eltPrev &= 0xff; + if (elt < eltPrev) + elt = eltPrev; + else if ((elt - eltPrev) > 0x7e) + elt = eltPrev + 0x7e; + return elt; +} + +static CARD32 I830BoundGamma (CARD32 gamma, CARD32 gammaPrev) +{ + return (I830BoundGammaElt (gamma >> 24, gammaPrev >> 24) << 24 | + I830BoundGammaElt (gamma >> 16, gammaPrev >> 16) << 16 | + I830BoundGammaElt (gamma >> 8, gammaPrev >> 8) << 8 | + I830BoundGammaElt (gamma , gammaPrev )); +} + static void I830UpdateGamma(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; + CARD32 gamma0 = pPriv->gamma0; + CARD32 gamma1 = pPriv->gamma1; + CARD32 gamma2 = pPriv->gamma2; + CARD32 gamma3 = pPriv->gamma3; + CARD32 gamma4 = pPriv->gamma4; + CARD32 gamma5 = pPriv->gamma5; - OUTREG(OGAMC5, pPriv->gamma5); - OUTREG(OGAMC4, pPriv->gamma4); - OUTREG(OGAMC3, pPriv->gamma3); - OUTREG(OGAMC2, pPriv->gamma2); - OUTREG(OGAMC1, pPriv->gamma1); - OUTREG(OGAMC0, pPriv->gamma0); + ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", + gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); + gamma1 = I830BoundGamma (gamma1, gamma0); + gamma2 = I830BoundGamma (gamma2, gamma1); + gamma3 = I830BoundGamma (gamma3, gamma2); + gamma4 = I830BoundGamma (gamma4, gamma3); + gamma5 = I830BoundGamma (gamma5, gamma4); + ErrorF ("Bounded gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", + gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); + + OUTREG(OGAMC5, gamma5); + OUTREG(OGAMC4, gamma4); + OUTREG(OGAMC3, gamma3); + OUTREG(OGAMC2, gamma2); + OUTREG(OGAMC1, gamma1); + OUTREG(OGAMC0, gamma0); } static XF86VideoAdaptorPtr @@ -849,28 +884,16 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, #endif } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { pPriv->gamma0 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma1 = pPriv->gamma0 + 0x7d; } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) { pPriv->gamma1 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma0 = pPriv->gamma1 - 0x7d; } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) { pPriv->gamma2 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma3 = pPriv->gamma2 + 0x7d; } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) { pPriv->gamma3 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma2 = pPriv->gamma3 - 0x7d; } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) { pPriv->gamma4 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma5 = pPriv->gamma4 + 0x7d; } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) { pPriv->gamma5 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma4 = pPriv->gamma5 - 0x7d; } else if (attribute == xvColorKey) { pPriv->colorKey = value; switch (pScrn->depth) { From fbba4312e7cb326fdcf6a71194c4fc4a7a9b5488 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 12 May 2006 18:44:27 +1000 Subject: [PATCH 089/257] add sdvo capability reading support This reads the SDVO cap bits and uses them to figure out the input/output to save/restore --- src/i830.h | 1 + src/i830_sdvo.c | 97 ++++++++++++++++++++++++++++++++++++------------- src/i830_sdvo.h | 11 ++++++ 3 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/i830.h b/src/i830.h index 7c4d50c8..c60bfbe6 100644 --- a/src/i830.h +++ b/src/i830.h @@ -194,6 +194,7 @@ typedef struct _I830SDVODriver { unsigned char sdvo_regs[20]; CARD32 output_device; /* SDVOB or SDVOC */ + i830_sdvo_caps caps; int save_sdvo_mult; Bool save_sdvo_active_1, save_sdvo_active_2; i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 99cdc6ac..fe37d21a 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -579,19 +579,29 @@ i830SDVOSave(ScrnInfoPtr pScrn, int output_index) I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1, &sdvo->save_sdvo_active_2); - I830SDVOSetTargetInput(sdvo, TRUE, FALSE); - I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); - I830SDVOSetTargetInput(sdvo, FALSE, TRUE); - I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); + if (sdvo->caps.caps & 0x1) { + I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); + } - I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); - I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); - I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); - I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + if (sdvo->caps.caps & 0x2) { + I830SDVOSetTargetInput(sdvo, FALSE, TRUE); + I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); + } + + if (sdvo->caps.output_0_supported) { + I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); + I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + } + + if (sdvo->caps.output_1_supported) { + I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); + I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + } sdvo->save_SDVOX = INREG(sdvo->output_device); } @@ -611,19 +621,29 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; - I830SDVOSetTargetInput(sdvo, TRUE, FALSE); - I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); - I830SDVOSetTargetInput(sdvo, FALSE, TRUE); - I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); + if (sdvo->caps.caps & 0x1) { + I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); + } - I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); - I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); - I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); - I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + if (sdvo->caps.caps & 0x2) { + I830SDVOSetTargetInput(sdvo, FALSE, TRUE); + I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); + } + + if (sdvo->caps.output_0_supported) { + I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); + I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + } + + if (sdvo->caps.output_1_supported) { + I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); + I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + } I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult); @@ -633,6 +653,24 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) sdvo->save_sdvo_active_2); } +static void +I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps) +{ + memset(s->sdvo_regs, 0, 9); + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS; + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + caps->vendor_id = s->sdvo_regs[SDVO_I2C_RETURN_0]; + caps->device_id = s->sdvo_regs[SDVO_I2C_RETURN_1]; + caps->device_rev_id = s->sdvo_regs[SDVO_I2C_RETURN_2]; + caps->sdvo_version_major = s->sdvo_regs[SDVO_I2C_RETURN_3]; + caps->sdvo_version_minor = s->sdvo_regs[SDVO_I2C_RETURN_4]; + caps->caps = s->sdvo_regs[SDVO_I2C_RETURN_5]; + caps->output_0_supported = s->sdvo_regs[SDVO_I2C_RETURN_6]; + caps->output_1_supported = s->sdvo_regs[SDVO_I2C_RETURN_7]; +} + static Bool I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) { @@ -669,7 +707,7 @@ I830SDVODDCI2CStart(I2CBusPtr b, int timeout) I830SDVOPtr sdvo = b->DriverPrivate.ptr; I2CBusPtr i2cbus = sdvo->d.pI2CBus; - I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC1); + I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC2); return i2cbus->I2CStart(i2cbus, timeout); } @@ -781,5 +819,14 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) pI830->output[output_index].sdvo_drv = sdvo; + I830SDVOGetCapabilities(sdvo, &sdvo->caps); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SDVO device VID/DID: %02X:%02X.%02X, %02X, output 1: %c, output 2: %c\n", + sdvo->caps.vendor_id, sdvo->caps.device_id, + sdvo->caps.device_rev_id, sdvo->caps.caps, + sdvo->caps.output_0_supported ? 'Y' : 'N', + sdvo->caps.output_1_supported ? 'Y' : 'N'); + return sdvo; } diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index ec4b538b..6b77c97a 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -25,6 +25,17 @@ * */ +typedef struct _i830_sdvo_caps { + CARD8 vendor_id; + CARD8 device_id; + CARD8 device_rev_id; + CARD8 sdvo_version_major; + CARD8 sdvo_version_minor; + CARD8 caps; + CARD8 output_0_supported; + CARD8 output_1_supported; +} __attribute__((packed)) i830_sdvo_caps; + typedef struct _i830_sdvo_dtd { CARD16 clock; CARD8 h_active; From 1bc2a8f7a20b2ea9251e93157c0f2342fdbb951c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 May 2006 16:58:22 +1000 Subject: [PATCH 090/257] fixup I830SDVOGetActiveInputs to use return values not args --- src/i830_sdvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index fe37d21a..579f77ab 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -169,8 +169,8 @@ I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2) I830SDVOWriteOutputs(s, 0); I830SDVOReadInputRegs(s); - *on_1 = s->sdvo_regs[SDVO_I2C_ARG_0]; - *on_2 = s->sdvo_regs[SDVO_I2C_ARG_1]; + *on_1 = s->sdvo_regs[SDVO_I2C_RETURN_0]; + *on_2 = s->sdvo_regs[SDVO_I2C_RETURN_1]; return TRUE; } From 1e2da2450d7213c0aa4d4bd1fba5723dcda13ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejtmanek?= Date: Mon, 22 May 2006 09:48:09 -0700 Subject: [PATCH 091/257] Replace VBE call to do DPMS with native code, and fix screensaver in clone mode. --- src/i830_driver.c | 153 ++++++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 61 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3eb32056..425ddd5c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4258,27 +4258,30 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) I830Ptr pI830 = I830PTR(pScrn); Bool on = xf86IsUnblank(mode); CARD32 temp, ctrl, base; + int i; DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { - if (pI830->pipe == 0) { - ctrl = DSPACNTR; - base = DSPABASE; - } else { - ctrl = DSPBCNTR; - base = DSPBADDR; - } - if (pI830->planeEnabled[pI830->pipe]) { - temp = INREG(ctrl); - if (on) - temp |= DISPLAY_PLANE_ENABLE; - else - temp &= ~DISPLAY_PLANE_ENABLE; - OUTREG(ctrl, temp); - /* Flush changes */ - temp = INREG(base); - OUTREG(base, temp); + for (i = 0; i < pI830->availablePipes; i++) { + if (i == 0) { + ctrl = DSPACNTR; + base = DSPABASE; + } else { + ctrl = DSPBCNTR; + base = DSPBADDR; + } + if (pI830->planeEnabled[i]) { + temp = INREG(ctrl); + if (on) + temp |= DISPLAY_PLANE_ENABLE; + else + temp &= ~DISPLAY_PLANE_ENABLE; + OUTREG(ctrl, temp); + /* Flush changes */ + temp = INREG(base); + OUTREG(base, temp); + } } if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { @@ -4292,63 +4295,91 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) return TRUE; } +static void +I830DPMSCRT(ScrnInfoPtr pScrn, int mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + + temp = INREG(ADPA); + temp &= ~(ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE); + switch(mode) { + case DPMSModeOn: + break; + case DPMSModeStandby: + temp |= ADPA_HSYNC_CNTL_DISABLE; + break; + case DPMSModeSuspend: + temp |= ADPA_VSYNC_CNTL_DISABLE; + break; + case DPMSModeOff: + temp |= ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE; + break; + } + OUTREG(ADPA, temp); +} + +static void +I830DPMSLVDS(ScrnInfoPtr pScrn, int mode) +{ + if (mode == DPMSModeOn) + i830SetLVDSPanelPower(pScrn, TRUE); + else + i830SetLVDSPanelPower(pScrn, FALSE); +} + /* Use the VBE version when available. */ static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) { I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; + int i; + CARD32 temp, ctrl, base; - if (pI830->Clone) { - SetBIOSPipe(pScrn, !pI830->pipe); - if (xf86LoaderCheckSymbol("VBEDPMSSet")) { - VBEDPMSSet(pVbe, PowerManagementMode); + for (i = 0; i < pI830->availablePipes; i++) { + if (i == 0) { + ctrl = DSPACNTR; + base = DSPABASE; } else { - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f10; - pVbe->pInt10->bx = 0x01; - - switch (PowerManagementMode) { - case DPMSModeOn: - break; - case DPMSModeStandby: - pVbe->pInt10->bx |= 0x0100; - break; - case DPMSModeSuspend: - pVbe->pInt10->bx |= 0x0200; - break; - case DPMSModeOff: - pVbe->pInt10->bx |= 0x0400; - break; - } - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + ctrl = DSPBCNTR; + base = DSPBADDR; + } + if (pI830->planeEnabled[i]) { + temp = INREG(ctrl); + if (PowerManagementMode == DPMSModeOn) + temp |= DISPLAY_PLANE_ENABLE; + else + temp &= ~DISPLAY_PLANE_ENABLE; + OUTREG(ctrl, temp); + /* Flush changes */ + temp = INREG(base); + OUTREG(base, temp); } } - SetPipeAccess(pScrn); + if (pI830->operatingDevices & (PIPE_CRT_ACTIVE | (PIPE_CRT_ACTIVE<<8))) { + I830DPMSCRT(pScrn, PowerManagementMode); + } - if (xf86LoaderCheckSymbol("VBEDPMSSet")) { - VBEDPMSSet(pVbe, PowerManagementMode); - } else { - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f10; - pVbe->pInt10->bx = 0x01; + if (pI830->operatingDevices & (PIPE_LCD_ACTIVE | (PIPE_LCD_ACTIVE<<8))) { + I830DPMSLVDS(pScrn, PowerManagementMode); + } - switch (PowerManagementMode) { - case DPMSModeOn: - break; - case DPMSModeStandby: - pVbe->pInt10->bx |= 0x0100; - break; - case DPMSModeSuspend: - pVbe->pInt10->bx |= 0x0200; - break; - case DPMSModeOff: - pVbe->pInt10->bx |= 0x0400; - break; - } - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (pI830->operatingDevices & (PIPE_DFP_ACTIVE | (PIPE_DFP_ACTIVE<<8))) { + /* TBD */ + } + + if (pI830->operatingDevices & (PIPE_DFP2_ACTIVE | (PIPE_DFP2_ACTIVE<<8))) { + /* TBD */ + } + + if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { + if (PowerManagementMode == DPMSModeOn) + pI830->CursorInfoRec->ShowCursor(pScrn); + else + pI830->CursorInfoRec->HideCursor(pScrn); + pI830->cursorOn = TRUE; } } From 34f6a8204f1edec015283fc6b5f196e47897e3de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Jun 2006 00:15:06 -0700 Subject: [PATCH 092/257] Get sDVO output working on mac mini. Add lots of register debugging to track delta from BIOS settings. Fix various mode settings to mirror BIOS sDVO values. Disable analog/lvds output on pipe with sDVO. Borrow Dave Airlie's I830xf86ValidateDDCModes code. Fix various sDVO I2C messages to mirror Dave's code. --- src/i810_reg.h | 3 +- src/i830.h | 2 + src/i830_debug.c | 13 +- src/i830_debug.h | 1 + src/i830_display.c | 30 ++-- src/i830_driver.c | 32 +++- src/i830_modes.c | 366 +++++++++++++++++++++++++++++++++++++++++++ src/i830_sdvo.c | 91 +++++++++-- src/i830_sdvo_regs.h | 2 + 9 files changed, 510 insertions(+), 30 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 53c65bbf..92e3342f 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -748,6 +748,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define TV_HOTPLUG_INT_STATUS (1 << 10) # define SDVOC_HOTPLUG_INT_STATUS (1 << 7) # define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) #define SDVOB 0x61140 #define SDVOC 0x61160 @@ -765,7 +766,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVOB_PCIE_CONCURRENCY (1 << 3) #define SDVO_DETECTED (1 << 2) /* Bits to be preserved when writing */ -#define SDVO_PRESERVE_MASK (1 << 17) +#define SDVOC_PRESERVE_MASK (1 << 17) #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff diff --git a/src/i830.h b/src/i830.h index c60bfbe6..8cf7b711 100644 --- a/src/i830.h +++ b/src/i830.h @@ -420,6 +420,7 @@ typedef struct _I830Rec { Bool devicePresence; OsTimerPtr devicesTimer; + int MaxClock; int ddc2; int num_outputs; @@ -589,6 +590,7 @@ extern Rotation I830GetRotation(ScreenPtr pScreen); extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_debug.c b/src/i830_debug.c index b5442577..6d43cd60 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -35,7 +35,7 @@ /* XXX: What was the syntax for sticking quotes around the "reg" argument? */ #define DEFINEREG(reg) \ - { reg, NULL, 0 } + { reg, #reg, 0 } static struct i830SnapshotRec { int reg; @@ -129,3 +129,14 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) } } } + +void i830DumpRegs (ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%10.10s: 0x%08x\n", + i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg)); + } +} diff --git a/src/i830_debug.h b/src/i830_debug.h index 269f03ea..a8e38398 100644 --- a/src/i830_debug.h +++ b/src/i830_debug.h @@ -27,3 +27,4 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn); void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn); +void i830DumpRegs (ScrnInfoPtr pScrn); diff --git a/src/i830_display.c b/src/i830_display.c index 95fa936d..d49da1f5 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -34,6 +34,7 @@ #include "i830.h" #include "i830_bios.h" #include "i830_display.h" +#include "i830_debug.h" /** Returns the pixel clock for the given refclk and divisors. */ static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) @@ -255,7 +256,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; - CARD32 pipesrc, dspsize, adpa, sdvoc = 0; + CARD32 pipesrc, dspsize, adpa; + CARD32 sdvob = 0, sdvoc= 0; Bool ok, is_sdvo; int refclk, pixel_clock; int outputs; @@ -391,13 +393,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC)); - sdvoc = INREG(SDVOC) & SDVO_PRESERVE_MASK; - sdvoc |= SDVO_ENABLE; + sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK; + sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK; + sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE; + sdvoc |= 9 << 19; if (pipe == 1) - sdvoc |= SDVO_PIPE_B_SELECT; - // sdvoc |= SDVO_PHASE_SELECT_DEFAULT; - sdvoc |= SDVO_BORDER_ENABLE; + sdvob |= SDVO_PIPE_B_SELECT; OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); + OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); } fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); @@ -434,7 +437,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) FatalError("unknown display bpp\n"); } - adpa = ADPA_DAC_ENABLE; + if (is_sdvo) + adpa = ADPA_DAC_DISABLE; + else + adpa = ADPA_DAC_ENABLE; if (pMode->Flags & V_PHSYNC) adpa |= ADPA_HSYNC_ACTIVE_HIGH; if (pMode->Flags & V_PVSYNC) @@ -466,9 +472,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(FPA0, fp); OUTREG(DPLL_A, dpll); - if (is_sdvo) - OUTREG(SDVOC, sdvoc); - OUTREG(HTOTAL_A, htot); OUTREG(HBLANK_A, hblank); OUTREG(HSYNC_A, hsync); @@ -487,6 +490,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPACNTR, dspcntr); + + if (is_sdvo) { + OUTREG(SDVOB, sdvob); + OUTREG(SDVOC, sdvoc); + } } else { /* Always make sure the LVDS is off before we play with DPLLs and pipe * configuration. @@ -637,6 +645,8 @@ done: I830DRIUnlock(pScrn); #endif + i830DumpRegs (pScrn); + I830DumpSDVO (pScrn); return ok; } diff --git a/src/i830_driver.c b/src/i830_driver.c index 425ddd5c..c91bf432 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2386,14 +2386,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum space available for video modes: %d kByte\n", memsize); + pI830->MaxClock = 300000; + /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. */ clockRanges = xnfcalloc(sizeof(ClockRange), 1); clockRanges->next = NULL; - clockRanges->minClock = 12000; /* XXX: Random number */ - clockRanges->maxClock = 400000; /* XXX: May be lower */ + /* 25MHz appears to be the smallest that works. */ + clockRanges->minClock = 25000; + clockRanges->maxClock = pI830->MaxClock; clockRanges->clockIndex = -1; /* programmable */ clockRanges->interlaceAllowed = TRUE; /* XXX check this */ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ @@ -2412,16 +2415,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } n = i830ValidateFPModes(pScrn, pScrn->display->modes); } else { + I830xf86ValidateDDCModes(pScrn, pScrn->display->modes); /* XXX minPitch, minHeight are random numbers. */ n = xf86ValidateModes(pScrn, pScrn->monitor->Modes, /* availModes */ pScrn->display->modes, /* modeNames */ clockRanges, /* clockRanges */ NULL, /* linePitches */ - 256, /* minPitch */ + 320, /* minPitch */ MAX_DISPLAY_PITCH, /* maxPitch */ - 64, /* pitchInc */ - pScrn->bitsPerPixel, /* minHeight */ + 64 * pScrn->bitsPerPixel, /* pitchInc */ + 200, /* minHeight */ MAX_DISPLAY_HEIGHT, /* maxHeight */ pScrn->display->virtualX, /* virtualX */ pScrn->display->virtualY, /* virtualY */ @@ -2444,6 +2448,24 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + /* + * Fix up modes to make hblank start at hsync start. + * I don't know why the xf86 code mangles this... + */ + { + DisplayModePtr p; + + for (p = pScrn->modes; p;) { + xf86DrvMsg (pScrn->scrnIndex, + X_INFO, "move blank start from %d to %d\n", + p->CrtcHBlankStart, p->CrtcHDisplay); + p->CrtcHBlankStart = p->CrtcHDisplay; + p = p->next; + if (p == pScrn->modes) + break; + } + } + pScrn->currentMode = pScrn->modes; #ifndef USE_PITCHES diff --git a/src/i830_modes.c b/src/i830_modes.c index 16576bbe..ce86d8ca 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -44,6 +44,52 @@ #include "xf86.h" #include "i830.h" +#include + +#define rint(x) floor(x) + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#define MARGIN_PERCENT 1.8 /* % of active vertical image */ +#define CELL_GRAN 8.0 /* assumed character cell granularity */ +#define MIN_PORCH 1 /* minimum front porch */ +#define V_SYNC_RQD 3 /* width of vsync in lines */ +#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */ +#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */ +#define M 600.0 /* blanking formula gradient */ +#define C 40.0 /* blanking formula offset */ +#define K 128.0 /* blanking formula scaling factor */ +#define J 20.0 /* blanking formula scaling factor */ + +/* C' and M' are part of the Blanking Duty Cycle computation */ + +#define C_PRIME (((C - J) * K/256.0) + J) +#define M_PRIME (K/256.0 * M) +/* Established timings from EDID standard */ +static struct +{ + int hsize; + int vsize; + int refresh; +} est_timings[] = { + {1280, 1024, 75}, + {1024, 768, 75}, + {1024, 768, 70}, + {1024, 768, 60}, + {1024, 768, 87}, + {832, 624, 75}, + {800, 600, 75}, + {800, 600, 72}, + {800, 600, 60}, + {800, 600, 56}, + {640, 480, 75}, + {640, 480, 72}, + {640, 480, 67}, + {640, 480, 60}, + {720, 400, 88}, + {720, 400, 70}, +}; + extern const int i830refreshes[]; void @@ -108,3 +154,323 @@ I830PrintModes(ScrnInfoPtr scrp) p = p->next; } while (p != NULL && p != scrp->modes); } + +/* This function will sort all modes according to their resolution. + * Highest resolution first. + */ +void +I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first, + DisplayModePtr *last) +{ + DisplayModePtr p; + + p = *last; + while (p) { + if ((((*new)->HDisplay < p->HDisplay) && + ((*new)->VDisplay < p->VDisplay)) || + (((*new)->HDisplay == p->HDisplay) && + ((*new)->VDisplay == p->VDisplay) && + ((*new)->Clock < p->Clock))) { + + if (p->next) p->next->prev = *new; + (*new)->prev = p; + (*new)->next = p->next; + p->next = *new; + if (!((*new)->next)) *last = *new; + break; + } + if (!p->prev) { + (*new)->prev = NULL; + (*new)->next = p; + p->prev = *new; + *first = *new; + break; + } + p = p->prev; + } + + if (!*first) { + *first = *new; + (*new)->prev = NULL; + (*new)->next = NULL; + *last = *new; + } +} + +DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn) +{ + DisplayModePtr p; + DisplayModePtr last = NULL; + DisplayModePtr new = NULL; + DisplayModePtr first = NULL; + int count = 0; + int j, tmp; + char stmp[32]; + xf86MonPtr ddc = pScrn->monitor->DDC; + + /* Go thru detailed timing table first */ + for (j = 0; j < 4; j++) { + if (ddc->det_mon[j].type == 0) { + struct detailed_timings *d_timings = + &ddc->det_mon[j].section.d_timings; + + if (d_timings->h_active == 0 || d_timings->v_active == 0) break; + + new = xnfcalloc(1, sizeof (DisplayModeRec)); + memset(new, 0, sizeof (DisplayModeRec)); + + new->HDisplay = d_timings->h_active; + new->VDisplay = d_timings->v_active; + + sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay); + new->name = xnfalloc(strlen(stmp) + 1); + strcpy(new->name, stmp); + + new->HTotal = new->HDisplay + d_timings->h_blanking; + new->HSyncStart = new->HDisplay + d_timings->h_sync_off; + new->HSyncEnd = new->HSyncStart + d_timings->h_sync_width; + new->VTotal = new->VDisplay + d_timings->v_blanking; + new->VSyncStart = new->VDisplay + d_timings->v_sync_off; + new->VSyncEnd = new->VSyncStart + d_timings->v_sync_width; + new->Clock = d_timings->clock / 1000; + new->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + new->status = MODE_OK; + new->type = M_T_DEFAULT; + + if (d_timings->sync == 3) { + switch (d_timings->misc) { + case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break; + } + } + count++; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid Mode from Detailed timing table: %s (ht %d hss %d hse %d vt %d vss %d vse %d)\n", + new->name, + new->HTotal, new->HSyncStart, new->HSyncEnd, + new->VTotal, new->VSyncStart, new->VSyncEnd); + + I830xf86SortModes(&new, &first, &last); + } + } + + /* Search thru standard VESA modes from EDID */ + for (j = 0; j < 8; j++) { + if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0) + continue; + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + /* Ignore all double scan modes */ + if ((ddc->timings2[j].hsize == p->HDisplay) && + (ddc->timings2[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + float err = (float)ddc->timings2[j].refresh - refresh; + + if (err < 0) err = -err; + if (err < 1.0) { + /* Is this good enough? */ + new = xnfcalloc(1, sizeof (DisplayModeRec)); + memcpy(new, p, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(p->name) + 1); + strcpy(new->name, p->name); + new->status = MODE_OK; + new->type = M_T_DEFAULT; + + count++; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid Mode from standard timing table: %s\n", + new->name); + + I830xf86SortModes(&new, &first, &last); + break; + } + } + } + } + + /* Search thru established modes from EDID */ + tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2; + for (j = 0; j < 16; j++) { + if (tmp & (1 << j)) { + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + if ((est_timings[j].hsize == p->HDisplay) && + (est_timings[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + float err = (float)est_timings[j].refresh - refresh; + + if (err < 1.0) { + /* Is this good enough? */ + new = xnfcalloc(1, sizeof (DisplayModeRec)); + memcpy(new, p, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(p->name) + 1); + strcpy(new->name, p->name); + new->status = MODE_OK; + new->type = M_T_DEFAULT; + + count++; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid Mode from established timing " + "table: %s\n", new->name); + + I830xf86SortModes(&new, &first, &last); + break; + } + } + } + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total of %d mode(s) found.\n", count); + + return first; +} + +/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, + * so here is our own validation routine. + */ +int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName) +{ + DisplayModePtr p; + DisplayModePtr last = NULL; + DisplayModePtr first = NULL; + DisplayModePtr ddcModes = NULL; + int count = 0; + int i, width, height; + ScrnInfoPtr pScrn = pScrn1; + + pScrn->virtualX = pScrn1->display->virtualX; + pScrn->virtualY = pScrn1->display->virtualY; + + if (pScrn->monitor->DDC) { + int maxVirtX = pScrn->virtualX; + int maxVirtY = pScrn->virtualY; + + /* Collect all of the DDC modes */ + first = last = ddcModes = I830xf86DDCModes(pScrn); + + for (p = ddcModes; p; p = p->next) { + + maxVirtX = MAX(maxVirtX, p->HDisplay); + maxVirtY = MAX(maxVirtY, p->VDisplay); + count++; + + last = p; + } + + /* Match up modes that are specified in the XF86Config file */ + if (ppModeName[0]) { + DisplayModePtr next; + + /* Reset the max virtual dimensions */ + maxVirtX = pScrn->virtualX; + maxVirtY = pScrn->virtualY; + + /* Reset list */ + first = last = NULL; + + for (i = 0; ppModeName[i]; i++) { + /* FIXME: Use HDisplay and VDisplay instead of mode string */ + if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) { + for (p = ddcModes; p; p = next) { + next = p->next; + + if (p->HDisplay == width && p->VDisplay == height) { + /* We found a DDC mode that matches the one + requested in the XF86Config file */ + p->type |= M_T_USERDEF; + + /* Update the max virtual setttings */ + maxVirtX = MAX(maxVirtX, width); + maxVirtY = MAX(maxVirtY, height); + + /* Unhook from DDC modes */ + if (p->prev) p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + if (p == ddcModes) ddcModes = p->next; + + /* Add to used modes */ + if (last) { + last->next = p; + p->prev = last; + } else { + first = p; + p->prev = NULL; + } + p->next = NULL; + last = p; + + break; + } + } + } + } + + /* + * Add remaining DDC modes if they're smaller than the user + * specified modes + */ + for (p = ddcModes; p; p = next) { + next = p->next; + if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) { + /* Unhook from DDC modes */ + if (p->prev) p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + if (p == ddcModes) ddcModes = p->next; + + /* Add to used modes */ + if (last) { + last->next = p; + p->prev = last; + } else { + first = p; + p->prev = NULL; + } + p->next = NULL; + last = p; + } + } + + /* Delete unused modes */ + while (ddcModes) + xf86DeleteMode(&ddcModes, ddcModes); + } else { + /* + * No modes were configured, so we make the DDC modes + * available for the user to cycle through. + */ + for (p = ddcModes; p; p = p->next) + p->type |= M_T_USERDEF; + } + + pScrn->virtualX = pScrn->display->virtualX = maxVirtX; + pScrn->virtualY = pScrn->display->virtualY = maxVirtY; + } + + /* Close the doubly-linked mode list, if we found any usable modes */ + if (last) { + DisplayModePtr temp = NULL; + /* we should add these to pScrn monitor modes */ + last->next = pScrn->monitor->Modes; + temp = pScrn->monitor->Modes->prev; + pScrn->monitor->Modes->prev = first; + pScrn->monitor->Modes->prev = last; + + first->prev = temp; + if (temp) + temp->next = first; + + pScrn->monitor->Modes = first; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total number of valid DDC mode(s) found: %d\n", count); + + return count; +} diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 579f77ab..7d239759 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -139,7 +139,7 @@ I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2) s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; - I830SDVOWriteOutputs(s, 1); + I830SDVOWriteOutputs(s, 2); I830SDVOReadInputRegs(s); @@ -218,7 +218,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2) s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; - I830SDVOWriteOutputs(s, 1); + I830SDVOWriteOutputs(s, 2); I830SDVOReadInputRegs(s); return TRUE; @@ -259,7 +259,7 @@ I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) return TRUE; } -/* Fetches either input or output timings to *dtd, depending on cmd. */ +/* Sets either input or output timings to *dtd, depending on cmd. */ Bool I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) { @@ -286,7 +286,7 @@ I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags; s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high; s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved; - I830SDVOWriteOutputs(s, 8); + I830SDVOWriteOutputs(s, 7); I830SDVOReadInputRegs(s); return TRUE; @@ -477,6 +477,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) CARD8 c17a[8]; CARD16 out_timings[6]; CARD16 clock_min, clock_max; + Bool out1, out2; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -516,30 +517,41 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) out_timings[4] = c17a[5] | ((short)c17a[4] << 8); out_timings[5] = c17a[3] | ((short)c17a[2] << 8); - I830SDVOSetTargetInput(s, TRUE, TRUE); + I830SDVOSetTargetInput(s, FALSE, FALSE); I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max); ErrorF("clock min/max: %d %d\n", clock_min, clock_max); + I830SDVOGetActiveOutputs(s, &out1, &out2); + I830SDVOSetActiveOutputs(s, FALSE, FALSE); - I830SDVOSetTargetOutput(s, TRUE, TRUE); + I830SDVOSetTargetOutput(s, TRUE, FALSE); I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1], out_timings[2]); I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4], out_timings[5]); + I830SDVOSetTargetInput (s, FALSE, FALSE); + I830SDVOCreatePreferredInputTiming(s, clock, width, height); I830SDVOGetPreferredInputTimingPart1(s); I830SDVOGetPreferredInputTimingPart2(s); + + I830SDVOSetTargetInput (s, FALSE, FALSE); + I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1], curr_table[2]); I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4], out_timings[5]); - /*if (mode->PrivFlags & I830_MFLAG_DOUBLE) - I830SDVOSetClockRateMult(s, 0x02); - else */ - I830SDVOSetClockRateMult(s, 0x01); + I830SDVOSetTargetInput (s, FALSE, FALSE); + + if (clock >= 10000) + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X); + else if (clock >= 5000) + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X); + else + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X); return TRUE; } @@ -548,6 +560,7 @@ Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) { Bool ret = TRUE; + Bool out1, out2; /* the BIOS writes out 6 commands post mode set */ /* two 03s, 04 05, 10, 1d */ @@ -564,7 +577,9 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) ret = FALSE; } - I830SDVOSetActiveOutputs(s, TRUE, TRUE); + I830SDVOGetActiveOutputs (s, &out1, &out2); + I830SDVOSetActiveOutputs(s, TRUE, FALSE); + I830SDVOSetTargetInput (s, FALSE, FALSE); return ret; } @@ -580,7 +595,7 @@ i830SDVOSave(ScrnInfoPtr pScrn, int output_index) &sdvo->save_sdvo_active_2); if (sdvo->caps.caps & 0x1) { - I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOSetTargetInput(sdvo, FALSE, FALSE); I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1, SDVO_CMD_GET_INPUT_TIMINGS_PART1); } @@ -622,7 +637,7 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; if (sdvo->caps.caps & 0x1) { - I830SDVOSetTargetInput(sdvo, TRUE, FALSE); + I830SDVOSetTargetInput(sdvo, FALSE, FALSE); I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, SDVO_CMD_SET_INPUT_TIMINGS_PART1); } @@ -830,3 +845,53 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) return sdvo; } + +static void +I830DumpSDVOCmd (I830SDVOPtr s, int opcode) +{ + memset (s->sdvo_regs, 0, sizeof (s->sdvo_regs)); + s->sdvo_regs[SDVO_I2C_OPCODE] = opcode; + I830SDVOWriteOutputs (s, 0); + I830SDVOReadInputRegs (s); +} + +static void +I830DumpOneSDVO (I830SDVOPtr s) +{ + ErrorF ("Dump %s\n", s->d.DevName); + I830DumpSDVOCmd (s, SDVO_CMD_GET_DEVICE_CAPS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_FIRMWARE_REV); + I830DumpSDVOCmd (s, SDVO_CMD_GET_TRAINED_INPUTS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_OUTPUTS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_IN_OUT_MAP); + I830DumpSDVOCmd (s, SDVO_CMD_GET_ATTACHED_DISPLAYS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_HOT_PLUG_SUPPORT); + I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_HOT_PLUG); + I830DumpSDVOCmd (s, SDVO_CMD_GET_INTR_EVENT_SOURCE); + I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART1); + I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART2); + I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2); + I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1); + I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2); + I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE); + I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE); + I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_CLOCK_RATE_MULT); + I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_TV_FORMATS); + I830DumpSDVOCmd (s, SDVO_CMD_GET_TV_FORMAT); +} + +void +I830DumpSDVO (ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr s; + int i; + + for (i = 0; i < 4; i++) { + s = pI830->output[i].sdvo_drv; + if (s) + I830DumpOneSDVO (s); + } +} diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index 37cfcf2e..a35d5a4e 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -157,7 +157,9 @@ #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 # define SDVO_CLOCK_RATE_MULT_1X (1 << 0) # define SDVO_CLOCK_RATE_MULT_2X (1 << 1) +# define SDVO_CLOCK_RATE_MULT_3X (1 << 2) # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) +# define SDVO_CLOCK_RATE_MULT_5X (1 << 4) #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 From b5acc6b3a3a3a109014d6b971f4722d0f0a4c29a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Jun 2006 13:22:17 -0700 Subject: [PATCH 093/257] Add backlight control to DPMS logic. Turn backlight on and off in response to DPMS state changes. --- src/i810_reg.h | 7 +++++++ src/i830.h | 3 +++ src/i830_display.c | 13 +++++++++++++ src/i830_driver.c | 12 ++++++++++++ 4 files changed, 35 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index 53c65bbf..f7ba930f 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -728,6 +728,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define SDVO_MULTIPLIER_MASK 0x000000ff # define SDVO_DEFAULT_MULTIPLIER 0x00000003 +#define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) + #define FPA0 0x06040 #define FPA1 0x06044 #define FPB0 0x06048 diff --git a/src/i830.h b/src/i830.h index c60bfbe6..0c47f7d0 100644 --- a/src/i830.h +++ b/src/i830.h @@ -440,6 +440,8 @@ typedef struct _I830Rec { int panel_fixed_vsyncoff; int panel_fixed_vsyncwidth; + int backlight_duty_cycle; /* restore backlight to this value */ + Bool panel_wants_dither; unsigned char *VBIOS; @@ -493,6 +495,7 @@ typedef struct _I830Rec { CARD32 savePaletteA[256]; CARD32 savePaletteB[256]; CARD32 saveSWF[17]; + CARD32 saveBLC_PWM_CTL; } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) diff --git a/src/i830_display.c b/src/i830_display.c index 95fa936d..7b9773a0 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -664,7 +664,14 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) { I830Ptr pI830 = I830PTR(pScrn); CARD32 pp_status, pp_control; + CARD32 blc_pwm_ctl; + int backlight_duty_cycle; + blc_pwm_ctl = INREG (BLC_PWM_CTL); + backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK; + if (backlight_duty_cycle) + pI830->backlight_duty_cycle = backlight_duty_cycle; + if (on) { OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); @@ -672,7 +679,13 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) pp_status = INREG(PP_STATUS); pp_control = INREG(PP_CONTROL); } while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON)); + OUTREG(BLC_PWM_CTL, + (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) | + pI830->backlight_duty_cycle); } else { + OUTREG(BLC_PWM_CTL, + (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK)); + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); do { diff --git a/src/i830_driver.c b/src/i830_driver.c index 425ddd5c..3a7b54a4 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2925,6 +2925,17 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveLVDS = INREG(LVDS); pI830->savePP_CONTROL = INREG(PP_CONTROL); pI830->savePP_CYCLE = INREG(PP_CYCLE); + pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); + pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + /* + * If the light is off at server startup, just make it full brightness + */ + if (!pI830->backlight_duty_cycle) + pI830->backlight_duty_cycle = ((pI830->saveBLC_PWM_CTL & + BACKLIGHT_MODULATION_FREQ_MASK) >> + BACKLIGHT_MODULATION_FREQ_SHIFT); + if (!IS_I9XX(pI830)) { pI830->saveDVOA = INREG(DVOA); @@ -3031,6 +3042,7 @@ RestoreHWState(ScrnInfoPtr pScrn) } } + OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); OUTREG(LVDSPP_ON, pI830->savePP_ON); OUTREG(LVDSPP_OFF, pI830->savePP_OFF); OUTREG(PP_CYCLE, pI830->savePP_CYCLE); From 2fb375b665f4802819b89f2277fd6154006c11ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Jun 2006 13:24:57 -0700 Subject: [PATCH 094/257] Set vblank interrupt configuration to match pipe configuration New i915 drm ioctl (in version 1.5) allows the X server to select which pipe drives vblank interrupts. Use this to drive from the 'preferred' pipe. Yes, per-window vblanks would be nice in a shared fb environment. Maybe someday. --- src/i830.h | 1 + src/i830_common.h | 9 +++++++++ src/i830_display.c | 3 +++ src/i830_dri.c | 25 +++++++++++++++++++++++++ src/i830_driver.c | 3 +++ 5 files changed, 41 insertions(+) diff --git a/src/i830.h b/src/i830.h index 0c47f7d0..aa9b275f 100644 --- a/src/i830.h +++ b/src/i830.h @@ -546,6 +546,7 @@ extern void I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea); extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea); extern void I830DRIUnlock(ScrnInfoPtr pScrn); extern Bool I830DRILock(ScrnInfoPtr pScrn); +extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on); #endif extern Bool I830AccelInit(ScreenPtr pScreen); diff --git a/src/i830_common.h b/src/i830_common.h index 41b5cc3c..a27bc011 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -52,6 +52,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define DRM_I830_INIT_HEAP 0x0a #define DRM_I830_CMDBUFFER 0x0b #define DRM_I830_DESTROY_HEAP 0x0c +#define DRM_I830_SET_VBLANK_PIPE 0x0d +#define DRM_I830_GET_VBLANK_PIPE 0x0e + typedef struct { enum { @@ -193,5 +196,11 @@ typedef struct { int region; } drmI830MemDestroyHeap; +#define DRM_I830_VBLANK_PIPE_A 1 +#define DRM_I830_VBLANK_PIPE_B 2 + +typedef struct { + int pipe; +} drmI830VBlankPipe; #endif /* _I830_DRM_H_ */ diff --git a/src/i830_display.c b/src/i830_display.c index 7b9773a0..a8336750 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -631,6 +631,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) pI830->planeEnabled[1] ? "enabled" : "disabled", planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); +#ifdef XF86DRI + I830DRISetVBlankInterrupt (pScrn, TRUE); +#endif done: #ifdef XF86DRI if (didLock) diff --git a/src/i830_dri.c b/src/i830_dri.c index 762d3d95..0cd3ed0b 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1448,6 +1448,31 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) return success; } +Bool +I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) +{ + I830Ptr pI830 = I830PTR(pScrn); + drmI830VBlankPipe pipe; + + if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { + if (on) { + if (pI830->planeEnabled[1]) + pipe.pipe = DRM_I830_VBLANK_PIPE_B; + else + pipe.pipe = DRM_I830_VBLANK_PIPE_A; + } else { + pipe.pipe = 0; + } + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SET_VBLANK_PIPE, + &pipe, sizeof (pipe))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed\n"); + return FALSE; + } + } + + return TRUE; +} + Bool I830DRILock(ScrnInfoPtr pScrn) { diff --git a/src/i830_driver.c b/src/i830_driver.c index 3a7b54a4..0a04aadf 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2976,6 +2976,9 @@ RestoreHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreHWState\n"); +#ifdef XF86DRI + I830DRISetVBlankInterrupt (pScrn, FALSE); +#endif vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); vgaHWLock(hwp); From ab60e34dcfc52ab5f22a82145d5b4db51b4c62c5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 10:07:47 -0700 Subject: [PATCH 095/257] Add debugging info for pipe/display plane size. --- src/i830_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 95fa936d..73e976f8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -411,6 +411,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) (int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1, (int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1, (int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1); + ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n", + (int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1, + (int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1); #endif i830PrintPll("chosen", refclk, m1, m2, n, p1, p2); From e4584a4f44a70d746396ed48b8e40033504d68b2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 10:39:28 -0700 Subject: [PATCH 096/257] Remove dead DisplayInfo option. --- man/i810.man | 6 ------ src/i830.h | 1 - src/i830_driver.c | 19 ------------------- 3 files changed, 26 deletions(-) diff --git a/man/i810.man b/man/i810.man index 099e1f8a..f6b73689 100644 --- a/man/i810.man +++ b/man/i810.man @@ -179,12 +179,6 @@ NOTE: Using this option may cause text mode to be restored incorrectly, and thus should be used with caution. Default: disabled. .TP -.BI "Option \*qDisplayInfo\*q \*q" boolean \*q -It has been found that a certain BIOS call can lockup the Xserver because -of a problem in the Video BIOS. The log file will identify if you are -suffering from this problem and tell you to turn this option off. -Default: enabled -.TP .BI "Option \*qDevicePresence\*q \*q" boolean \*q Tell the driver to perform an active detect of the currently connected monitors. This option is useful if the monitor was not connected when diff --git a/src/i830.h b/src/i830.h index c60bfbe6..efd9f6d5 100644 --- a/src/i830.h +++ b/src/i830.h @@ -416,7 +416,6 @@ typedef struct _I830Rec { unsigned int SaveGeneration; Bool vbeRestoreWorkaround; - Bool displayInfo; Bool devicePresence; OsTimerPtr devicesTimer; diff --git a/src/i830_driver.c b/src/i830_driver.c index 425ddd5c..a4fde942 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -261,7 +261,6 @@ static OptionInfoRec I830BIOSOptions[] = { {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VBE_RESTORE, "VBERestore", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_DISPLAY_INFO,"DisplayInfo", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0}, FALSE}, {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, @@ -2252,24 +2251,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } } - /* Buggy BIOS 3066 is known to cause this, so turn this off */ - if (pI830->bios_version == 3066) { - pI830->displayInfo = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected Broken Video BIOS, turning off displayInfo.\n"); - } else - pI830->displayInfo = TRUE; - from = X_DEFAULT; - if (!xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, TRUE)) { - pI830->displayInfo = FALSE; - from = X_CONFIG; - } - if (xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, FALSE)) { - pI830->displayInfo = TRUE; - from = X_CONFIG; - } - xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n", - pI830->displayInfo ? "enabled" : "disabled"); - PrintDisplayDeviceInfo(pScrn); if (xf86IsEntityShared(pScrn->entityList[0])) { From 0b76646666e9d330e77c6f81af8b91e34623be92 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 13:57:26 -0700 Subject: [PATCH 097/257] Add CRT detection function by testing for load, and clean up hotplug version. --- src/i810_reg.h | 5 +++ src/i830_display.c | 105 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 53c65bbf..c45368df 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -746,6 +746,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PORT_HOTPLUG_STAT 0x61114 # define CRT_HOTPLUG_INT_STATUS (1 << 11) # define TV_HOTPLUG_INT_STATUS (1 << 10) +# define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +# define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +# define CRT_HOTPLUG_MONITOR_NONE (0 << 8) # define SDVOC_HOTPLUG_INT_STATUS (1 << 7) # define SDVOB_HOTPLUG_INT_STATUS (1 << 6) @@ -830,6 +834,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PIPEACONF_PIPE_LOCKED (1<<25) #define PIPEACONF_PALETTE 0 #define PIPEACONF_GAMMA (1<<24) +#define PIPECONF_FORCE_BORDER (1<<25) #define PIPEBCONF 0x71008 #define PIPEBCONF_ENABLE (1<<31) diff --git a/src/i830_display.c b/src/i830_display.c index 73e976f8..6146933d 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -643,20 +643,109 @@ done: return ok; } +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. + * + * Only for I945G/GM. + */ +static Bool +i830HotplugDetectCRT(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + const int timeout_ms = 1000; + int starttime, curtime; + + temp = INREG(PORT_HOTPLUG_EN); + + OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5)); + + for (curtime = starttime = GetTimeInMillis(); + (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis()) + { + if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0) + break; + } + + if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == + CRT_HOTPLUG_MONITOR_COLOR) + { + return TRUE; + } else { + return FALSE; + } +} + +/** + * Detects CRT presence by checking for load. + * + * Requires that the current pipe's DPLL is active. This will cause flicker + * on the CRT, so it should not be used while the display is being used. Only + * color (not monochrome) displays are detected. + */ +static Bool +i830LoadDetectCRT(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 adpa, pipeconf; + CARD8 st00; + int pipeconf_reg, bclrpat_reg, dpll_reg; + int pipe; + + pipe = pI830->pipe; + if (pipe == 0) { + bclrpat_reg = BCLRPAT_A; + pipeconf_reg = PIPEACONF; + dpll_reg = DPLL_A; + } else { + bclrpat_reg = BCLRPAT_B; + pipeconf_reg = PIPEBCONF; + dpll_reg = DPLL_B; + } + + /* Don't try this if the DPLL isn't running. */ + if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE)) + return FALSE; + + adpa = INREG(ADPA); + + /* Enable CRT output if disabled. */ + if (!(adpa & ADPA_DAC_ENABLE)) { + OUTREG(ADPA, adpa | ADPA_DAC_ENABLE | + ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); + } + + /* Set the border color to red, green. Maybe we should save/restore this + * reg. + */ + OUTREG(bclrpat_reg, 0x00500050); + + /* Force the border color through the active region */ + pipeconf = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); + + /* Read the ST00 VGA status register */ + st00 = pI830->readStandard(pI830, 0x3c2); + + /* Restore previous settings */ + OUTREG(pipeconf_reg, pipeconf); + OUTREG(ADPA, adpa); + + if (st00 & (1 << 4)) + return TRUE; + else + return FALSE; +} + Bool i830DetectCRT(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; - temp = INREG(PORT_HOTPLUG_EN); - OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT); + if (IS_I945G(pI830) || IS_I945GM(pI830)) + return i830HotplugDetectCRT(pScrn); - /* Wait for the bit to clear to signal detection finished. */ - while (INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) - ; - - return ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_INT_STATUS)); + return i830LoadDetectCRT(pScrn); } /** From b454c9601f005c69c11556a558150403378d34d9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 14:32:40 -0700 Subject: [PATCH 098/257] Add support for CRT detection using DDC. This method is slower (~5ms), but works on older chipsets. Also, load-based detection is disabled, as it can be fooled by other outputs on the pipe being active, such as LVDS. --- src/i830_display.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- src/i830_display.h | 2 +- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 6146933d..3a4833e2 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -737,15 +737,57 @@ i830LoadDetectCRT(ScrnInfoPtr pScrn) return FALSE; } +/** + * Detects CRT presence by probing for a response on the DDC address. + * + * This takes approximately 5ms in testing on an i915GM, with CRT connected or + * not. + */ Bool -i830DetectCRT(ScrnInfoPtr pScrn) +i830DDCDetectCRT(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + struct _I830OutputRec *output; + + output = &pI830->output[0]; + /* CRT should always be at 0, but check anyway */ + if (output->type != I830_OUTPUT_ANALOG) + return FALSE; + + return xf86I2CProbeAddress(output->pDDCBus, 0x00A0); +} + +/** + * Attempts to detect CRT presence through any method available. + * + * @param allow_disturb enables detection methods that may cause flickering + * on active displays. + */ +Bool +i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool found_ddc; if (IS_I945G(pI830) || IS_I945GM(pI830)) return i830HotplugDetectCRT(pScrn); - return i830LoadDetectCRT(pScrn); + found_ddc = i830DDCDetectCRT(pScrn); + if (found_ddc) + return TRUE; + + /* Use the load-detect method if we're not currently outputting to the CRT, + * or we don't care. + * + * Actually, the method is unreliable currently. We need to not share a + * pipe, as it seems having other outputs on that pipe will result in a + * false positive. + */ + if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { + return i830LoadDetectCRT(pScrn); + } + + return FALSE; } /** diff --git a/src/i830_display.h b/src/i830_display.h index aecf8dcd..2e61afce 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -27,7 +27,7 @@ /* i830_display.c */ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); -Bool i830DetectCRT(ScrnInfoPtr pScrn); +Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); From be08661e3126907c50c54485042fcde00b0da2b4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 14:48:03 -0700 Subject: [PATCH 099/257] Only default to enabling CRT or LVDS output if they're actually detected. Still, if we haven't detected any outputs automatically (including CRT through DDC), default to CRT anyway. --- src/i830_driver.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index a4fde942..dd3122ea 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1952,26 +1952,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType2 |= PIPE_LFP; } - for (i=0; inum_outputs; i++) { - if (pI830->output[i].MonInfo == NULL) - continue; - - switch (pI830->output[i].type) { - case I830_OUTPUT_ANALOG: - case I830_OUTPUT_DVO: - pI830->MonType1 |= PIPE_CRT; - break; - case I830_OUTPUT_LVDS: - pI830->MonType2 |= PIPE_LFP; - break; - case I830_OUTPUT_SDVO: - /* XXX DVO */ - break; - case I830_OUTPUT_UNUSED: - break; - } + if (i830DetectCRT(pScrn, TRUE)) { + pI830->MonType1 |= PIPE_CRT; } + /* And, if we haven't found anything (including CRT through DDC), assume + * that there's a CRT and that the user has set up some appropriate modes + * or something. + */ + if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) + pI830->MonType1 |= PIPE_CRT; + if (pI830->MonType1 != PIPE_NONE) pI830->pipe = 0; else From 89c2c4bc40b8c032915ccb3ed4f3c143c3d8db12 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jun 2006 15:10:19 -0700 Subject: [PATCH 100/257] Add #if 0-ed code I've been using for CRT detection debugging. --- src/i830_driver.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/i830_driver.c b/src/i830_driver.c index dd3122ea..bc375e7b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -4545,6 +4545,20 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) ScrnInfoPtr pScrn = (ScrnInfoPtr) arg; I830Ptr pI830 = I830PTR(pScrn); int cloned = 0; +#if 0 + Bool found_crt; + int start, finish; + + if (!pScrn->vtSema) + return 1000; + + start = GetTimeInMillis(); + found_crt = i830DetectCRT(pScrn, FALSE); + finish = GetTimeInMillis(); + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n", + found_crt ? "connected" : "disconnected", finish - start); +#endif if (pScrn->vtSema) { /* Check for monitor lid being closed/opened and act accordingly */ From 726443309d72134341cff1f6db978aa1d6e3ce52 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2006 15:38:19 -0700 Subject: [PATCH 101/257] Add decoding of SDVO command names for debug output. --- src/i830_sdvo.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 7d239759..c14277e2 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -58,6 +58,50 @@ static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) return TRUE; } + +#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} +const struct _sdvo_cmd_name { + CARD8 cmd; + char *name; +} sdvo_cmd_names[] = { + SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTR_EVENT_SOURCE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), +}; /* following on from tracing the intel BIOS i2c routines */ static void I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) @@ -67,6 +111,14 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]); for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) ErrorF("%02X ", s->sdvo_regs[i]); + for (; i > SDVO_I2C_ARG_7; i--) + ErrorF(" "); + for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { + if (s->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) { + ErrorF("(%s)", sdvo_cmd_names[i].name); + break; + } + } ErrorF("\n"); /* blast the output regs */ From 72e25a7488c2eabcc92e9e0769a89dee687f52fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2006 16:04:18 -0700 Subject: [PATCH 102/257] Fix SDVO output at low pixel clocks. I had interpreted the docs as saying that the multiplier setting would further divide the clock and stuff dummy bytes in. Instead, we have to set the DPLL at the higher clock rate, and the pixel multiplier just controls the stuffing of dummy bytes. Also, we have to set the multiplier both in the graphics chip and on the SDVO device on the other side. --- src/i810_reg.h | 4 +++- src/i830_display.c | 25 +++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index b95f795b..e8462f9d 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -726,7 +726,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) # define SDVO_MULTIPLIER_MASK 0x000000ff -# define SDVO_DEFAULT_MULTIPLIER 0x00000003 +# define SDVO_MULTIPLIER_SHIFT_HIRES 4 +# define SDVO_MULTIPLIER_SHIFT_VGA 0 #define BLC_PWM_CTL 0x61254 #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) @@ -769,6 +770,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVO_INTERRUPT_ENABLE (1 << 26) /* Programmed value is multiplier - 1, up to 5x. alv, gdg only */ #define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 #define SDVO_PHASE_SELECT_MASK (15 << 19) #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) diff --git a/src/i830_display.c b/src/i830_display.c index f1642da3..0fadc0c1 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -259,7 +259,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 pipesrc, dspsize, adpa; CARD32 sdvob = 0, sdvoc= 0; Bool ok, is_sdvo; - int refclk, pixel_clock; + int refclk, pixel_clock, sdvo_pixel_multiply; int outputs; ErrorF("Requested pix clock: %d\n", pMode->Clock); @@ -342,6 +342,22 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pixel_clock = pI830->panel_fixed_clock; } + if (pMode->Clock >= 100000) + sdvo_pixel_multiply = 1; + else if (pMode->Clock >= 50000) + sdvo_pixel_multiply = 2; + else + sdvo_pixel_multiply = 4; + + /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz. + * The clock on the bus is 10 times the pixel clock normally. If that + * would be too low, we run the DPLL at a multiple of the pixel clock, and + * tell the SDVO device the multiplier so it can throw away the dummy bytes. + */ + if (is_sdvo) { + pixel_clock *= sdvo_pixel_multiply; + } + if (IS_I9XX(pI830)) { refclk = 96000; } else { @@ -386,7 +402,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_REF_INPUT_TVCLKINBC; else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= SDVO_DEFAULT_MULTIPLIER; if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; @@ -399,6 +414,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) sdvoc |= 9 << 19; if (pipe == 1) sdvob |= SDVO_PIPE_B_SELECT; + + if (IS_I945G(pI830) || IS_I945GM(pI830)) + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + else + sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; + OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); } From 66d9a1be302ad34573de98de21cbdf6419592092 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2006 17:11:54 -0700 Subject: [PATCH 103/257] Detect SDVO display presence at startup and default to displaying to it, too. --- src/i830_display.c | 10 +++++----- src/i830_driver.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/i830_sdvo.c | 26 ++++++++++++++++++++++++++ src/i830_sdvo.h | 3 +++ 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 0fadc0c1..8843f989 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -514,11 +514,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(DSPACNTR, dspcntr); - - if (is_sdvo) { - OUTREG(SDVOB, sdvob); - OUTREG(SDVOC, sdvoc); - } } else { /* Always make sure the LVDS is off before we play with DPLLs and pipe * configuration. @@ -591,6 +586,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & PIPE_CRT_ACTIVE) OUTREG(ADPA, adpa); + if (is_sdvo) { + OUTREG(SDVOB, sdvob); + OUTREG(SDVOC, sdvoc); + } + return TRUE; } diff --git a/src/i830_driver.c b/src/i830_driver.c index c0938faa..c51587b0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1841,7 +1841,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830DetectMonitors(pScrn); - for (i = 0; i < MAX_OUTPUTS; i++) { + /* Walk from the end so we'll happen to hit SDVO first, if we found some. An + * SDVO device is probably a DFP, and so probably pickier than (say) a CRT + * that we might find early in the list. This hackery will go away when we + * start doing independent per-head mode selection. + */ + for (i = MAX_OUTPUTS - 1; i >= 0; i--) { if (pI830->output[i].MonInfo) { pScrn->monitor->DDC = pI830->output[i].MonInfo; xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); @@ -1956,6 +1961,23 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType1 |= PIPE_CRT; } + /* Check for attached SDVO outputs. Assume that they're flat panels for + * now. Though really, it's just a name at the moment, since we don't + * treat different SDVO outputs differently. + */ + for (i = 0; i < MAX_OUTPUTS; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO && + pI830->output[i].sdvo_drv != NULL) { + if (!I830DetectSDVODisplays(pScrn, i)) + continue; + + if (pI830->MonType1 == PIPE_NONE) + pI830->MonType1 |= PIPE_DFP; + else if (pI830->MonType2 == PIPE_NONE) + pI830->MonType2 |= PIPE_DFP; + } + } + /* And, if we haven't found anything (including CRT through DDC), assume * that there's a CRT and that the user has set up some appropriate modes * or something. @@ -4584,17 +4606,31 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) int cloned = 0; #if 0 Bool found_crt; - int start, finish; + int start, finish, i; if (!pScrn->vtSema) return 1000; start = GetTimeInMillis(); - found_crt = i830DetectCRT(pScrn, FALSE); + found_crt = i830DetectCRT(pScrn, FALSE); finish = GetTimeInMillis(); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n", found_crt ? "connected" : "disconnected", finish - start); + + for (i = 0; i < MAX_OUTPUTS; i++) { + Bool found_sdvo = TRUE; + + if (pI830->output[i].type != I830_OUTPUT_SDVO || + pI830->output[i].sdvo_drv == NULL) + { + continue; + } + start = GetTimeInMillis(); + found_sdvo = I830DetectSDVODisplays(pScrn, i); + finish = GetTimeInMillis(); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n", + found_sdvo ? "connected" : "disconnected", finish - start); + } #endif if (pScrn->vtSema) { diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index c14277e2..06840ef1 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -947,3 +947,29 @@ I830DumpSDVO (ScrnInfoPtr pScrn) I830DumpOneSDVO (s); } } + +/** + * Asks the SDVO device if any displays are currently connected. + * + * This interface will need to be augmented, since we could potentially have + * multiple displays connected, and the caller will also probably want to know + * what type of display is connected. But this is enough for the moment. + * + * Takes 14ms on average on my i945G. + */ +Bool +I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr s = pI830->output[output_index].sdvo_drv; + + s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS; + I830SDVOWriteOutputs(s, 0); + I830SDVOReadInputRegs(s); + + if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 || + s->sdvo_regs[SDVO_I2C_RETURN_1] != 0); +} diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 6b77c97a..d52eb607 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -63,3 +63,6 @@ i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index); void i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index); + +Bool +I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); From bb4810521633b6c3db2fc7d01ddc71325583d265 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 22 Jun 2006 09:38:27 -0700 Subject: [PATCH 104/257] Move FP mode validation next to other mode validation code. --- src/i830.h | 1 + src/i830_driver.c | 164 --------------------------------------------- src/i830_modes.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 164 deletions(-) diff --git a/src/i830.h b/src/i830.h index d5bb9c6c..26a0063e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -594,6 +594,7 @@ extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName); +int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_driver.c b/src/i830_driver.c index c51587b0..f3cb186a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1245,170 +1245,6 @@ I830IsPrimary(ScrnInfoPtr pScrn) return TRUE; } -static void -i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode) -{ - I830Ptr pI830 = I830PTR(pScrn); - - pMode->HTotal = pI830->panel_fixed_hactive; - pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; - pMode->HSyncEnd = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth; - pMode->VTotal = pI830->panel_fixed_vactive; - pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; - pMode->VSyncEnd = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth; - pMode->Clock = pI830->panel_fixed_clock; -} - -/** - * This function returns a default mode for flat panels using the timing - * information provided by the BIOS. - */ -static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr new; - char stmp[32]; - - if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0) - return NULL; - - /* Add native panel size */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - new->HDisplay = pI830->PanelXRes; - new->VDisplay = pI830->PanelYRes; - i830SetModeToPanelParameters(pScrn, new); - new->type = M_T_USERDEF; - - pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes); - pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes); - pScrn->display->virtualX = pScrn->virtualX; - pScrn->display->virtualY = pScrn->virtualY; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No valid mode specified, force to native mode\n"); - - return new; -} - -/* FP mode validation routine for using panel fitting. - */ -static int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr last = NULL; - DisplayModePtr new = NULL; - DisplayModePtr first = NULL; - DisplayModePtr p, tmp; - int count = 0; - int i, width, height; - - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - - /* We have a flat panel connected to the primary display, and we - * don't have any DDC info. - */ - for (i = 0; ppModeName[i] != NULL; i++) { - - if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) - continue; - - /* Note: We allow all non-standard modes as long as they do not - * exceed the native resolution of the panel. Since these modes - * need the internal RMX unit in the video chips (and there is - * only one per card), this will only apply to the primary head. - */ - if (width < 320 || width > pI830->PanelXRes || - height < 200 || height > pI830->PanelYRes) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", - ppModeName[i]); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Valid modes must be between 320x200-%dx%d\n", - pI830->PanelXRes, pI830->PanelYRes); - continue; - } - - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(ppModeName[i]) + 1); - strcpy(new->name, ppModeName[i]); - new->HDisplay = width; - new->VDisplay = height; - new->type |= M_T_USERDEF; - - i830SetModeToPanelParameters(pScrn, new); - - new->next = NULL; - new->prev = last; - - if (last) - last->next = new; - last = new; - if (!first) - first = new; - - pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); - pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height); - count++; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid mode using panel fitting: %s\n", new->name); - } - - /* If all else fails, add the native mode */ - if (!count) { - first = last = i830FPNativeMode(pScrn); - if (first) - count = 1; - } - - /* add in all default vesa modes smaller than panel size, used for randr*/ - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) { - tmp = first; - while (tmp) { - if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; - tmp = tmp->next; - } - if (!tmp) { - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->HDisplay = p->HDisplay; - new->VDisplay = p->VDisplay; - i830SetModeToPanelParameters(pScrn, new); - new->type |= M_T_DEFAULT; - - new->next = NULL; - new->prev = last; - - if (last) - last->next = new; - last = new; - if (!first) - first = new; - } - } - } - - /* Close the doubly-linked mode list, if we found any usable modes */ - if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total number of valid FP mode(s) found: %d\n", count); - - /* Adjust the display pitch to fit the modes we've come up with. */ - pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX); - pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63; - - return count; -} - static Bool I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) { diff --git a/src/i830_modes.c b/src/i830_modes.c index ce86d8ca..c0c258c2 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -332,6 +332,171 @@ DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn) return first; } +static void +i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pMode->HTotal = pI830->panel_fixed_hactive; + pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; + pMode->HSyncEnd = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth; + pMode->VTotal = pI830->panel_fixed_vactive; + pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; + pMode->VSyncEnd = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth; + pMode->Clock = pI830->panel_fixed_clock; +} + +/** + * This function returns a default mode for flat panels using the timing + * information provided by the BIOS. + */ +static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr new; + char stmp[32]; + + if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0) + return NULL; + + /* Add native panel size */ + new = xnfcalloc(1, sizeof (DisplayModeRec)); + sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); + new->name = xnfalloc(strlen(stmp) + 1); + strcpy(new->name, stmp); + new->HDisplay = pI830->PanelXRes; + new->VDisplay = pI830->PanelYRes; + i830SetModeToPanelParameters(pScrn, new); + new->type = M_T_USERDEF; + + pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes); + pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes); + pScrn->display->virtualX = pScrn->virtualX; + pScrn->display->virtualY = pScrn->virtualY; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No valid mode specified, force to native mode\n"); + + return new; +} + +/* FP mode validation routine for using panel fitting. + */ +int +i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr last = NULL; + DisplayModePtr new = NULL; + DisplayModePtr first = NULL; + DisplayModePtr p, tmp; + int count = 0; + int i, width, height; + + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + + /* We have a flat panel connected to the primary display, and we + * don't have any DDC info. + */ + for (i = 0; ppModeName[i] != NULL; i++) { + + if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) + continue; + + /* Note: We allow all non-standard modes as long as they do not + * exceed the native resolution of the panel. Since these modes + * need the internal RMX unit in the video chips (and there is + * only one per card), this will only apply to the primary head. + */ + if (width < 320 || width > pI830->PanelXRes || + height < 200 || height > pI830->PanelYRes) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", + ppModeName[i]); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Valid modes must be between 320x200-%dx%d\n", + pI830->PanelXRes, pI830->PanelYRes); + continue; + } + + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(ppModeName[i]) + 1); + strcpy(new->name, ppModeName[i]); + new->HDisplay = width; + new->VDisplay = height; + new->type |= M_T_USERDEF; + + i830SetModeToPanelParameters(pScrn, new); + + new->next = NULL; + new->prev = last; + + if (last) + last->next = new; + last = new; + if (!first) + first = new; + + pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); + pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height); + count++; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid mode using panel fitting: %s\n", new->name); + } + + /* If all else fails, add the native mode */ + if (!count) { + first = last = i830FPNativeMode(pScrn); + if (first) + count = 1; + } + + /* add in all default vesa modes smaller than panel size, used for randr*/ + for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) { + tmp = first; + while (tmp) { + if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; + tmp = tmp->next; + } + if (!tmp) { + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(p->name) + 1); + strcpy(new->name, p->name); + new->HDisplay = p->HDisplay; + new->VDisplay = p->VDisplay; + i830SetModeToPanelParameters(pScrn, new); + new->type |= M_T_DEFAULT; + + new->next = NULL; + new->prev = last; + + if (last) + last->next = new; + last = new; + if (!first) + first = new; + } + } + } + + /* Close the doubly-linked mode list, if we found any usable modes */ + if (last) { + last->next = first; + first->prev = last; + pScrn->modes = first; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total number of valid FP mode(s) found: %d\n", count); + + /* Adjust the display pitch to fit the modes we've come up with. */ + pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX); + pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63; + + return count; +} + /* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, * so here is our own validation routine. */ From 89791914d2a78f19f4f60ca370d387e5b1ccfb46 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 23 Jun 2006 18:21:17 -0700 Subject: [PATCH 105/257] Split probed modes out per pipe, and union them into the available modes. This is the first stage of getting runtime monitor attachment. The old i830 GTF code is returned to use to provide suitable modelines for xf86ValidateModes in the LVDS case, even though the LVDS doesn't care about the modeline and just always programs its fixed values. --- src/Makefile.am | 1 + src/i830.h | 11 +- src/i830_driver.c | 46 +----- src/i830_gtf.c | 356 ++++++++++++++++++++++++++++++++++++++++++ src/i830_modes.c | 385 +++++++++++++++++++++++++--------------------- 5 files changed, 575 insertions(+), 224 deletions(-) create mode 100644 src/i830_gtf.c diff --git a/src/Makefile.am b/src/Makefile.am index da48149e..8970db1e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,6 +55,7 @@ i810_drv_la_SOURCES = \ i830_display.h \ i830_driver.c \ i830.h \ + i830_gtf.c \ i830_i2c.c \ i830_io.c \ i830_memory.c \ diff --git a/src/i830.h b/src/i830.h index 26a0063e..59f563fc 100644 --- a/src/i830.h +++ b/src/i830.h @@ -399,9 +399,10 @@ typedef struct _I830Rec { /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; - int pipeDevices[MAX_DISPLAY_PIPES]; /* [0] is display plane A, [1] is display plane B. */ int planeEnabled[MAX_DISPLAY_PIPES]; + xf86MonPtr pipeMon[MAX_DISPLAY_PIPES]; + DisplayModePtr pipeModes[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ Bool preinit; @@ -593,8 +594,12 @@ extern Rotation I830GetRotation(ScreenPtr pScreen); extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); -int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName); -int i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName); +/* i830_modes.c */ +int I830ValidateXF86ModeList(ScrnInfoPtr pScrn); + +/* i830_gtf.c */ +DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, + int interlaced, int margins); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_driver.c b/src/i830_driver.c index f3cb186a..75f9e4b7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1258,7 +1258,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) int flags24; int i, n; char *s; - ClockRangePtr clockRanges; pointer pVBEModule = NULL; Bool enable, has_lvds; const char *chipname; @@ -2218,50 +2217,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MaxClock = 300000; - /* - * Setup the ClockRanges, which describe what clock ranges are available, - * and what sort of modes they can be used for. - */ - clockRanges = xnfcalloc(sizeof(ClockRange), 1); - clockRanges->next = NULL; - /* 25MHz appears to be the smallest that works. */ - clockRanges->minClock = 25000; - clockRanges->maxClock = pI830->MaxClock; - clockRanges->clockIndex = -1; /* programmable */ - clockRanges->interlaceAllowed = TRUE; /* XXX check this */ - clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ - - if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || - (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) { - /* If we're outputting to an LFP, use the LFP mode validation that will - * rely on the scaler so that we can display any mode smaller than or the - * same size as the panel. - */ - if (!has_lvds) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unable to locate panel information in BIOS VBT tables\n"); - PreInitCleanup(pScrn); - return FALSE; - } - n = i830ValidateFPModes(pScrn, pScrn->display->modes); - } else { - I830xf86ValidateDDCModes(pScrn, pScrn->display->modes); - /* XXX minPitch, minHeight are random numbers. */ - n = xf86ValidateModes(pScrn, - pScrn->monitor->Modes, /* availModes */ - pScrn->display->modes, /* modeNames */ - clockRanges, /* clockRanges */ - NULL, /* linePitches */ - 320, /* minPitch */ - MAX_DISPLAY_PITCH, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 200, /* minHeight */ - MAX_DISPLAY_HEIGHT, /* maxHeight */ - pScrn->display->virtualX, /* virtualX */ - pScrn->display->virtualY, /* virtualY */ - pI830->FbMapSize, /* apertureSize */ - LOOKUP_BEST_REFRESH /* strategy */); - } + n = I830ValidateXF86ModeList(pScrn); if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); diff --git a/src/i830_gtf.c b/src/i830_gtf.c new file mode 100644 index 00000000..2eff46a9 --- /dev/null +++ b/src/i830_gtf.c @@ -0,0 +1,356 @@ +#define DEBUG_VERB 2 +/* + * Copyright © 2002 David Dawes + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the author(s) shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from + * the author(s). + * + * Authors: David Dawes + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $ + */ +/* + * Modified by Alan Hourihane + * to support extended BIOS modes for the Intel chipsets + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xf86.h" +#include "vbe.h" +#include "vbeModes.h" +#include "i830.h" + +#include + +#define rint(x) floor(x) + +#define MARGIN_PERCENT 1.8 /* % of active vertical image */ +#define CELL_GRAN 8.0 /* assumed character cell granularity */ +#define MIN_PORCH 1 /* minimum front porch */ +#define V_SYNC_RQD 3 /* width of vsync in lines */ +#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */ +#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */ +#define M 600.0 /* blanking formula gradient */ +#define C 40.0 /* blanking formula offset */ +#define K 128.0 /* blanking formula scaling factor */ +#define J 20.0 /* blanking formula scaling factor */ + +/* C' and M' are part of the Blanking Duty Cycle computation */ + +#define C_PRIME (((C - J) * K/256.0) + J) +#define M_PRIME (K/256.0 * M) + +extern const int i830refreshes[]; + +DisplayModePtr +i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins) +{ + float h_pixels_rnd; + float v_lines_rnd; + float v_field_rate_rqd; + float top_margin; + float bottom_margin; + float interlace; + float h_period_est; + float vsync_plus_bp; + float v_back_porch; + float total_v_lines; + float v_field_rate_est; + float h_period; + float v_field_rate; + float v_frame_rate; + float left_margin; + float right_margin; + float total_active_pixels; + float ideal_duty_cycle; + float h_blank; + float total_pixels; + float pixel_freq; + float h_freq; + + float h_sync; + float h_front_porch; + float v_odd_front_porch_lines; + char modename[20]; + DisplayModePtr m; + + m = xnfcalloc(sizeof(DisplayModeRec), 1); + + + /* 1. In order to give correct results, the number of horizontal + * pixels requested is first processed to ensure that it is divisible + * by the character size, by rounding it to the nearest character + * cell boundary: + * + * [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND]) + */ + + h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN; + + + /* 2. If interlace is requested, the number of vertical lines assumed + * by the calculation must be halved, as the computation calculates + * the number of vertical lines per field. In either case, the + * number of lines is rounded to the nearest integer. + * + * [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0), + * ROUND([V LINES],0)) + */ + + v_lines_rnd = interlaced ? + rint((float) v_lines) / 2.0 : + rint((float) v_lines); + + /* 3. Find the frame rate required: + * + * [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2, + * [I/P FREQ RQD]) + */ + + v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq); + + /* 4. Find number of lines in Top margin: + * + * [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y", + * ROUND(([MARGIN%]/100*[V LINES RND]),0), + * 0) + */ + + top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0); + + /* 5. Find number of lines in Bottom margin: + * + * [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y", + * ROUND(([MARGIN%]/100*[V LINES RND]),0), + * 0) + */ + + bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0); + + /* 6. If interlace is required, then set variable [INTERLACE]=0.5: + * + * [INTERLACE]=(IF([INT RQD?]="y",0.5,0)) + */ + + interlace = interlaced ? 0.5 : 0.0; + + /* 7. Estimate the Horizontal period + * + * [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) / + * ([V LINES RND] + (2*[TOP MARGIN (LINES)]) + + * [MIN PORCH RND]+[INTERLACE]) * 1000000 + */ + + h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0)) + / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace) + * 1000000.0); + + /* 8. Find the number of lines in V sync + back porch: + * + * [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0) + */ + + vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est); + + /* 9. Find the number of lines in V back porch alone: + * + * [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND] + * + * XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]? + */ + + v_back_porch = vsync_plus_bp - V_SYNC_RQD; + + /* 10. Find the total number of lines in Vertical field period: + * + * [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] + + * [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] + + * [MIN PORCH RND] + */ + + total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + + interlace + MIN_PORCH; + + /* 11. Estimate the Vertical field frequency: + * + * [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000 + */ + + v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0; + + /* 12. Find the actual horizontal period: + * + * [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST]) + */ + + h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est); + + /* 13. Find the actual Vertical field frequency: + * + * [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000 + */ + + v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0; + + /* 14. Find the Vertical frame frequency: + * + * [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE])) + */ + + v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate; + + /* 15. Find number of pixels in left margin: + * + * [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", + * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / + * [CELL GRAN RND]),0)) * [CELL GRAN RND], + * 0)) + */ + + left_margin = margins ? + rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : + 0.0; + + /* 16. Find number of pixels in right margin: + * + * [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", + * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / + * [CELL GRAN RND]),0)) * [CELL GRAN RND], + * 0)) + */ + + right_margin = margins ? + rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : + 0.0; + + /* 17. Find total number of active pixels in image and left and right + * margins: + * + * [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] + + * [RIGHT MARGIN (PIXELS)] + */ + + total_active_pixels = h_pixels_rnd + left_margin + right_margin; + + /* 18. Find the ideal blanking duty cycle from the blanking duty cycle + * equation: + * + * [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000) + */ + + ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0); + + /* 19. Find the number of pixels in the blanking time to the nearest + * double character cell: + * + * [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] * + * [IDEAL DUTY CYCLE] / + * (100-[IDEAL DUTY CYCLE]) / + * (2*[CELL GRAN RND])), 0)) + * * (2*[CELL GRAN RND]) + */ + + h_blank = rint(total_active_pixels * + ideal_duty_cycle / + (100.0 - ideal_duty_cycle) / + (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN); + + /* 20. Find total number of pixels: + * + * [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)] + */ + + total_pixels = total_active_pixels + h_blank; + + /* 21. Find pixel clock frequency: + * + * [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD] + */ + + pixel_freq = total_pixels / h_period; + + /* 22. Find horizontal frequency: + * + * [H FREQ] = 1000 / [H PERIOD] + */ + + h_freq = 1000.0 / h_period; + + + /* Stage 1 computations are now complete; I should really pass + the results to another function and do the Stage 2 + computations, but I only need a few more values so I'll just + append the computations here for now */ + + + + /* 17. Find the number of pixels in the horizontal sync period: + * + * [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] / + * [CELL GRAN RND]),0))*[CELL GRAN RND] + */ + + h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN; + + /* 18. Find the number of pixels in the horizontal front porch period: + * + * [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)] + */ + + h_front_porch = (h_blank / 2.0) - h_sync; + + /* 36. Find the number of lines in the odd front porch period: + * + * [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE]) + */ + + v_odd_front_porch_lines = MIN_PORCH + interlace; + + /* finally, pack the results in the DisplayMode struct */ + + m->HDisplay = (int) (h_pixels_rnd); + m->HSyncStart = (int) (h_pixels_rnd + h_front_porch); + m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync); + m->HTotal = (int) (total_pixels); + + m->VDisplay = (int) (v_lines_rnd); + m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines); + m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD); + m->VTotal = (int) (total_v_lines); + + m->Clock = (int)(pixel_freq * 1000); + m->SynthClock = m->Clock; + m->HSync = h_freq; + m->VRefresh = v_frame_rate /* freq */; + + snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay); + m->name = xnfstrdup(modename); + + return (m); +} diff --git a/src/i830_modes.c b/src/i830_modes.c index c0c258c2..6f878a5e 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -197,7 +197,7 @@ I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first, } } -DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn) +DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) { DisplayModePtr p; DisplayModePtr last = NULL; @@ -206,7 +206,9 @@ DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn) int count = 0; int j, tmp; char stmp[32]; - xf86MonPtr ddc = pScrn->monitor->DDC; + + if (ddc == NULL) + return NULL; /* Go thru detailed timing table first */ for (j = 0; j < 4; j++) { @@ -327,30 +329,17 @@ DisplayModePtr I830xf86DDCModes(ScrnInfoPtr pScrn) } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d mode(s) found.\n", count); + "Total of %d DDC mode(s) found.\n", count); return first; } -static void -i830SetModeToPanelParameters(ScrnInfoPtr pScrn, DisplayModePtr pMode) -{ - I830Ptr pI830 = I830PTR(pScrn); - - pMode->HTotal = pI830->panel_fixed_hactive; - pMode->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; - pMode->HSyncEnd = pMode->HSyncStart + pI830->panel_fixed_hsyncwidth; - pMode->VTotal = pI830->panel_fixed_vactive; - pMode->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; - pMode->VSyncEnd = pMode->VSyncStart + pI830->panel_fixed_vsyncwidth; - pMode->Clock = pI830->panel_fixed_clock; -} - /** * This function returns a default mode for flat panels using the timing * information provided by the BIOS. */ -static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) +static DisplayModePtr +i830FPNativeMode(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); DisplayModePtr new; @@ -366,7 +355,14 @@ static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) strcpy(new->name, stmp); new->HDisplay = pI830->PanelXRes; new->VDisplay = pI830->PanelYRes; - i830SetModeToPanelParameters(pScrn, new); + new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; + new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth; + new->HTotal = new->HSyncEnd + 1; + new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; + new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth; + new->VTotal = new->VSyncEnd + 1; + new->Clock = pI830->panel_fixed_clock; + new->type = M_T_USERDEF; pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes); @@ -380,10 +376,21 @@ static DisplayModePtr i830FPNativeMode(ScrnInfoPtr pScrn) return new; } -/* FP mode validation routine for using panel fitting. +/** + * FP automatic modelist creation routine for using panel fitting. + * + * Constructs modes for any resolution less than the panel size specified by the + * user, with the user flag set, plus standard VESA mode sizes without the user + * flag set (for randr). + * + * Modes will be faked to use GTF parameters, even though at the time of being + * programmed into the LVDS they'll end up being forced to the panel's fixed + * mode. + * + * \return doubly-linked list of modes. */ -int -i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +DisplayModePtr +i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) { I830Ptr pI830 = I830PTR(pScrn); DisplayModePtr last = NULL; @@ -419,14 +426,8 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) continue; } - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(ppModeName[i]) + 1); - strcpy(new->name, ppModeName[i]); - new->HDisplay = width; - new->VDisplay = height; - new->type |= M_T_USERDEF; - - i830SetModeToPanelParameters(pScrn, new); + new = i830GetGTF(width, height, 60.0, FALSE, FALSE); + new->type |= M_T_USERDEF; new->next = NULL; new->prev = last; @@ -437,21 +438,19 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) if (!first) first = new; - pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); - pScrn->display->virtualY = pScrn->virtualY = MAX(pScrn->virtualY, height); count++; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid mode using panel fitting: %s\n", new->name); } - /* If all else fails, add the native mode */ + /* If the user hasn't specified modes, add the native mode */ if (!count) { first = last = i830FPNativeMode(pScrn); if (first) count = 1; } - /* add in all default vesa modes smaller than panel size, used for randr*/ + /* add in all default vesa modes smaller than panel size, used for randr */ for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) { tmp = first; @@ -460,13 +459,11 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) tmp = tmp->next; } if (!tmp) { - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->HDisplay = p->HDisplay; - new->VDisplay = p->VDisplay; - i830SetModeToPanelParameters(pScrn, new); - new->type |= M_T_DEFAULT; + new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE); + if (ppModeName[i] == NULL) + new->type |= M_T_USERDEF; + else + new->type |= M_T_DEFAULT; new->next = NULL; new->prev = last; @@ -476,166 +473,202 @@ i830ValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) last = new; if (!first) first = new; + + count++; } } } - /* Close the doubly-linked mode list, if we found any usable modes */ - if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Total number of valid FP mode(s) found: %d\n", count); - /* Adjust the display pitch to fit the modes we've come up with. */ - pScrn->displayWidth = MAX(pScrn->displayWidth, pScrn->virtualX); - pScrn->displayWidth = (pScrn->displayWidth + 63) & ~63; - - return count; + return first; } -/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, - * so here is our own validation routine. +/** + * Allocates and returns a copy of pMode, including pointers within pMode. */ -int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName) +static DisplayModePtr +I830DuplicateMode(DisplayModePtr pMode) { - DisplayModePtr p; - DisplayModePtr last = NULL; - DisplayModePtr first = NULL; - DisplayModePtr ddcModes = NULL; - int count = 0; - int i, width, height; - ScrnInfoPtr pScrn = pScrn1; + DisplayModePtr pNew; - pScrn->virtualX = pScrn1->display->virtualX; - pScrn->virtualY = pScrn1->display->virtualY; + pNew = xnfalloc(sizeof(DisplayModeRec)); + *pNew = *pMode; + pNew->next = NULL; + pNew->prev = NULL; + pNew->name = xnfstrdup(pMode->name); - if (pScrn->monitor->DDC) { - int maxVirtX = pScrn->virtualX; - int maxVirtY = pScrn->virtualY; + return pNew; +} - /* Collect all of the DDC modes */ - first = last = ddcModes = I830xf86DDCModes(pScrn); +/** + * Injects a list of probed modes into another mode list. + * + * Take the doubly-linked list of modes we've probed for the device, and injects + * it into the doubly-linked modeList. We don't need to filter, because the + * eventual call to xf86ValidateModes will do this for us. I think. + */ +int +I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, + char **ppModeName, DisplayModePtr addModes) +{ + DisplayModePtr last = modeList; + DisplayModePtr first = modeList; + DisplayModePtr addMode; + int count = 0; - for (p = ddcModes; p; p = p->next) { + for (addMode = addModes; addMode != NULL; addMode = addMode->next) { + DisplayModePtr pNew; - maxVirtX = MAX(maxVirtX, p->HDisplay); - maxVirtY = MAX(maxVirtY, p->VDisplay); - count++; + /* XXX: Do we need to check if modeList already contains the same mode? + */ - last = p; + pNew = I830DuplicateMode(addMode); + /* If the user didn't specify any modes, mark all modes as M_T_USERDEF + * so that we can cycle through them, etc. XXX: really need to? + */ + if (ppModeName[0] == NULL) { + pNew->type |= M_T_USERDEF; } - /* Match up modes that are specified in the XF86Config file */ - if (ppModeName[0]) { - DisplayModePtr next; - - /* Reset the max virtual dimensions */ - maxVirtX = pScrn->virtualX; - maxVirtY = pScrn->virtualY; - - /* Reset list */ - first = last = NULL; - - for (i = 0; ppModeName[i]; i++) { - /* FIXME: Use HDisplay and VDisplay instead of mode string */ - if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) { - for (p = ddcModes; p; p = next) { - next = p->next; - - if (p->HDisplay == width && p->VDisplay == height) { - /* We found a DDC mode that matches the one - requested in the XF86Config file */ - p->type |= M_T_USERDEF; - - /* Update the max virtual setttings */ - maxVirtX = MAX(maxVirtX, width); - maxVirtY = MAX(maxVirtY, height); - - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - - break; - } - } - } - } - - /* - * Add remaining DDC modes if they're smaller than the user - * specified modes - */ - for (p = ddcModes; p; p = next) { - next = p->next; - if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) { - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - } - } - - /* Delete unused modes */ - while (ddcModes) - xf86DeleteMode(&ddcModes, ddcModes); + /* Insert pNew into modeList */ + if (last) { + last->next = pNew; + pNew->prev = last; } else { - /* - * No modes were configured, so we make the DDC modes - * available for the user to cycle through. - */ - for (p = ddcModes; p; p = p->next) - p->type |= M_T_USERDEF; + first = pNew; + pNew->prev = NULL; } + pNew->next = NULL; + last = pNew; - pScrn->virtualX = pScrn->display->virtualX = maxVirtX; - pScrn->virtualY = pScrn->display->virtualY = maxVirtY; - } - - /* Close the doubly-linked mode list, if we found any usable modes */ - if (last) { - DisplayModePtr temp = NULL; - /* we should add these to pScrn monitor modes */ - last->next = pScrn->monitor->Modes; - temp = pScrn->monitor->Modes->prev; - pScrn->monitor->Modes->prev = first; - pScrn->monitor->Modes->prev = last; - - first->prev = temp; - if (temp) - temp->next = first; - - pScrn->monitor->Modes = first; + count++; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total number of valid DDC mode(s) found: %d\n", count); + "Injected %d modes detected from the monitor\n", count); return count; } + +/** + * Performs probing of modes available on the output connected to the given + * pipe. + * + * We do not support multiple outputs per pipe (since the cases for that are + * sufficiently rare we can't imagine the complexity being worth it), so + * the pipe is a sufficient specifier. + */ +static void +I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + int output_index = -1; + int i; + int outputs; + + while (pI830->pipeModes[pipe] != NULL) + xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]); + + if (pipe == 0) + outputs = pI830->operatingDevices & 0xff; + else + outputs = (pI830->operatingDevices >> 8) & 0xff; + + for (i = 0; i < MAX_OUTPUTS; i++) { + switch (pI830->output[i].type) { + case I830_OUTPUT_ANALOG: + if (outputs & PIPE_CRT) { + output_index = i; + } + break; + case I830_OUTPUT_LVDS: + if (outputs & PIPE_LFP) { + output_index = i; + } + break; + case I830_OUTPUT_SDVO: + if (outputs & PIPE_DFP) { + output_index = i; + } + break; + } + } + /* XXX: If there's no output associated with the pipe, bail for now. */ + if (output_index == -1) + return; + + if (outputs & PIPE_LFP) { + pI830->pipeMon[pipe] = NULL; /* XXX */ + pI830->pipeModes[pipe] = i830GetLVDSModes(pScrn, + pScrn->display->modes); + } else if (pI830->output[output_index].pDDCBus != NULL) { + /* XXX: Free the mon */ + pI830->pipeMon[pipe] = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->output[output_index].pDDCBus); + pI830->pipeModes[pipe] = I830GetDDCModes(pScrn, + pI830->pipeMon[pipe]); + } else { + ErrorF("don't know how to get modes for this device.\n"); + } +} + +/** + * Probes for video modes on attached otuputs, and assembles a list to insert + * into pScrn. + */ +int +I830ValidateXF86ModeList(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + ClockRangePtr clockRanges; + int n, pipe; + + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + I830ReprobePipeModeList(pScrn, pipe); + } + + /* XXX: Clean out modes previously injected by our driver */ + + if (pI830->pipeModes[0] != NULL) { + I830InjectProbedModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, pI830->pipeModes[0]); + } + if (pI830->pipeModes[1] != NULL) { + I830InjectProbedModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, pI830->pipeModes[1]); + } + + /* + * Set up the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 25000; + clockRanges->maxClock = pI830->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = TRUE; /* XXX check this */ + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + + /* Take the pScrn->monitor->Modes we've accumulated and validate them into + * pScrn->modes. + */ + n = xf86ValidateModes(pScrn, + pScrn->monitor->Modes, /* availModes */ + pScrn->display->modes, /* modeNames */ + clockRanges, /* clockRanges */ + NULL, /* linePitches */ + 320, /* minPitch */ + MAX_DISPLAY_PITCH, /* maxPitch */ + 64 * pScrn->bitsPerPixel, /* pitchInc */ + 200, /* minHeight */ + MAX_DISPLAY_HEIGHT, /* maxHeight */ + pScrn->display->virtualX, /* virtualX */ + pScrn->display->virtualY, /* virtualY */ + pI830->FbMapSize, /* apertureSize */ + LOOKUP_BEST_REFRESH /* strategy */); + + return n; +} From f5e5f8aeddb3e0d6d073471aeff6176fb54576e2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 23 Jun 2006 23:29:55 -0700 Subject: [PATCH 106/257] WIP to allow re-probing and validation of modes for new heads at "xrandr" time. Now, DDC modes always end up being preferred to custom modelines, even if smaller. This should probably be fixed by inserting custom modelines into the probed mode list if they're valid according to the probed parameters of the monitor. Too much code is lifted from static functions in xf86Mode.c, and those should be made unstatic if possible. Using xf86ValidateModes is also rather hacky, and I want to break the function down, but this is a first step. --- src/i830.h | 2 +- src/i830_display.c | 38 +++++++ src/i830_driver.c | 6 +- src/i830_modes.c | 264 ++++++++++++++++++++++++++++++++++++++++++++- src/i830_randr.c | 3 + 5 files changed, 303 insertions(+), 10 deletions(-) diff --git a/src/i830.h b/src/i830.h index 59f563fc..c4a4771e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -595,7 +595,7 @@ extern Bool I830RandRInit(ScreenPtr pScreen, int rotation); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); /* i830_modes.c */ -int I830ValidateXF86ModeList(ScrnInfoPtr pScrn); +int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); /* i830_gtf.c */ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, diff --git a/src/i830_display.c b/src/i830_display.c index 8843f989..50f49402 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -262,6 +262,44 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int refclk, pixel_clock, sdvo_pixel_multiply; int outputs; + assert(pMode->VRefresh != 0.0); + /* If we've got a list of modes probed for the device, find the best match + * in there to the requested mode. + */ + if (pI830->pipeModes[pipe] != NULL) { + DisplayModePtr pBest = NULL, pScan; + + assert(pScan->VRefresh != 0.0); + for (pScan = pI830->pipeModes[pipe]; pScan != NULL; pScan = pScan->next) + { + /* Reject if it's larger than the desired mode. */ + if (pScan->HDisplay > pMode->HDisplay || + pScan->VDisplay > pMode->VDisplay) + { + continue; + } + if (pBest == NULL) { + pBest = pScan; + continue; + } + /* Find if it's closer than the current best option */ + if (abs(pScan->VRefresh - pMode->VRefresh) > + abs(pBest->VRefresh - pMode->VRefresh)) + { + continue; + } + } + if (pBest != NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Choosing pipe's mode %p (%dx%dx%.1f) instead of xf86 " + "mode %p (%dx%dx%.1f)\n", pBest, + pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, + pMode, + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + pMode = pBest; + } + } + ErrorF("Requested pix clock: %d\n", pMode->Clock); if (pipe == 0) diff --git a/src/i830_driver.c b/src/i830_driver.c index 75f9e4b7..32beb8a5 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2217,23 +2217,19 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MaxClock = 300000; - n = I830ValidateXF86ModeList(pScrn); + n = I830ValidateXF86ModeList(pScrn, TRUE); if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); return FALSE; } - xf86PruneDriverModes(pScrn); - if (pScrn->modes == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); PreInitCleanup(pScrn); return FALSE; } - xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); - /* * Fix up modes to make hblank start at hsync start. * I don't know why the xf86 code mangles this... diff --git a/src/i830_modes.c b/src/i830_modes.c index 6f878a5e..faa843e3 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -1,6 +1,7 @@ #define DEBUG_VERB 2 /* * Copyright © 2002 David Dawes + * Copyright © 2006 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,6 +27,7 @@ * the author(s). * * Authors: David Dawes + * Eric Anholt * * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $ */ @@ -197,6 +199,30 @@ I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first, } } +/** + * Calculates the vertical refresh of a mode. + * + * Taken directly from xf86Mode.c, and should be put back there --Eric Anholt + */ +static double +I830ModeVRefresh(DisplayModePtr mode) +{ + double refresh = 0.0; + + if (mode->VRefresh > 0.0) + refresh = mode->VRefresh; + else if (mode->HTotal > 0 && mode->VTotal > 0) { + refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; + if (mode->Flags & V_INTERLACE) + refresh *= 2.0; + if (mode->Flags & V_DBLSCAN) + refresh /= 2.0; + if (mode->VScan > 1) + refresh /= (float)(mode->VScan); + } + return refresh; +} + DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) { DisplayModePtr p; @@ -552,6 +578,97 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, return count; } +/* + * I830xf86SetModeCrtc + * + * Initialises the Crtc parameters for a mode. The initialisation includes + * adjustments for interlaced and double scan modes. + * + * Taken directly from xf86Mode.c:xf86SetModeCrtc -- Eric Anholt + * (and it should be put back there!) + */ +static void +I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) +{ + if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)) + return; + + p->CrtcHDisplay = p->HDisplay; + p->CrtcHSyncStart = p->HSyncStart; + p->CrtcHSyncEnd = p->HSyncEnd; + p->CrtcHTotal = p->HTotal; + p->CrtcHSkew = p->HSkew; + p->CrtcVDisplay = p->VDisplay; + p->CrtcVSyncStart = p->VSyncStart; + p->CrtcVSyncEnd = p->VSyncEnd; + p->CrtcVTotal = p->VTotal; + if (p->Flags & V_INTERLACE) { + if (adjustFlags & INTERLACE_HALVE_V) { + p->CrtcVDisplay /= 2; + p->CrtcVSyncStart /= 2; + p->CrtcVSyncEnd /= 2; + p->CrtcVTotal /= 2; + } + /* Force interlaced modes to have an odd VTotal */ + /* maybe we should only do this when INTERLACE_HALVE_V is set? */ + p->CrtcVTotal |= 1; + } + + if (p->Flags & V_DBLSCAN) { + p->CrtcVDisplay *= 2; + p->CrtcVSyncStart *= 2; + p->CrtcVSyncEnd *= 2; + p->CrtcVTotal *= 2; + } + if (p->VScan > 1) { + p->CrtcVDisplay *= p->VScan; + p->CrtcVSyncStart *= p->VScan; + p->CrtcVSyncEnd *= p->VScan; + p->CrtcVTotal *= p->VScan; + } + p->CrtcHAdjusted = FALSE; + p->CrtcVAdjusted = FALSE; + + /* + * XXX + * + * The following is taken from VGA, but applies to other cores as well. + */ + p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); + p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); + if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) { + /* + * V Blanking size must be < 127. + * Moving blank start forward is safer than moving blank end + * back, since monitors clamp just AFTER the sync pulse (or in + * the sync pulse), but never before. + */ + p->CrtcVBlankStart = p->CrtcVBlankEnd - 127; + /* + * If VBlankStart is now > VSyncStart move VBlankStart + * to VSyncStart using the maximum width that fits into + * VTotal. + */ + if (p->CrtcVBlankStart > p->CrtcVSyncStart) { + p->CrtcVBlankStart = p->CrtcVSyncStart; + p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal); + } + } + p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); + p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); + + if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) { + /* + * H Blanking size must be < 63*8. Same remark as above. + */ + p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8; + if (p->CrtcHBlankStart > p->CrtcHSyncStart) { + p->CrtcHBlankStart = p->CrtcHSyncStart; + p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal); + } + } +} + /** * Performs probing of modes available on the output connected to the given * pipe. @@ -567,6 +684,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) int output_index = -1; int i; int outputs; + DisplayModePtr pMode; while (pI830->pipeModes[pipe] != NULL) xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]); @@ -609,26 +727,108 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) pI830->output[output_index].pDDCBus); pI830->pipeModes[pipe] = I830GetDDCModes(pScrn, pI830->pipeMon[pipe]); + + for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) + { + I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); + pMode->VRefresh = I830ModeVRefresh(pMode); + } } else { ErrorF("don't know how to get modes for this device.\n"); } + + /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe + * code later on. + */ + for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) { + pMode->VRefresh = I830ModeVRefresh(pMode); + } } +/** + * This function removes a mode from a list of modes. It should probably be + * moved to xf86Mode.c + * + * There are different types of mode lists: + * + * - singly linked linear lists, ending in NULL + * - doubly linked linear lists, starting and ending in NULL + * - doubly linked circular lists + * + */ + +static void +I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode) +{ + /* Catch the easy/insane cases */ + if (modeList == NULL || *modeList == NULL || mode == NULL) + return; + + /* If the mode is at the start of the list, move the start of the list */ + if (*modeList == mode) + *modeList = mode->next; + + /* If mode is the only one on the list, set the list to NULL */ + if ((mode == mode->prev) && (mode == mode->next)) { + *modeList = NULL; + } else { + if ((mode->prev != NULL) && (mode->prev->next == mode)) + mode->prev->next = mode->next; + if ((mode->next != NULL) && (mode->next->prev == mode)) + mode->next->prev = mode->prev; + } +} + /** * Probes for video modes on attached otuputs, and assembles a list to insert * into pScrn. + * + * \param first_time indicates that the memory layout has already been set up, + * so displayWidth, virtualX, and virtualY shouldn't be touched. + * + * A SetMode must follow this call in order for operatingDevices to match the + * hardware's state, in case we detect a new output device. */ int -I830ValidateXF86ModeList(ScrnInfoPtr pScrn) +I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) { I830Ptr pI830 = I830PTR(pScrn); ClockRangePtr clockRanges; int n, pipe; + DisplayModePtr saved_mode; + int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0; for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { I830ReprobePipeModeList(pScrn, pipe); } + /* If we've got a spare pipe, try to detect if a new CRT has been plugged + * in. + */ + if ((pI830->operatingDevices & (PIPE_CRT | (PIPE_CRT << 8))) == 0) { + if ((pI830->operatingDevices & 0xff) == PIPE_NONE) { + pI830->operatingDevices |= PIPE_CRT; + I830ReprobePipeModeList(pScrn, 0); + if (pI830->pipeModes[0] == NULL) { + /* No new output found. */ + pI830->operatingDevices &= ~PIPE_CRT; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Enabled new CRT on pipe A\n"); + } + } else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) { + pI830->operatingDevices |= PIPE_CRT << 8; + I830ReprobePipeModeList(pScrn, 1); + if (pI830->pipeModes[1] == NULL) { + /* No new output found. */ + pI830->operatingDevices &= ~(PIPE_CRT << 8); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Enabled new CRT on pipe B\n"); + } + } + } + /* XXX: Clean out modes previously injected by our driver */ if (pI830->pipeModes[0] != NULL) { @@ -652,23 +852,79 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn) clockRanges->interlaceAllowed = TRUE; /* XXX check this */ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + /* Remove the current mode from the modelist if we're re-validating, so we + * can find a new mode to map ourselves to afterwards. + */ + saved_mode = pI830->currentMode; + if (saved_mode != NULL) { + I830xf86DeleteModeFromList(&pScrn->modes, saved_mode); + } + + if (!first_time) { + saved_virtualX = pScrn->virtualX; + saved_virtualY = pScrn->virtualY; + saved_displayWidth = pScrn->displayWidth; + } + /* Take the pScrn->monitor->Modes we've accumulated and validate them into * pScrn->modes. + * XXX: Should set up a scrp->monitor->DDC covering the union of the + * capabilities of our pipes. */ n = xf86ValidateModes(pScrn, pScrn->monitor->Modes, /* availModes */ pScrn->display->modes, /* modeNames */ clockRanges, /* clockRanges */ - NULL, /* linePitches */ + !first_time ? &pScrn->displayWidth : NULL, /* linePitches */ 320, /* minPitch */ MAX_DISPLAY_PITCH, /* maxPitch */ 64 * pScrn->bitsPerPixel, /* pitchInc */ 200, /* minHeight */ MAX_DISPLAY_HEIGHT, /* maxHeight */ - pScrn->display->virtualX, /* virtualX */ - pScrn->display->virtualY, /* virtualY */ + pScrn->virtualX, /* virtualX */ + pScrn->virtualY, /* virtualY */ pI830->FbMapSize, /* apertureSize */ LOOKUP_BEST_REFRESH /* strategy */); + if (!first_time) { + /* Restore things that may have been damaged by xf86ValidateModes. */ + pScrn->virtualX = saved_virtualX; + pScrn->virtualY = saved_virtualY; + pScrn->displayWidth = saved_displayWidth; + } + + /* Need to do xf86CrtcForModes so any user-configured modes are valid for + * non-LVDS. + */ + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + xf86PruneDriverModes(pScrn); + + /* Try to find the closest equivalent of the previous mode pointer to switch + * to. + */ + if (saved_mode != NULL) { + DisplayModePtr pBestMode = NULL, pMode; + + /* XXX: Is finding a matching x/y res enough? probably not. */ + for (pMode = pScrn->modes; ; pMode = pMode->next) { + if (pMode->HDisplay == saved_mode->HDisplay && + pMode->VDisplay == saved_mode->VDisplay) + { + ErrorF("found matching mode %p\n", pMode); + pBestMode = pMode; + } + if (pMode->next == pScrn->modes) + break; + } + + if (pBestMode != NULL) + xf86SwitchMode(pScrn->pScreen, pBestMode); + else + FatalError("No suitable modes after re-probe\n"); + + xfree(saved_mode->name); + xfree(saved_mode); + } return n; } diff --git a/src/i830_randr.c b/src/i830_randr.c index 0311f2b6..93c05198 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -79,6 +79,9 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) randrp->virtualY = scrp->virtualY; } + /* Re-probe the outputs for new monitors or modes */ + I830ValidateXF86ModeList(scrp, FALSE); + for (mode = scrp->modes; ; mode = mode->next) { int refresh = I830RandRModeRefresh (mode); From 52e8231a19f28bd4744f983aee2197a18c20aa3a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 07:46:28 +0200 Subject: [PATCH 107/257] Major cleanup of mode reprobing: - Don't mess with pScrn->monitor->Modes, and instead make our own availModes. - Don't re-program the pipe with the same values (no flicker at xrandr) - Move a bunch of stuff that should be exposed through the public API (probably) to i830_xf86Modes.c - Use a table with established modes plus GTF to come up with modes from EDID, instead of trying to walk and find one in pScrn->monitor->Modes. I think this is correct. - Reset clone state if we've detected new pipes, which should turn on the cursor. --- src/Makefile.am | 5 +- src/i830.h | 1 + src/i830_display.c | 5 + src/i830_modes.c | 289 ++++++++++++++++------------------- src/i830_sdvo.h | 3 + src/i830_xf86Modes.c | 348 +++++++++++++++++++++++++++++++++++++++++++ src/i830_xf86Modes.h | 40 +++++ 7 files changed, 527 insertions(+), 164 deletions(-) create mode 100644 src/i830_xf86Modes.c create mode 100644 src/i830_xf86Modes.h diff --git a/src/Makefile.am b/src/Makefile.am index 8970db1e..f8aaad1d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,8 +63,9 @@ i810_drv_la_SOURCES = \ i830_video.c \ i830_rotate.c \ i830_randr.c \ - i830_sdvo.c - + i830_sdvo.c \ + i830_xf86Modes.h \ + i830_xf86Modes.c if DRI i810_drv_la_SOURCES += \ i810_dri.c \ diff --git a/src/i830.h b/src/i830.h index c4a4771e..b3a0895c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -403,6 +403,7 @@ typedef struct _I830Rec { int planeEnabled[MAX_DISPLAY_PIPES]; xf86MonPtr pipeMon[MAX_DISPLAY_PIPES]; DisplayModePtr pipeModes[MAX_DISPLAY_PIPES]; + DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ Bool preinit; diff --git a/src/i830_display.c b/src/i830_display.c index 50f49402..1546c377 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -35,6 +35,7 @@ #include "i830_bios.h" #include "i830_display.h" #include "i830_debug.h" +#include "i830_xf86Modes.h" /** Returns the pixel clock for the given refclk and divisors. */ static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2) @@ -299,6 +300,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pMode = pBest; } } + if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) + return TRUE; ErrorF("Requested pix clock: %d\n", pMode->Clock); @@ -629,6 +632,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(SDVOC, sdvoc); } + pI830->pipeCurMode[pipe] = *pMode; + return TRUE; } diff --git a/src/i830_modes.c b/src/i830_modes.c index faa843e3..e1e5fd53 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -42,9 +42,11 @@ #include #include +#include #include "xf86.h" #include "i830.h" +#include "i830_xf86Modes.h" #include @@ -92,6 +94,8 @@ static struct {720, 400, 70}, }; +#define DEBUG_REPROBE 1 + extern const int i830refreshes[]; void @@ -157,6 +161,23 @@ I830PrintModes(ScrnInfoPtr scrp) } while (p != NULL && p != scrp->modes); } +/** + * Allocates and returns a copy of pMode, including pointers within pMode. + */ +static DisplayModePtr +I830DuplicateMode(DisplayModePtr pMode) +{ + DisplayModePtr pNew; + + pNew = xnfalloc(sizeof(DisplayModeRec)); + *pNew = *pMode; + pNew->next = NULL; + pNew->prev = NULL; + pNew->name = xnfstrdup(pMode->name); + + return pNew; +} + /* This function will sort all modes according to their resolution. * Highest resolution first. */ @@ -200,32 +221,31 @@ I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first, } /** - * Calculates the vertical refresh of a mode. + * Gets a new pointer to a VESA established mode. * - * Taken directly from xf86Mode.c, and should be put back there --Eric Anholt + * \param i index into the VESA established modes table. */ -static double -I830ModeVRefresh(DisplayModePtr mode) +static DisplayModePtr +I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) { - double refresh = 0.0; + DisplayModePtr pMode; - if (mode->VRefresh > 0.0) - refresh = mode->VRefresh; - else if (mode->HTotal > 0 && mode->VTotal > 0) { - refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; - if (mode->Flags & V_INTERLACE) - refresh *= 2.0; - if (mode->Flags & V_DBLSCAN) - refresh /= 2.0; - if (mode->VScan > 1) - refresh /= (float)(mode->VScan); + for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode = pMode->next) + { + if (pMode->HDisplay == est_timings[i].hsize && + pMode->VDisplay == est_timings[i].vsize && + fabs(I830ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0) + { + DisplayModePtr pNew = I830DuplicateMode(pMode); + pNew->VRefresh = I830ModeVRefresh(pMode); + return pNew; + } } - return refresh; + return NULL; } DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) { - DisplayModePtr p; DisplayModePtr last = NULL; DisplayModePtr new = NULL; DisplayModePtr first = NULL; @@ -289,7 +309,16 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) for (j = 0; j < 8; j++) { if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0) continue; +#if 1 + new = i830GetGTF(ddc->timings2[j].hsize, ddc->timings2[j].vsize, + ddc->timings2[j].refresh, FALSE, FALSE); + new->status = MODE_OK; + new->type |= M_T_DEFAULT; + + I830xf86SortModes(&new, &first, &last); +#else for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { + /* Ignore all double scan modes */ if ((ddc->timings2[j].hsize == p->HDisplay) && (ddc->timings2[j].vsize == p->VDisplay)) { @@ -318,39 +347,27 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) } } } +#endif } /* Search thru established modes from EDID */ tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2; for (j = 0; j < 16; j++) { if (tmp & (1 << j)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((est_timings[j].hsize == p->HDisplay) && - (est_timings[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - float err = (float)est_timings[j].refresh - refresh; + DisplayModePtr pNew; - if (err < 1.0) { - /* Is this good enough? */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memcpy(new, p, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->status = MODE_OK; - new->type = M_T_DEFAULT; + pNew = I830GetVESAEstablishedMode(pScrn, j); + assert(pNew != NULL); /* We'd better have all the est. modes. */ - count++; + new->status = MODE_OK; + new->type = M_T_DEFAULT; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from established timing " - "table: %s\n", new->name); + count++; - I830xf86SortModes(&new, &first, &last); - break; - } - } - } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established " + "timing table: %s\n", new->name); + + I830xf86SortModes(&new, &first, &last); } } @@ -511,23 +528,6 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) return first; } -/** - * Allocates and returns a copy of pMode, including pointers within pMode. - */ -static DisplayModePtr -I830DuplicateMode(DisplayModePtr pMode) -{ - DisplayModePtr pNew; - - pNew = xnfalloc(sizeof(DisplayModeRec)); - *pNew = *pMode; - pNew->next = NULL; - pNew->prev = NULL; - pNew->name = xnfstrdup(pMode->name); - - return pNew; -} - /** * Injects a list of probed modes into another mode list. * @@ -536,11 +536,11 @@ I830DuplicateMode(DisplayModePtr pMode) * eventual call to xf86ValidateModes will do this for us. I think. */ int -I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, - char **ppModeName, DisplayModePtr addModes) +I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + DisplayModePtr addModes) { - DisplayModePtr last = modeList; - DisplayModePtr first = modeList; + DisplayModePtr last = *modeList; + DisplayModePtr first = *modeList; DisplayModePtr addMode; int count = 0; @@ -551,12 +551,14 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, */ pNew = I830DuplicateMode(addMode); +#if 0 /* If the user didn't specify any modes, mark all modes as M_T_USERDEF * so that we can cycle through them, etc. XXX: really need to? */ - if (ppModeName[0] == NULL) { + if (pScrn->display->modes[0] == NULL) { pNew->type |= M_T_USERDEF; } +#endif /* Insert pNew into modeList */ if (last) { @@ -571,6 +573,7 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, count++; } + *modeList = first; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Injected %d modes detected from the monitor\n", count); @@ -578,97 +581,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr modeList, return count; } -/* - * I830xf86SetModeCrtc - * - * Initialises the Crtc parameters for a mode. The initialisation includes - * adjustments for interlaced and double scan modes. - * - * Taken directly from xf86Mode.c:xf86SetModeCrtc -- Eric Anholt - * (and it should be put back there!) - */ -static void -I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) -{ - if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)) - return; - - p->CrtcHDisplay = p->HDisplay; - p->CrtcHSyncStart = p->HSyncStart; - p->CrtcHSyncEnd = p->HSyncEnd; - p->CrtcHTotal = p->HTotal; - p->CrtcHSkew = p->HSkew; - p->CrtcVDisplay = p->VDisplay; - p->CrtcVSyncStart = p->VSyncStart; - p->CrtcVSyncEnd = p->VSyncEnd; - p->CrtcVTotal = p->VTotal; - if (p->Flags & V_INTERLACE) { - if (adjustFlags & INTERLACE_HALVE_V) { - p->CrtcVDisplay /= 2; - p->CrtcVSyncStart /= 2; - p->CrtcVSyncEnd /= 2; - p->CrtcVTotal /= 2; - } - /* Force interlaced modes to have an odd VTotal */ - /* maybe we should only do this when INTERLACE_HALVE_V is set? */ - p->CrtcVTotal |= 1; - } - - if (p->Flags & V_DBLSCAN) { - p->CrtcVDisplay *= 2; - p->CrtcVSyncStart *= 2; - p->CrtcVSyncEnd *= 2; - p->CrtcVTotal *= 2; - } - if (p->VScan > 1) { - p->CrtcVDisplay *= p->VScan; - p->CrtcVSyncStart *= p->VScan; - p->CrtcVSyncEnd *= p->VScan; - p->CrtcVTotal *= p->VScan; - } - p->CrtcHAdjusted = FALSE; - p->CrtcVAdjusted = FALSE; - - /* - * XXX - * - * The following is taken from VGA, but applies to other cores as well. - */ - p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); - p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); - if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) { - /* - * V Blanking size must be < 127. - * Moving blank start forward is safer than moving blank end - * back, since monitors clamp just AFTER the sync pulse (or in - * the sync pulse), but never before. - */ - p->CrtcVBlankStart = p->CrtcVBlankEnd - 127; - /* - * If VBlankStart is now > VSyncStart move VBlankStart - * to VSyncStart using the maximum width that fits into - * VTotal. - */ - if (p->CrtcVBlankStart > p->CrtcVSyncStart) { - p->CrtcVBlankStart = p->CrtcVSyncStart; - p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal); - } - } - p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); - p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); - - if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) { - /* - * H Blanking size must be < 63*8. Same remark as above. - */ - p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8; - if (p->CrtcHBlankStart > p->CrtcHSyncStart) { - p->CrtcHBlankStart = p->CrtcHSyncStart; - p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal); - } - } -} - /** * Performs probing of modes available on the output connected to the given * pipe. @@ -740,14 +652,21 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe * code later on. */ +#ifdef DEBUG_REPROBE + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n", + pipe); +#endif for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) { pMode->VRefresh = I830ModeVRefresh(pMode); +#ifdef DEBUG_REPROBE + PrintModeline(pScrn->scrnIndex, pMode); +#endif } } /** * This function removes a mode from a list of modes. It should probably be - * moved to xf86Mode.c + * moved to xf86Mode.c. * * There are different types of mode lists: * @@ -795,8 +714,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) I830Ptr pI830 = I830PTR(pScrn); ClockRangePtr clockRanges; int n, pipe; - DisplayModePtr saved_mode; + DisplayModePtr saved_mode, availModes; int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0; + Bool pipes_reconfigured = FALSE; for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { I830ReprobePipeModeList(pScrn, pipe); @@ -815,6 +735,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabled new CRT on pipe A\n"); + pipes_reconfigured = TRUE; + /* Clear the current mode, so we reprogram the pipe for sure. */ + memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0])); } } else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) { pI830->operatingDevices |= PIPE_CRT << 8; @@ -825,19 +748,24 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabled new CRT on pipe B\n"); + pipes_reconfigured = TRUE; + /* Clear the current mode, so we reprogram the pipe for sure. */ + memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1])); } } } - /* XXX: Clean out modes previously injected by our driver */ - + /* Start by injecting the XFree86 default modes and user-configured + * modelines. XXX: This actually isn't of use if we've got any DDC, as DDC + * currently has higher priority than the validated modelist. We need to + * deal with that. + */ + I830InjectProbedModes(pScrn, &availModes, pScrn->monitor->Modes); if (pI830->pipeModes[0] != NULL) { - I830InjectProbedModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, pI830->pipeModes[0]); + I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[0]); } if (pI830->pipeModes[1] != NULL) { - I830InjectProbedModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, pI830->pipeModes[1]); + I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]); } /* @@ -872,7 +800,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) * capabilities of our pipes. */ n = xf86ValidateModes(pScrn, - pScrn->monitor->Modes, /* availModes */ + availModes, /* availModes */ pScrn->display->modes, /* modeNames */ clockRanges, /* clockRanges */ !first_time ? &pScrn->displayWidth : NULL, /* linePitches */ @@ -886,6 +814,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) pI830->FbMapSize, /* apertureSize */ LOOKUP_BEST_REFRESH /* strategy */); + /* availModes is of no more use as xf86ValidateModes has duplicated and + * saved everything it needs. + */ + while (availModes != NULL) + xf86DeleteMode(&availModes, availModes); + if (!first_time) { /* Restore things that may have been damaged by xf86ValidateModes. */ pScrn->virtualX = saved_virtualX; @@ -900,6 +834,19 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) xf86PruneDriverModes(pScrn); +#if DEBUG_REPROBE + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n"); + do { + DisplayModePtr pMode; + + for (pMode = pScrn->modes; ; pMode = pMode->next) { + PrintModeline(pScrn->scrnIndex, pMode); + if (pMode->next == pScrn->modes) + break; + } + } while (0); +#endif + /* Try to find the closest equivalent of the previous mode pointer to switch * to. */ @@ -926,5 +873,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) xfree(saved_mode->name); xfree(saved_mode); } + + /* If we've enabled/disabled some pipes, we need to reset cloning mode + * support. + */ + if (pipes_reconfigured) { + if ((pI830->operatingDevices & 0x00ff) && + (pI830->operatingDevices & 0xff00)) + { + pI830->Clone = TRUE; + } else { + pI830->Clone = FALSE; + } + + /* If HW cursor currently showing, reset cursor state */ + if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) + pI830->CursorInfoRec->ShowCursor(pScrn); + } + return n; } diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index d52eb607..52621e03 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -66,3 +66,6 @@ i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index); Bool I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); + +void +I830DumpSDVO(ScrnInfoPtr pScrn); diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c new file mode 100644 index 00000000..16a8cd83 --- /dev/null +++ b/src/i830_xf86Modes.c @@ -0,0 +1,348 @@ +/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "xf86.h" +#include "i830.h" +#include "i830_xf86Modes.h" + +/** + * @file this file contains symbols from xf86Mode.c and friends that are static + * there but we still want to use. We need to come up with better API here. + */ + +/** + * Calculates the vertical refresh of a mode. + * + * Exact copy of xf86Mode.c's. + */ +double +I830ModeVRefresh(DisplayModePtr mode) +{ + double refresh = 0.0; + + if (mode->VRefresh > 0.0) + refresh = mode->VRefresh; + else if (mode->HTotal > 0 && mode->VTotal > 0) { + refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; + if (mode->Flags & V_INTERLACE) + refresh *= 2.0; + if (mode->Flags & V_DBLSCAN) + refresh /= 2.0; + if (mode->VScan > 1) + refresh /= (float)(mode->VScan); + } + return refresh; +} + +/* + * I830xf86SetModeCrtc + * + * Initialises the Crtc parameters for a mode. The initialisation includes + * adjustments for interlaced and double scan modes. + * + * Exact copy of xf86Mode.c's. + */ +void +I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) +{ + if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)) + return; + + p->CrtcHDisplay = p->HDisplay; + p->CrtcHSyncStart = p->HSyncStart; + p->CrtcHSyncEnd = p->HSyncEnd; + p->CrtcHTotal = p->HTotal; + p->CrtcHSkew = p->HSkew; + p->CrtcVDisplay = p->VDisplay; + p->CrtcVSyncStart = p->VSyncStart; + p->CrtcVSyncEnd = p->VSyncEnd; + p->CrtcVTotal = p->VTotal; + if (p->Flags & V_INTERLACE) { + if (adjustFlags & INTERLACE_HALVE_V) { + p->CrtcVDisplay /= 2; + p->CrtcVSyncStart /= 2; + p->CrtcVSyncEnd /= 2; + p->CrtcVTotal /= 2; + } + /* Force interlaced modes to have an odd VTotal */ + /* maybe we should only do this when INTERLACE_HALVE_V is set? */ + p->CrtcVTotal |= 1; + } + + if (p->Flags & V_DBLSCAN) { + p->CrtcVDisplay *= 2; + p->CrtcVSyncStart *= 2; + p->CrtcVSyncEnd *= 2; + p->CrtcVTotal *= 2; + } + if (p->VScan > 1) { + p->CrtcVDisplay *= p->VScan; + p->CrtcVSyncStart *= p->VScan; + p->CrtcVSyncEnd *= p->VScan; + p->CrtcVTotal *= p->VScan; + } + p->CrtcHAdjusted = FALSE; + p->CrtcVAdjusted = FALSE; + + /* + * XXX + * + * The following is taken from VGA, but applies to other cores as well. + */ + p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); + p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); + if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) { + /* + * V Blanking size must be < 127. + * Moving blank start forward is safer than moving blank end + * back, since monitors clamp just AFTER the sync pulse (or in + * the sync pulse), but never before. + */ + p->CrtcVBlankStart = p->CrtcVBlankEnd - 127; + /* + * If VBlankStart is now > VSyncStart move VBlankStart + * to VSyncStart using the maximum width that fits into + * VTotal. + */ + if (p->CrtcVBlankStart > p->CrtcVSyncStart) { + p->CrtcVBlankStart = p->CrtcVSyncStart; + p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal); + } + } + p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); + p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); + + if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) { + /* + * H Blanking size must be < 63*8. Same remark as above. + */ + p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8; + if (p->CrtcHBlankStart > p->CrtcHSyncStart) { + p->CrtcHBlankStart = p->CrtcHSyncStart; + p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal); + } + } +} + +/** + * Returns true if the given modes should program to the same timings. + * + * This doesn't use Crtc values, as it might be used on ModeRecs without the + * Crtc values set. So, it's assumed that the other numbers are enough. + * + * This isn't in xf86Modes.c, but it might deserve to be there. + */ +Bool +I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2) +{ + if (pMode1->Clock == pMode2->Clock && + pMode1->HDisplay == pMode2->HDisplay && + pMode1->HSyncStart == pMode2->HSyncStart && + pMode1->HSyncEnd == pMode2->HSyncEnd && + pMode1->HTotal == pMode2->HTotal && + pMode1->HSkew == pMode2->HSkew && + pMode1->VDisplay == pMode2->VDisplay && + pMode1->VSyncStart == pMode2->VSyncStart && + pMode1->VSyncEnd == pMode2->VSyncEnd && + pMode1->VTotal == pMode2->VTotal && + pMode1->VScan == pMode2->VScan && + pMode1->Flags == pMode2->Flags) + { + return TRUE; + } else { + return FALSE; + } +} + +/* exact copy of xf86Mode.c */ +static void +add(char **p, char *new) +{ + *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); + strcat(*p, " "); + strcat(*p, new); +} + +/** + * Print out a modeline. + * + * Convenient VRefresh printing was added, though, compared to xf86Mode.c + */ +void +PrintModeline(int scrnIndex,DisplayModePtr mode) +{ + char tmp[256]; + char *flags = xnfcalloc(1, 1); + + if (mode->HSkew) { + snprintf(tmp, 256, "hskew %i", mode->HSkew); + add(&flags, tmp); + } + if (mode->VScan) { + snprintf(tmp, 256, "vscan %i", mode->VScan); + add(&flags, tmp); + } + if (mode->Flags & V_INTERLACE) add(&flags, "interlace"); + if (mode->Flags & V_CSYNC) add(&flags, "composite"); + if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan"); + if (mode->Flags & V_BCAST) add(&flags, "bcast"); + if (mode->Flags & V_PHSYNC) add(&flags, "+hsync"); + if (mode->Flags & V_NHSYNC) add(&flags, "-hsync"); + if (mode->Flags & V_PVSYNC) add(&flags, "+vsync"); + if (mode->Flags & V_NVSYNC) add(&flags, "-vsync"); + if (mode->Flags & V_PCSYNC) add(&flags, "+csync"); + if (mode->Flags & V_NCSYNC) add(&flags, "-csync"); +#if 0 + if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); +#endif + xf86DrvMsg(scrnIndex, X_ERROR, + "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s\n", + mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay, + mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, + mode->VTotal, flags); + xfree(flags); +} + +#define MODEPREFIX(name) NULL, NULL, name, MODE_OK, M_T_DEFAULT +#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 + +/** + * List of VESA established modes, taken from xf86DefaultModes but trimmed down. + * (not trimming should be harmless). + */ +DisplayModeRec I830xf86DefaultModes[] = { +/* 640x350 @ 85Hz (VESA) hsync: 37.9kHz */ + {MODEPREFIX("640x350"),31500, 640,672,736,832,0, 350,382,385,445,0, V_PHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("320x175"),15750, 320,336,368,416,0, 175,191,192,222,0, V_PHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 640x400 @ 85Hz (VESA) hsync: 37.9kHz */ + {MODEPREFIX("640x400"),31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("320x200"),15750, 320,336,368,416,0, 200,200,202,222,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 720x400 @ 85Hz (VESA) hsync: 37.9kHz */ + {MODEPREFIX("720x400"),35500, 720,756,828,936,0, 400,401,404,446,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("360x200"),17750, 360,378,414,468,0, 200,200,202,223,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */ + {MODEPREFIX("640x480"),31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("320x240"),15750, 320,332,352,416,0, 240,244,245,260,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */ + {MODEPREFIX("640x480"),31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("320x240"),15750, 320,328,360,420,0, 240,240,242,250,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */ + {MODEPREFIX("640x480"),36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("320x240"),18000, 320,348,376,416,0, 240,240,242,254,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */ + {MODEPREFIX("800x600"),36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("400x300"),18000, 400,412,448,512,0, 300,300,301,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */ + {MODEPREFIX("800x600"),40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("400x300"),20000, 400,420,484,528,0, 300,300,302,314,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */ + {MODEPREFIX("800x600"),50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("400x300"),25000, 400,428,488,520,0, 300,318,321,333,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */ + {MODEPREFIX("800x600"),49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("400x300"),24750, 400,408,448,528,0, 300,300,302,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */ + {MODEPREFIX("800x600"),56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("400x300"),28150, 400,416,448,524,0, 300,300,302,315,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */ + {MODEPREFIX("1024x768"),65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("512x384"),32500, 512,524,592,672,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */ + {MODEPREFIX("1024x768"),75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX}, + {MODEPREFIX("512x384"),37500, 512,524,592,664,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */ + {MODEPREFIX("1024x768"),78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("512x384"),39400, 512,520,568,656,0, 384,384,386,400,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */ + {MODEPREFIX("1024x768"),94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("512x384"),47250, 512,536,584,688,0, 384,384,386,404,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */ + {MODEPREFIX("1152x864"),108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("576x432"),54000, 576,608,672,800,0, 432,432,434,450,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1280x960 @ 60Hz (VESA) hsync: 60.0kHz */ + {MODEPREFIX("1280x960"),108000, 1280,1376,1488,1800,0, 960,961,964,1000,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("640x480"),54000, 640,688,744,900,0, 480,480,482,500,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1280x960 @ 85Hz (VESA) hsync: 85.9kHz */ + {MODEPREFIX("1280x960"),148500, 1280,1344,1504,1728,0, 960,961,964,1011,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("640x480"),74250, 640,672,752,864,0, 480,480,482,505,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz */ + {MODEPREFIX("1280x1024"),108000, 1280,1328,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("640x512"),54000, 640,664,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz */ + {MODEPREFIX("1280x1024"),135000, 1280,1296,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("640x512"),67500, 640,648,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz */ + {MODEPREFIX("1280x1024"),157500, 1280,1344,1504,1728,0, 1024,1025,1028,1072,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("640x512"),78750, 640,672,752,864,0, 512,512,514,536,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz */ + {MODEPREFIX("1600x1200"),162000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("800x600"),81000, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz */ + {MODEPREFIX("1600x1200"),175500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("800x600"),87750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz */ + {MODEPREFIX("1600x1200"),189000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("800x600"),94500, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz */ + {MODEPREFIX("1600x1200"),202500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("800x600"),101250, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz */ + {MODEPREFIX("1600x1200"),229500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("800x600"),114750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz */ + {MODEPREFIX("1792x1344"),204800, 1792,1920,2120,2448,0, 1344,1345,1348,1394,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("896x672"),102400, 896,960,1060,1224,0, 672,672,674,697,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz */ + {MODEPREFIX("1792x1344"),261000, 1792,1888,2104,2456,0, 1344,1345,1348,1417,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("896x672"),130500, 896,944,1052,1228,0, 672,672,674,708,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz */ + {MODEPREFIX("1856x1392"),218300, 1856,1952,2176,2528,0, 1392,1393,1396,1439,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("928x696"),109150, 928,976,1088,1264,0, 696,696,698,719,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz */ + {MODEPREFIX("1856x1392"),288000, 1856,1984,2208,2560,0, 1392,1393,1396,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("928x696"),144000, 928,992,1104,1280,0, 696,696,698,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz */ + {MODEPREFIX("1920x1440"),234000, 1920,2048,2256,2600,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("960x720"),117000, 960,1024,1128,1300,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, +/* 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz */ + {MODEPREFIX("1920x1440"),297000, 1920,2064,2288,2640,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX}, + {MODEPREFIX("960x720"),148500, 960,1032,1144,1320,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX}, + + /* Terminator */ + {MODEPREFIX(NULL), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX} +}; diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h new file mode 100644 index 00000000..ba7d8209 --- /dev/null +++ b/src/i830_xf86Modes.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +double +I830ModeVRefresh(DisplayModePtr mode); + +void +I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); + +Bool +I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); + +void +PrintModeline(int scrnIndex,DisplayModePtr mode); + +extern DisplayModeRec I830xf86DefaultModes[]; From 6d1d105d68d9c25890c3fd2ebad1367529c2a991 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 10:14:27 +0200 Subject: [PATCH 108/257] Unset pipe current mode on EnterVT, so we reprogram the mode for sure. --- src/i830_driver.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 32beb8a5..7af5fb7b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3954,10 +3954,13 @@ I830BIOSEnterVT(int scrnIndex, int flags) ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); + /* Mark that we'll need to re-set the mode for sure */ + memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode)); + /* Detect monitor change and switch to suitable mode */ if (!pI830->starting) I830DetectMonitorChange(pScrn); - + if (!i830SetMode(pScrn, pScrn->currentMode)) return FALSE; From d2c18d8d79596513149273e4a0d322f04bf27e80 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 10:15:11 +0200 Subject: [PATCH 109/257] Fix DDC probing after last (untested) commit. --- src/i830_modes.c | 67 ++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index e1e5fd53..fe28c7a8 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -182,41 +182,43 @@ I830DuplicateMode(DisplayModePtr pMode) * Highest resolution first. */ void -I830xf86SortModes(DisplayModePtr *new, DisplayModePtr *first, +I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first, DisplayModePtr *last) { DisplayModePtr p; p = *last; while (p) { - if ((((*new)->HDisplay < p->HDisplay) && - ((*new)->VDisplay < p->VDisplay)) || - (((*new)->HDisplay == p->HDisplay) && - ((*new)->VDisplay == p->VDisplay) && - ((*new)->Clock < p->Clock))) { + if (((new->HDisplay < p->HDisplay) && + (new->VDisplay < p->VDisplay)) || + ((new->HDisplay == p->HDisplay) && + (new->VDisplay == p->VDisplay) && + (new->Clock < p->Clock))) { - if (p->next) p->next->prev = *new; - (*new)->prev = p; - (*new)->next = p->next; - p->next = *new; - if (!((*new)->next)) *last = *new; + if (p->next) + p->next->prev = new; + new->prev = p; + new->next = p->next; + p->next = new; + if (!(new->next)) + *last = new; break; } if (!p->prev) { - (*new)->prev = NULL; - (*new)->next = p; - p->prev = *new; - *first = *new; + new->prev = NULL; + new->next = p; + p->prev = new; + *first = new; break; } p = p->prev; } if (!*first) { - *first = *new; - (*new)->prev = NULL; - (*new)->next = NULL; - *last = *new; + *first = new; + new->prev = NULL; + new->next = NULL; + *last = new; } } @@ -230,7 +232,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) { DisplayModePtr pMode; - for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode = pMode->next) + for (pMode = I830xf86DefaultModes; pMode->name != NULL; pMode++) { if (pMode->HDisplay == est_timings[i].hsize && pMode->VDisplay == est_timings[i].vsize && @@ -301,7 +303,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) new->HTotal, new->HSyncStart, new->HSyncEnd, new->VTotal, new->VSyncStart, new->VSyncEnd); - I830xf86SortModes(&new, &first, &last); + I830xf86SortModes(new, &first, &last); } } @@ -315,7 +317,11 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) new->status = MODE_OK; new->type |= M_T_DEFAULT; - I830xf86SortModes(&new, &first, &last); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid Mode from standard timing table: %s\n", + new->name); + + I830xf86SortModes(new, &first, &last); #else for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { @@ -342,7 +348,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) "Valid Mode from standard timing table: %s\n", new->name); - I830xf86SortModes(&new, &first, &last); + I830xf86SortModes(new, &first, &last); break; } } @@ -354,11 +360,11 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2; for (j = 0; j < 16; j++) { if (tmp & (1 << j)) { - DisplayModePtr pNew; - - pNew = I830GetVESAEstablishedMode(pScrn, j); - assert(pNew != NULL); /* We'd better have all the est. modes. */ - + new = I830GetVESAEstablishedMode(pScrn, j); + if (new == NULL) { + ErrorF("Couldn't get established mode %d\n", j); + continue; + } new->status = MODE_OK; new->type = M_T_DEFAULT; @@ -367,7 +373,7 @@ DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid Mode from established " "timing table: %s\n", new->name); - I830xf86SortModes(&new, &first, &last); + I830xf86SortModes(new, &first, &last); } } @@ -643,7 +649,6 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) { I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); - pMode->VRefresh = I830ModeVRefresh(pMode); } } else { ErrorF("don't know how to get modes for this device.\n"); @@ -714,7 +719,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) I830Ptr pI830 = I830PTR(pScrn); ClockRangePtr clockRanges; int n, pipe; - DisplayModePtr saved_mode, availModes; + DisplayModePtr saved_mode, availModes = NULL; int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0; Bool pipes_reconfigured = FALSE; From 51d14f803aae6d0a738520c3cad110289ee444db Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 10:21:23 +0200 Subject: [PATCH 110/257] Add a function to turn off unused outputs, DPLLs, planes, and pipes. --- src/i830_display.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 1546c377..a96e6ee9 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -637,6 +637,111 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) return TRUE; } +static void +i830DisableUnusedFunctions(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int outputsA, outputsB; + + return; + + outputsA = pI830->operatingDevices & 0xff; + outputsB = (pI830->operatingDevices >> 8) & 0xff; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); + + /* First, disable the unused outputs */ + if ((outputsA & PIPE_CRT_ACTIVE) == 0 && + (outputsB & PIPE_CRT_ACTIVE) == 0) + { + CARD32 adpa = INREG(adpa); + + if (adpa & ADPA_DAC_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n"); + OUTREG(ADPA, adpa & ~ADPA_DAC_ENABLE); + } + } + + if ((outputsB & PIPE_LCD_ACTIVE) == 0) { + CARD32 pp_status = INREG(PP_STATUS); + + if (pp_status & PP_ON) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling LVDS output\n"); + i830SetLVDSPanelPower(pScrn, FALSE); + } + } + + if (IS_I9XX(pI830) && ((outputsA & PIPE_DFP_ACTIVE) == 0 && + (outputsB & PIPE_DFP_ACTIVE) == 0)) + { + CARD32 sdvob = INREG(SDVOB); + CARD32 sdvoc = INREG(SDVOC); + + if (sdvob & SDVO_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOB output\n"); + OUTREG(SDVOB, sdvob & ~SDVO_ENABLE); + } + if (sdvoc & SDVO_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOC output\n"); + OUTREG(SDVOC, sdvoc & ~SDVO_ENABLE); + } + } + + /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915 + * internal TV) should have no outputs trying to pull data out of it, so + * we're ready to turn those off. + */ + if (!pI830->planeEnabled[0]) { + CARD32 dspcntr, pipeconf, dpll; + + dspcntr = INREG(DSPACNTR); + if (dspcntr & DISPLAY_PLANE_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane A\n"); + OUTREG(DSPACNTR, dspcntr & ~DISPLAY_PLANE_ENABLE); + + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + } + + pipeconf = INREG(PIPEACONF); + if (pipeconf & PIPEACONF_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe A\n"); + OUTREG(PIPEACONF, pipeconf & ~PIPEACONF_ENABLE); + } + + dpll = INREG(DPLL_A); + if (dpll & DPLL_VCO_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n"); + OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE); + } + } + + if (!pI830->planeEnabled[1]) { + CARD32 dspcntr, pipeconf, dpll; + + dspcntr = INREG(DSPBCNTR); + if (dspcntr & DISPLAY_PLANE_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane B\n"); + OUTREG(DSPBCNTR, dspcntr & ~DISPLAY_PLANE_ENABLE); + + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + } + + pipeconf = INREG(PIPEBCONF); + if (pipeconf & PIPEBCONF_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe B\n"); + OUTREG(PIPEBCONF, pipeconf & ~PIPEBCONF_ENABLE); + } + + dpll = INREG(DPLL_B); + if (dpll & DPLL_VCO_ENABLE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n"); + OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE); + } + } +} + /** * This function sets the given mode on the active pipes. */ @@ -693,6 +798,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(pMode->HDisplay * pMode->VDisplay * pMode->VRefresh / 1000000)); + i830DisableUnusedFunctions(pScrn); + planeA = INREG(DSPACNTR); planeB = INREG(DSPBCNTR); From 0e5cda3796ba0164496f0814eb57d1dfa7ab9257 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 10:30:46 +0200 Subject: [PATCH 111/257] Fix FP scaling by using the desired mode to get at the real [HV]Display. --- src/i830_display.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index a96e6ee9..4719cef2 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -262,6 +262,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) Bool ok, is_sdvo; int refclk, pixel_clock, sdvo_pixel_multiply; int outputs; + DisplayModePtr pMasterMode = pMode; assert(pMode->VRefresh != 0.0); /* If we've got a list of modes probed for the device, find the best match @@ -341,8 +342,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); - pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); - dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + pipesrc = ((pMasterMode->HDisplay - 1) << 16) | (pMasterMode->VDisplay - 1); + dspsize = ((pMasterMode->VDisplay - 1) << 16) | (pMasterMode->HDisplay - 1); pixel_clock = pMode->Clock; if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0) { @@ -369,17 +370,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) | ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + pI830->panel_fixed_vsyncwidth - 1) << 16); - /* Hack until we get better clone-mode modesetting. If the mode to be - * programmed is larger than the size of the panel, only display the - * size of the panel. - */ - if (pMode->HDisplay > pI830->panel_fixed_hactive || - pMode->VDisplay > pI830->panel_fixed_vactive) { - dspsize = ((pI830->panel_fixed_vactive - 1) << 16) | - (pI830->panel_fixed_hactive - 1); - pipesrc = ((pI830->panel_fixed_hactive - 1) << 16) | - (pI830->panel_fixed_vactive - 1); - } pixel_clock = pI830->panel_fixed_clock; } From f113e9002cf53510e30984f816d44b06f1e71216 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 12:54:30 +0200 Subject: [PATCH 112/257] Fix the plane/pipe disabling and turn off missing outputs when no longer DDCed. --- src/i830_display.c | 8 +++++--- src/i830_modes.c | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 4719cef2..05b7655b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -633,8 +633,6 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); int outputsA, outputsB; - return; - outputsA = pI830->operatingDevices & 0xff; outputsB = (pI830->operatingDevices >> 8) & 0xff; @@ -644,7 +642,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) if ((outputsA & PIPE_CRT_ACTIVE) == 0 && (outputsB & PIPE_CRT_ACTIVE) == 0) { - CARD32 adpa = INREG(adpa); + CARD32 adpa = INREG(ADPA); if (adpa & ADPA_DAC_ENABLE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n"); @@ -704,6 +702,8 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n"); OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE); } + + memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0])); } if (!pI830->planeEnabled[1]) { @@ -729,6 +729,8 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n"); OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE); } + + memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1])); } } diff --git a/src/i830_modes.c b/src/i830_modes.c index fe28c7a8..a43fa617 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -603,7 +603,9 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) int i; int outputs; DisplayModePtr pMode; + Bool had_modes; + had_modes = (pI830->pipeModes[pipe] != NULL); while (pI830->pipeModes[pipe] != NULL) xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]); @@ -650,6 +652,14 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) { I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); } + if (had_modes && pI830->pipeModes[pipe] == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Failed to DDC pipe %d, disabling output\n", pipe); + if (pipe == 0) + pI830->operatingDevices &= ~0x00ff; + else + pI830->operatingDevices &= ~0xff00; + } } else { ErrorF("don't know how to get modes for this device.\n"); } From 7104b915da412a26661bab7b5a940e935e8cbc8a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jun 2006 15:11:13 +0200 Subject: [PATCH 113/257] Clean up warnings. --- src/i830_debug.c | 2 +- src/i830_display.c | 2 +- src/i830_driver.c | 5 +++-- src/i830_modes.c | 9 +++++---- src/i830_sdvo.c | 7 ++++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index 6d43cd60..e2a28b27 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -32,8 +32,8 @@ #include "xf86.h" #include "xf86_ansic.h" #include "i830.h" +#include "i830_debug.h" -/* XXX: What was the syntax for sticking quotes around the "reg" argument? */ #define DEFINEREG(reg) \ { reg, #reg, 0 } diff --git a/src/i830_display.c b/src/i830_display.c index 05b7655b..1391c287 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -919,7 +919,7 @@ i830LoadDetectCRT(ScrnInfoPtr pScrn) * This takes approximately 5ms in testing on an i915GM, with CRT connected or * not. */ -Bool +static Bool i830DDCDetectCRT(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index 7af5fb7b..6b7dfc70 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1101,7 +1101,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) pI830->num_outputs = i; } -void +static void I830PreInitDDC(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); @@ -1128,7 +1128,8 @@ I830PreInitDDC(ScrnInfoPtr pScrn) } } -void I830DetectMonitors(ScrnInfoPtr pScrn) +static void +I830DetectMonitors(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int i; diff --git a/src/i830_modes.c b/src/i830_modes.c index a43fa617..6ee1a942 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -181,7 +181,7 @@ I830DuplicateMode(DisplayModePtr pMode) /* This function will sort all modes according to their resolution. * Highest resolution first. */ -void +static void I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first, DisplayModePtr *last) { @@ -246,7 +246,8 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) return NULL; } -DisplayModePtr I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) +static DisplayModePtr +I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) { DisplayModePtr last = NULL; DisplayModePtr new = NULL; @@ -438,7 +439,7 @@ i830FPNativeMode(ScrnInfoPtr pScrn) * * \return doubly-linked list of modes. */ -DisplayModePtr +static DisplayModePtr i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) { I830Ptr pI830 = I830PTR(pScrn); @@ -541,7 +542,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) * it into the doubly-linked modeList. We don't need to filter, because the * eventual call to xf86ValidateModes will do this for us. I think. */ -int +static int I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, DisplayModePtr addModes) { diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 06840ef1..9a18f578 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86_OSproc.h" #include "compiler.h" #include "i830.h" +#include "i830_display.h" #include "i830_sdvo_regs.h" CARD16 curr_table[6]; @@ -170,7 +171,7 @@ I830SDVOReadInputRegs(I830SDVOPtr s) * PROM. It resets from the DDC bus back to internal registers at the next I2C * STOP. PROM access is terminated by accessing an internal register. */ -Bool +static Bool I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target) { memset(s->sdvo_regs, 0, 9); @@ -277,7 +278,7 @@ I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2) } /* Fetches either input or output timings to *dtd, depending on cmd. */ -Bool +static Bool I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) { memset(s->sdvo_regs, 0, 9); @@ -312,7 +313,7 @@ I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) } /* Sets either input or output timings to *dtd, depending on cmd. */ -Bool +static Bool I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) { memset(s->sdvo_regs, 0, 9); From 56f7aedd0ad1f5645a90a5509b1263ec6b7b7ee1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jun 2006 00:37:56 +0200 Subject: [PATCH 114/257] Fix randr current mode reporting and mode loss/mis-configuration on re-randr. --- src/i830.h | 1 + src/i830_display.c | 35 +++++++++++++++++++++++------------ src/i830_modes.c | 19 +++++++------------ src/i830_randr.c | 29 ++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/i830.h b/src/i830.h index 11015bfc..9bd02275 100644 --- a/src/i830.h +++ b/src/i830.h @@ -606,6 +606,7 @@ Bool I830RandRInit(ScreenPtr pScreen, int rotation); Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); Rotation I830GetRotation(ScreenPtr pScreen); +void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); /* * 12288 is set as the maximum, chosen because it is enough for diff --git a/src/i830_display.c b/src/i830_display.c index 1391c287..8080c55c 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -285,32 +285,39 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) continue; } /* Find if it's closer than the current best option */ - if (abs(pScan->VRefresh - pMode->VRefresh) > - abs(pBest->VRefresh - pMode->VRefresh)) + if ((pScan->HDisplay >= pBest->HDisplay && + pScan->HDisplay >= pBest->HDisplay) || + (fabs(pScan->VRefresh - pMode->VRefresh) < + fabs(pBest->VRefresh - pMode->VRefresh))) { - continue; + pBest = pScan; } } if (pBest != NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Choosing pipe's mode %p (%dx%dx%.1f) instead of xf86 " - "mode %p (%dx%dx%.1f)\n", pBest, + "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " + "mode %dx%d@%.1f\n", pipe, pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, - pMode, pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); pMode = pBest; } } - if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) - return TRUE; - - ErrorF("Requested pix clock: %d\n", pMode->Clock); - if (pipe == 0) outputs = pI830->operatingDevices & 0xff; else outputs = (pI830->operatingDevices >> 8) & 0xff; + if (outputs & PIPE_LCD_ACTIVE) { + if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMasterMode)) + return TRUE; + } else { + if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) + return TRUE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", + pMode->Clock); + if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable LVDS and non-LVDS on the same pipe\n"); @@ -622,7 +629,11 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(SDVOC, sdvoc); } - pI830->pipeCurMode[pipe] = *pMode; + if (outputs & PIPE_LCD_ACTIVE) { + pI830->pipeCurMode[pipe] = *pMasterMode; + } else { + pI830->pipeCurMode[pipe] = *pMode; + } return TRUE; } diff --git a/src/i830_modes.c b/src/i830_modes.c index 6ee1a942..893ef101 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -43,12 +43,12 @@ #include #include #include +#include #include "xf86.h" #include "i830.h" #include "i830_xf86Modes.h" - -#include +#include #define rint(x) floor(x) @@ -415,11 +415,6 @@ i830FPNativeMode(ScrnInfoPtr pScrn) new->type = M_T_USERDEF; - pScrn->virtualX = MAX(pScrn->virtualX, pI830->PanelXRes); - pScrn->virtualY = MAX(pScrn->virtualY, pI830->PanelYRes); - pScrn->display->virtualX = pScrn->virtualX; - pScrn->display->virtualY = pScrn->virtualY; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No valid mode specified, force to native mode\n"); @@ -450,9 +445,6 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) int count = 0; int i, width, height; - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - /* We have a flat panel connected to the primary display, and we * don't have any DDC info. */ @@ -733,6 +725,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) DisplayModePtr saved_mode, availModes = NULL; int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0; Bool pipes_reconfigured = FALSE; + int originalVirtualX, originalVirtualY; for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { I830ReprobePipeModeList(pScrn, pipe); @@ -810,6 +803,8 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) saved_displayWidth = pScrn->displayWidth; } + I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + /* Take the pScrn->monitor->Modes we've accumulated and validate them into * pScrn->modes. * XXX: Should set up a scrp->monitor->DDC covering the union of the @@ -825,8 +820,8 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) 64 * pScrn->bitsPerPixel, /* pitchInc */ 200, /* minHeight */ MAX_DISPLAY_HEIGHT, /* maxHeight */ - pScrn->virtualX, /* virtualX */ - pScrn->virtualY, /* virtualY */ + originalVirtualX, /* virtualX maximum */ + originalVirtualY, /* virtualY maximum */ pI830->FbMapSize, /* apertureSize */ LOOKUP_BEST_REFRESH /* strategy */); diff --git a/src/i830_randr.c b/src/i830_randr.c index 93c05198..4c7c087e 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -35,6 +35,7 @@ #include #include "i830.h" +#include "i830_xf86Modes.h" typedef struct _i830RandRInfo { int virtualX; @@ -100,9 +101,13 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) if (!pSize) return FALSE; RRRegisterRate (pScreen, pSize, refresh); - if (mode == scrp->currentMode && - mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) + + if (I830ModesEqual(mode, scrp->currentMode) && + mode->HDisplay == scrp->virtualX && + mode->VDisplay == scrp->virtualY) + { RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + } if (mode->next == scrp->modes) break; } @@ -116,7 +121,6 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) if (scrp->currentMode->HDisplay != randrp->virtualX || scrp->currentMode->VDisplay != randrp->virtualY) { - mode = scrp->modes; pSize = RRRegisterSize (pScreen, randrp->virtualX, randrp->virtualY, randrp->mmWidth, @@ -164,6 +168,7 @@ I830RandRSetMode (ScreenPtr pScreen, scrp->virtualX = mode->HDisplay; scrp->virtualY = mode->VDisplay; } + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) { /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ @@ -356,3 +361,21 @@ I830RandRInit (ScreenPtr pScreen, int rotation) return TRUE; } + +void +I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) +{ + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + + if (i830RandRGeneration != serverGeneration || + XF86RANDRINFO(pScreen)->virtualX == -1) + { + *x = pScrn->virtualX; + *y = pScrn->virtualY; + } else { + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + *x = randrp->virtualX; + *y = randrp->virtualY; + } +} From 9fbd3d8f4befb75ed6f6bd9a9ffe0175626e8785 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jun 2006 23:31:40 +0200 Subject: [PATCH 115/257] If the panel power registers are all zeroes on Mobile parts, disable LVDS. This is the case on the Mac mini, which is an i945GM but has no LVDS attached. Powering on with the power timing registers zeroed would probably be a bad idea, even if there was a panel attached. --- src/i830_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/i830_driver.c b/src/i830_driver.c index 6b7dfc70..ca87951a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1701,6 +1701,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) if (!i830GetLVDSInfoFromBIOS(pScrn)) has_lvds = FALSE; + /* If the panel sequencing, status, and control registers are all zero, + * assume there's no panel attached. This is the case on the Mac mini, + * which is an i945GM but has no LVDS. If we tried to power something on + * with zeroed panel sequencing registers, it probably wouldn't be a good + * thing anyway. + */ + if (INREG(PP_STATUS) == 0 && INREG(PP_CONTROL) == 0 && + INREG(LVDSPP_ON) == 0 && INREG(LVDSPP_OFF) == 0) + { + has_lvds = FALSE; + } + if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { char *Mon1; From 367f69f8e7710e53dcd286f1b62506a3276e80f9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jun 2006 13:10:02 +0200 Subject: [PATCH 116/257] Replace xf86ValidateModes usage with a set of custom validators and pruning. This moves us to maintaining MonPtrs per pipe instead of using the EDID structure "xf86MonPtr", which is closer to what we want to be looking at when doing validation. The new validation isn't enough yet -- particularly, we aren't importing and validating the custom modelines to the pipes when applicable, but this will be easier than (for example) trying to make flat panel modes pass xf86ValidateModes through various gross hacks. Hotplug turn-on/off also happens at SwitchMode time now, instead of at randr probe time. --- src/i830.h | 7 +- src/i830_display.c | 45 ++++- src/i830_modes.c | 446 +++++++++++++++++++++++++++---------------- src/i830_xf86Modes.c | 120 ++++++++++++ src/i830_xf86Modes.h | 20 ++ 5 files changed, 467 insertions(+), 171 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9bd02275..f1b97745 100644 --- a/src/i830.h +++ b/src/i830.h @@ -227,6 +227,10 @@ typedef struct _I830Rec { int fixedPipe; DisplayModePtr currentMode; + /* Mode saved during randr reprobe, which will need to be freed at the point + * of the next SwitchMode, when we lose this last reference to it. + */ + DisplayModePtr savedCurrentMode; Bool Clone; int CloneRefresh; @@ -401,8 +405,7 @@ typedef struct _I830Rec { int availablePipes; /* [0] is display plane A, [1] is display plane B. */ int planeEnabled[MAX_DISPLAY_PIPES]; - xf86MonPtr pipeMon[MAX_DISPLAY_PIPES]; - DisplayModePtr pipeModes[MAX_DISPLAY_PIPES]; + MonPtr pipeMon[MAX_DISPLAY_PIPES]; DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ diff --git a/src/i830_display.c b/src/i830_display.c index 8080c55c..24103cb7 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -268,11 +268,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* If we've got a list of modes probed for the device, find the best match * in there to the requested mode. */ - if (pI830->pipeModes[pipe] != NULL) { + if (pI830->pipeMon[pipe] != NULL) { DisplayModePtr pBest = NULL, pScan; assert(pScan->VRefresh != 0.0); - for (pScan = pI830->pipeModes[pipe]; pScan != NULL; pScan = pScan->next) + for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL; + pScan = pScan->next) { /* Reject if it's larger than the desired mode. */ if (pScan->HDisplay > pMode->HDisplay || @@ -284,9 +285,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pBest = pScan; continue; } - /* Find if it's closer than the current best option */ - if ((pScan->HDisplay >= pBest->HDisplay && - pScan->HDisplay >= pBest->HDisplay) || + /* Find if it's closer to the right size than the current best + * option. + */ + if (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) + { + pBest = pScan; + continue; + } + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (pScan->HDisplay == pBest->HDisplay && + pScan->VDisplay == pBest->VDisplay && (fabs(pScan->VRefresh - pMode->VRefresh) < fabs(pBest->VRefresh - pMode->VRefresh))) { @@ -801,6 +813,29 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(pMode->HDisplay * pMode->VDisplay * pMode->VRefresh / 1000000)); + if (pI830->savedCurrentMode) { + /* We're done with the currentMode that the last randr probe had left + * behind, so free it. + */ + xfree(pI830->savedCurrentMode->name); + xfree(pI830->savedCurrentMode); + + /* If we might have enabled/disabled some pipes, we need to reset + * cloning mode support. + */ + if ((pI830->operatingDevices & 0x00ff) && + (pI830->operatingDevices & 0xff00)) + { + pI830->Clone = TRUE; + } else { + pI830->Clone = FALSE; + } + + /* If HW cursor currently showing, reset cursor state */ + if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) + pI830->CursorInfoRec->ShowCursor(pScrn); + } + i830DisableUnusedFunctions(pScrn); planeA = INREG(DSPACNTR); diff --git a/src/i830_modes.c b/src/i830_modes.c index 893ef101..74333441 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -47,6 +47,7 @@ #include "xf86.h" #include "i830.h" +#include "i830_display.h" #include "i830_xf86Modes.h" #include @@ -247,7 +248,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) } static DisplayModePtr -I830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) +i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) { DisplayModePtr last = NULL; DisplayModePtr new = NULL; @@ -487,9 +488,11 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) /* If the user hasn't specified modes, add the native mode */ if (!count) { - first = last = i830FPNativeMode(pScrn); - if (first) + new = i830FPNativeMode(pScrn); + if (first) { + I830xf86SortModes(new, &first, &last); count = 1; + } } /* add in all default vesa modes smaller than panel size, used for randr */ @@ -507,14 +510,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) else new->type |= M_T_DEFAULT; - new->next = NULL; - new->prev = last; - - if (last) - last->next = new; - last = new; - if (!first) - first = new; + I830xf86SortModes(new, &first, &last); count++; } @@ -546,9 +542,6 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, for (addMode = addModes; addMode != NULL; addMode = addMode->next) { DisplayModePtr pNew; - /* XXX: Do we need to check if modeList already contains the same mode? - */ - pNew = I830DuplicateMode(addMode); #if 0 /* If the user didn't specify any modes, mark all modes as M_T_USERDEF @@ -580,6 +573,102 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, return count; } +static DisplayModePtr +i830GetModeListTail(DisplayModePtr pModeList) +{ + DisplayModePtr last; + + if (pModeList == NULL) + return NULL; + + for (last = pModeList; last->next != NULL; last = last->next) + ; + + return last; +} + +static MonPtr +i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) +{ + xf86MonPtr ddc; + MonPtr mon; + int i; + + ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus); + + if (ddc == NULL) + return NULL; + + mon = xnfcalloc(1, sizeof(*mon)); + mon->Modes = i830GetDDCModes(pScrn, ddc); + mon->Last = i830GetModeListTail(mon->Modes); + mon->DDC = ddc; + + for (i = 0; i < DET_TIMINGS; i++) { + struct detailed_monitor_section *det_mon = &ddc->det_mon[i]; + + switch (ddc->det_mon[i].type) { + case DS_RANGES: + mon->hsync[mon->nHsync].lo = det_mon->section.ranges.min_h; + mon->hsync[mon->nHsync].hi = det_mon->section.ranges.max_h; + mon->nHsync++; + mon->vrefresh[mon->nVrefresh].lo = det_mon->section.ranges.min_v; + mon->vrefresh[mon->nVrefresh].hi = det_mon->section.ranges.max_v; + mon->nVrefresh++; + break; + default: + /* We probably don't care about trying to contruct ranges around + * modes specified by DDC. + */ + break; + } + } + + return mon; +} + +static MonPtr +i830GetLVDSMonitor(ScrnInfoPtr pScrn) +{ + MonPtr mon; + + mon = xnfcalloc(1, sizeof(*mon)); + mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes); + mon->Last = i830GetModeListTail(mon->Modes); + + return mon; +} + +static MonPtr +i830GetConfiguredMonitor(ScrnInfoPtr pScrn) +{ + MonPtr mon; + + mon = xnfcalloc(1, sizeof(*mon)); + memcpy(mon, pScrn->monitor, sizeof(*mon)); + + if (pScrn->monitor->id != NULL) + mon->id = xnfstrdup(pScrn->monitor->id); + if (pScrn->monitor->vendor != NULL) + mon->vendor = xnfstrdup(pScrn->monitor->vendor); + if (pScrn->monitor->model != NULL) + mon->model = xnfstrdup(pScrn->monitor->model); + + return mon; +} + +static void +i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon) +{ + while (mon->Modes != NULL) + xf86DeleteMode(&mon->Modes, mon->Modes); + xfree(mon->id); + xfree(mon->vendor); + xfree(mon->model); + xfree(mon->DDC); + xfree(mon); +} + /** * Performs probing of modes available on the output connected to the given * pipe. @@ -596,11 +685,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) int i; int outputs; DisplayModePtr pMode; - Bool had_modes; - - had_modes = (pI830->pipeModes[pipe] != NULL); - while (pI830->pipeModes[pipe] != NULL) - xf86DeleteMode(&pI830->pipeModes[pipe], pI830->pipeModes[pipe]); + MonPtr old_mon = pI830->pipeMon[pipe]; if (pipe == 0) outputs = pI830->operatingDevices & 0xff; @@ -631,45 +716,87 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) return; if (outputs & PIPE_LFP) { - pI830->pipeMon[pipe] = NULL; /* XXX */ - pI830->pipeModes[pipe] = i830GetLVDSModes(pScrn, - pScrn->display->modes); + pI830->pipeMon[pipe] = i830GetLVDSMonitor(pScrn); } else if (pI830->output[output_index].pDDCBus != NULL) { - /* XXX: Free the mon */ - pI830->pipeMon[pipe] = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[output_index].pDDCBus); - pI830->pipeModes[pipe] = I830GetDDCModes(pScrn, - pI830->pipeMon[pipe]); - - for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) - { - I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); + pI830->pipeMon[pipe] = + i830GetDDCMonitor(pScrn, pI830->output[output_index].pDDCBus); + } + /* If DDC didn't work (or the flat panel equivalent), then see if we can + * detect if a monitor is at least plugged in. If we can't tell that one + * is plugged in, then assume that it is. + */ + if (pI830->pipeMon[pipe] == NULL) { + switch (pI830->output[output_index].type) { + case I830_OUTPUT_SDVO: + if (I830DetectSDVODisplays(pScrn, output_index)) + pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); + break; + case I830_OUTPUT_ANALOG: + /* Do a disruptive detect if necessary, since we want to be sure we + * know if a monitor is attached, and this detect process should be + * infrequent. + */ + if (i830DetectCRT(pScrn, TRUE)) + pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); + break; + default: + pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); + break; } - if (had_modes && pI830->pipeModes[pipe] == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Failed to DDC pipe %d, disabling output\n", pipe); - if (pipe == 0) - pI830->operatingDevices &= ~0x00ff; - else - pI830->operatingDevices &= ~0xff00; - } - } else { - ErrorF("don't know how to get modes for this device.\n"); } - /* Set the vertical refresh, which is used by the choose-best-mode-per-pipe - * code later on. - */ #ifdef DEBUG_REPROBE xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n", pipe); #endif - for (pMode = pI830->pipeModes[pipe]; pMode != NULL; pMode = pMode->next) { - pMode->VRefresh = I830ModeVRefresh(pMode); + if (pI830->pipeMon[pipe] != NULL) { + int minclock, maxclock; + + switch (pI830->output[output_index].type) { + case I830_OUTPUT_SDVO: + minclock = 25000; + maxclock = 165000; + case I830_OUTPUT_LVDS: + case I830_OUTPUT_ANALOG: + default: + minclock = 25000; + maxclock = 400000; + } + + i830xf86ValidateModesFlags(pScrn, pI830->pipeMon[pipe]->Modes, + V_INTERLACE); + i830xf86ValidateModesClocks(pScrn, pI830->pipeMon[pipe]->Modes, + &minclock, &maxclock, 1); + + i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE); + + for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL; + pMode = pMode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + + pMode->VRefresh = I830ModeVRefresh(pMode); + I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); #ifdef DEBUG_REPROBE - PrintModeline(pScrn->scrnIndex, pMode); + PrintModeline(pScrn->scrnIndex, pMode); #endif + } } + + if (old_mon != NULL && pI830->pipeMon[pipe] == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Failed to probe output on pipe %d, disabling output at next " + "mode switch\n", pipe); + if (pipe == 0) + pI830->operatingDevices &= ~0x00ff; + else + pI830->operatingDevices &= ~0xff00; + } + + if (old_mon != NULL) + i830FreeMonitor(pScrn, old_mon); } /** @@ -720,10 +847,8 @@ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) { I830Ptr pI830 = I830PTR(pScrn); - ClockRangePtr clockRanges; - int n, pipe; - DisplayModePtr saved_mode, availModes = NULL; - int saved_virtualX = 0, saved_virtualY = 0, saved_displayWidth = 0; + int pipe; + DisplayModePtr saved_mode, last; Bool pipes_reconfigured = FALSE; int originalVirtualX, originalVirtualY; @@ -738,7 +863,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) if ((pI830->operatingDevices & 0xff) == PIPE_NONE) { pI830->operatingDevices |= PIPE_CRT; I830ReprobePipeModeList(pScrn, 0); - if (pI830->pipeModes[0] == NULL) { + if (pI830->pipeMon[0] == NULL) { /* No new output found. */ pI830->operatingDevices &= ~PIPE_CRT; } else { @@ -751,7 +876,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) } else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) { pI830->operatingDevices |= PIPE_CRT << 8; I830ReprobePipeModeList(pScrn, 1); - if (pI830->pipeModes[1] == NULL) { + if (pI830->pipeMon[1] == NULL) { /* No new output found. */ pI830->operatingDevices &= ~(PIPE_CRT << 8); } else { @@ -764,20 +889,105 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) } } - /* Start by injecting the XFree86 default modes and user-configured - * modelines. XXX: This actually isn't of use if we've got any DDC, as DDC - * currently has higher priority than the validated modelist. We need to - * deal with that. - */ - I830InjectProbedModes(pScrn, &availModes, pScrn->monitor->Modes); - if (pI830->pipeModes[0] != NULL) { - I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[0]); - } - if (pI830->pipeModes[1] != NULL) { - I830InjectProbedModes(pScrn, &availModes, pI830->pipeModes[1]); + if ((pI830->pipeMon[0] == NULL || pI830->pipeMon[0]->Modes == NULL) && + (pI830->pipeMon[1] == NULL || pI830->pipeMon[1]->Modes == NULL)) + { + FatalError("No modes found on either pipe\n"); } - /* + if (first_time) { + int maxX = -1, maxY = -1; + + /* Set up a virtual size that will cover any clone mode we'd want to set + * for either of the two pipes. + */ + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + MonPtr mon = pI830->pipeMon[pipe]; + DisplayModePtr mode; + + if (mon == NULL) + continue; + + for (mode = mon->Modes; mode != NULL; mode = mode->next) { + if (mode->HDisplay > maxX) + maxX = mode->HDisplay; + if (mode->VDisplay > maxY) + maxY = mode->VDisplay; + } + } + pScrn->virtualX = maxX; + pScrn->virtualY = maxY; + pScrn->displayWidth = (maxX + 63) & ~63; + } + + I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + + /* Disable modes that are larger than the virtual size we decided on + * initially. + */ + if (!first_time) { + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + MonPtr mon = pI830->pipeMon[pipe]; + DisplayModePtr mode; + + if (mon == NULL) + continue; + + for (mode = mon->Modes; mode != NULL; mode = mode->next) + { + if (mode->HDisplay > originalVirtualX) + mode->status = MODE_VIRTUAL_X; + if (mode->VDisplay > originalVirtualY) + mode->status = MODE_VIRTUAL_Y; + } + } + } + + /* Remove the current mode from the modelist if we're re-validating, so we + * can find a new mode to map ourselves to afterwards. + */ + saved_mode = pI830->currentMode; + if (saved_mode != NULL) { + I830xf86DeleteModeFromList(&pScrn->modes, saved_mode); + } + + /* Clear any existing modes from pScrn->modes */ + while (pScrn->modes != NULL) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + + /* Set pScrn->modes to the mode list for the an arbitrary head. + * pScrn->modes should only be used for XF86VidMode now, which we don't + * care about enough to make some sort of unioned list. + */ + if (pI830->pipeMon[1] != NULL) { + I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes); + } else { + I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes); + } + if (pScrn->modes == NULL) { + FatalError("No modes found\n"); + } + + /* Don't let pScrn->modes have modes larger than the max root window size. + * We don't really care about the monitors having it, particularly since we + * eventually want randr to be able to move to those sizes. + */ + i830xf86ValidateModesSize(pScrn, pScrn->modes, + originalVirtualX, originalVirtualY, + pScrn->displayWidth); + + /* Strip out anything bad that we threw out for virtualX. */ + i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); + + /* For some reason, pScrn->modes is circular, unlike the other mode lists. + * How great is that? + */ + last = i830GetModeListTail(pScrn->modes); + last->next = pScrn->modes; + pScrn->modes->prev = last; + +#if 0 + /* XXX: do I need this any more? Maybe XF86VidMode uses it? * Set up the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. */ @@ -788,62 +998,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) clockRanges->clockIndex = -1; /* programmable */ clockRanges->interlaceAllowed = TRUE; /* XXX check this */ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ - - /* Remove the current mode from the modelist if we're re-validating, so we - * can find a new mode to map ourselves to afterwards. - */ - saved_mode = pI830->currentMode; - if (saved_mode != NULL) { - I830xf86DeleteModeFromList(&pScrn->modes, saved_mode); - } - - if (!first_time) { - saved_virtualX = pScrn->virtualX; - saved_virtualY = pScrn->virtualY; - saved_displayWidth = pScrn->displayWidth; - } - - I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); - - /* Take the pScrn->monitor->Modes we've accumulated and validate them into - * pScrn->modes. - * XXX: Should set up a scrp->monitor->DDC covering the union of the - * capabilities of our pipes. - */ - n = xf86ValidateModes(pScrn, - availModes, /* availModes */ - pScrn->display->modes, /* modeNames */ - clockRanges, /* clockRanges */ - !first_time ? &pScrn->displayWidth : NULL, /* linePitches */ - 320, /* minPitch */ - MAX_DISPLAY_PITCH, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 200, /* minHeight */ - MAX_DISPLAY_HEIGHT, /* maxHeight */ - originalVirtualX, /* virtualX maximum */ - originalVirtualY, /* virtualY maximum */ - pI830->FbMapSize, /* apertureSize */ - LOOKUP_BEST_REFRESH /* strategy */); - - /* availModes is of no more use as xf86ValidateModes has duplicated and - * saved everything it needs. - */ - while (availModes != NULL) - xf86DeleteMode(&availModes, availModes); - - if (!first_time) { - /* Restore things that may have been damaged by xf86ValidateModes. */ - pScrn->virtualX = saved_virtualX; - pScrn->virtualY = saved_virtualY; - pScrn->displayWidth = saved_displayWidth; - } - - /* Need to do xf86CrtcForModes so any user-configured modes are valid for - * non-LVDS. - */ - xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); - - xf86PruneDriverModes(pScrn); +#endif #if DEBUG_REPROBE xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n"); @@ -858,49 +1013,12 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) } while (0); #endif - /* Try to find the closest equivalent of the previous mode pointer to switch - * to. + /* Save a pointer to the previous current mode. We can't reset + * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not + * happening so we can hot-enable devices at SwitchMode. We'll notice this + * case at SwitchMode and free the saved mode. */ - if (saved_mode != NULL) { - DisplayModePtr pBestMode = NULL, pMode; + pI830->savedCurrentMode = saved_mode; - /* XXX: Is finding a matching x/y res enough? probably not. */ - for (pMode = pScrn->modes; ; pMode = pMode->next) { - if (pMode->HDisplay == saved_mode->HDisplay && - pMode->VDisplay == saved_mode->VDisplay) - { - ErrorF("found matching mode %p\n", pMode); - pBestMode = pMode; - } - if (pMode->next == pScrn->modes) - break; - } - - if (pBestMode != NULL) - xf86SwitchMode(pScrn->pScreen, pBestMode); - else - FatalError("No suitable modes after re-probe\n"); - - xfree(saved_mode->name); - xfree(saved_mode); - } - - /* If we've enabled/disabled some pipes, we need to reset cloning mode - * support. - */ - if (pipes_reconfigured) { - if ((pI830->operatingDevices & 0x00ff) && - (pI830->operatingDevices & 0xff00)) - { - pI830->Clone = TRUE; - } else { - pI830->Clone = FALSE; - } - - /* If HW cursor currently showing, reset cursor state */ - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) - pI830->CursorInfoRec->ShowCursor(pScrn); - } - - return n; + return 1; /* XXX */ } diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 16a8cd83..6f620c81 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -238,6 +238,126 @@ PrintModeline(int scrnIndex,DisplayModePtr mode) xfree(flags); } +/** + * Marks as bad any modes with unsupported flags. + * + * \param modeList doubly-linked or circular list of modes. + * \param flags flags supported by the driver. + * + * \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough? + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE)) + mode->status = MODE_NO_INTERLACE; + if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN)) + mode->status = MODE_NO_DBLESCAN; + } +} + +/** + * Marks as bad any modes extending beyond the given max X, Y, or pitch. + * + * \param modeList doubly-linked or circular list of modes. + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int maxX, int maxY, int maxPitch) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + if (maxPitch > 0 && mode->HDisplay > maxPitch) + mode->status = MODE_BAD_WIDTH; + + if (maxX > 0 && mode->HDisplay > maxX) + mode->status = MODE_VIRTUAL_X; + + if (maxY > 0 && mode->VDisplay > maxY) + mode->status = MODE_VIRTUAL_Y; + + if (mode->next == modeList) + break; + } +} + +/** + * Marks as bad any modes extending beyond outside of the given clock ranges. + * + * \param modeList doubly-linked or circular list of modes. + * \param min pointer to minimums of clock ranges + * \param max pointer to maximums of clock ranges + * \param n_ranges number of ranges. + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int *min, int *max, int n_ranges) +{ + DisplayModePtr mode; + int i; + + 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]) { + good = TRUE; + break; + } + } + if (!good) + mode->status = MODE_CLOCK_RANGE; + } +} + +/** + * Frees any modes from the list with a status other than MODE_OK. + * + * \param modeList pointer to a doubly-linked or circular list of modes. + * \param verbose determines whether the reason for mode invalidation is + * printed. + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + Bool verbose) +{ + DisplayModePtr mode; + + for (mode = *modeList; mode != NULL;) { + DisplayModePtr next = mode->next; + + if (mode->status != MODE_OK) { + if (verbose) { + char *type = ""; + if (mode->type & M_T_BUILTIN) + type = "built-in "; + else if (mode->type & M_T_DEFAULT) + type = "default "; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using %smode \"%s\" (%s)\n", type, mode->name, + xf86ModeStatusToString(mode->status)); + } + xf86DeleteMode(modeList, mode); + } + + if (next == *modeList) + break; + mode = next; + } +} + #define MODEPREFIX(name) NULL, NULL, name, MODE_OK, M_T_DEFAULT #define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index ba7d8209..86e5b060 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -34,6 +34,26 @@ I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); Bool I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); +void +i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags); + +void +i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int *min, int *max, int n_ranges); + +void +i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int maxX, int maxY, int maxPitch); + +void +i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + Bool verbose); + +void +i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags); + void PrintModeline(int scrnIndex,DisplayModePtr mode); From ce5bd108c55d2378db072617c380514a39672603 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jun 2006 14:21:49 +0200 Subject: [PATCH 117/257] Validate and insert user and VESA standard modes for DDC or configured fallback. This isn't really tested because I lack a good CRT to test against currently. --- src/i830_modes.c | 125 ++++++++++++++++++++++++++++++++++--------- src/i830_xf86Modes.c | 68 ++++++++++++++++++++++- src/i830_xf86Modes.h | 9 +++- 3 files changed, 175 insertions(+), 27 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index 74333441..6b914bc3 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -237,10 +237,10 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) { if (pMode->HDisplay == est_timings[i].hsize && pMode->VDisplay == est_timings[i].vsize && - fabs(I830ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0) + fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0) { DisplayModePtr pNew = I830DuplicateMode(pMode); - pNew->VRefresh = I830ModeVRefresh(pMode); + pNew->VRefresh = i830xf86ModeVRefresh(pMode); return pNew; } } @@ -523,16 +523,80 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) return first; } +static DisplayModePtr +i830GetModeListTail(DisplayModePtr pModeList) +{ + DisplayModePtr last; + + if (pModeList == NULL) + return NULL; + + for (last = pModeList; last->next != NULL; last = last->next) + ; + + return last; +} + /** - * Injects a list of probed modes into another mode list. + * Appends a list of modes to another mode list, without duplication. + */ +static void +i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + DisplayModePtr addModes) +{ + DisplayModePtr first = *modeList; + DisplayModePtr last = i830GetModeListTail(first); + + if (first == NULL) { + *modeList = addModes; + } else { + last->next = addModes; + addModes->prev = last; + } +} + +/** + * Duplicates every mode in the given list and returns a pointer to the first + * mode. + * + * \param modeList doubly-linked mode list + */ +static DisplayModePtr +i830DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + DisplayModePtr first = NULL, last = NULL; + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + DisplayModePtr new; + + new = I830DuplicateMode(mode); + + /* Insert pNew into modeList */ + if (last) { + last->next = new; + new->prev = last; + } else { + first = new; + new->prev = NULL; + } + new->next = NULL; + last = new; + } + + return first; +} + +/** + * Duplicates and appends a list of modes to a mode list. * * Take the doubly-linked list of modes we've probed for the device, and injects * it into the doubly-linked modeList. We don't need to filter, because the * eventual call to xf86ValidateModes will do this for us. I think. */ static int -I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, - DisplayModePtr addModes) +i830InjectModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + DisplayModePtr addModes) { DisplayModePtr last = *modeList; DisplayModePtr first = *modeList; @@ -573,25 +637,12 @@ I830InjectProbedModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, return count; } -static DisplayModePtr -i830GetModeListTail(DisplayModePtr pModeList) -{ - DisplayModePtr last; - - if (pModeList == NULL) - return NULL; - - for (last = pModeList; last->next != NULL; last = last->next) - ; - - return last; -} - static MonPtr i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) { xf86MonPtr ddc; MonPtr mon; + DisplayModePtr userModes; int i; ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus); @@ -601,7 +652,6 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) mon = xnfcalloc(1, sizeof(*mon)); mon->Modes = i830GetDDCModes(pScrn, ddc); - mon->Last = i830GetModeListTail(mon->Modes); mon->DDC = ddc; for (i = 0; i < DET_TIMINGS; i++) { @@ -624,6 +674,22 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) } } + /* Add in VESA standard and user modelines, and do additional validation + * on them beyond what pipe config will do (x/y/pitch, clocks, flags) + */ + userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); + + i830xf86ValidateModesSync(pScrn, userModes, mon); + if (ddc->features.hsize > 0 && ddc->features.vsize > 0) { + i830xf86ValidateModesSize(pScrn, userModes, ddc->features.hsize, + ddc->features.vsize, -1); + } + i830xf86PruneInvalidModes(pScrn, &userModes, TRUE); + + i830AppendModes(pScrn, &mon->Modes, userModes); + + mon->Last = i830GetModeListTail(mon->Modes); + return mon; } @@ -643,6 +709,7 @@ static MonPtr i830GetConfiguredMonitor(ScrnInfoPtr pScrn) { MonPtr mon; + DisplayModePtr userModes; mon = xnfcalloc(1, sizeof(*mon)); memcpy(mon, pScrn->monitor, sizeof(*mon)); @@ -654,6 +721,17 @@ i830GetConfiguredMonitor(ScrnInfoPtr pScrn) if (pScrn->monitor->model != NULL) mon->model = xnfstrdup(pScrn->monitor->model); + /* Add in VESA standard and user modelines, and do additional validation + * on them beyond what pipe config will do (x/y/pitch, clocks, flags) + */ + userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); + i830xf86ValidateModesSync(pScrn, userModes, mon); + i830xf86PruneInvalidModes(pScrn, &userModes, FALSE); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "prune 1\n"); + i830AppendModes(pScrn, &mon->Modes, userModes); + + mon->Last = i830GetModeListTail(mon->Modes); + return mon; } @@ -776,8 +854,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) /* The code to choose the best mode per pipe later on will require * VRefresh to be set. */ - - pMode->VRefresh = I830ModeVRefresh(pMode); + pMode->VRefresh = i830xf86ModeVRefresh(pMode); I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); #ifdef DEBUG_REPROBE PrintModeline(pScrn->scrnIndex, pMode); @@ -960,9 +1037,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) * care about enough to make some sort of unioned list. */ if (pI830->pipeMon[1] != NULL) { - I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes); + i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes); } else { - I830InjectProbedModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes); + i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes); } if (pScrn->modes == NULL) { FatalError("No modes found\n"); diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 6f620c81..09f6b342 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -44,13 +44,32 @@ * there but we still want to use. We need to come up with better API here. */ + /** - * Calculates the vertical refresh of a mode. + * Calculates the horizontal sync rate of a mode. * * Exact copy of xf86Mode.c's. */ double -I830ModeVRefresh(DisplayModePtr mode) +i830xf86ModeHSync(DisplayModePtr mode) +{ + double hsync = 0.0; + + if (mode->HSync > 0.0) + hsync = mode->HSync; + else if (mode->HTotal > 0) + hsync = (float)mode->Clock / (float)mode->HTotal; + + return hsync; +} + +/** + * Calculates the vertical refresh rate of a mode. + * + * Exact copy of xf86Mode.c's. + */ +double +i830xf86ModeVRefresh(DisplayModePtr mode) { double refresh = 0.0; @@ -290,6 +309,51 @@ i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, } } +/** + * Marks as bad any modes that aren't supported by the given monitor's + * hsync and vrefresh ranges. + * + * \param modeList doubly-linked or circular list of modes. + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, + MonPtr mon) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + Bool bad; + int i; + + bad = TRUE; + for (i = 0; i < mon->nHsync; i++) { + if (i830xf86ModeHSync(mode) >= mon->hsync[i].lo && + i830xf86ModeHSync(mode) <= mon->hsync[i].hi) + { + bad = FALSE; + } + } + if (bad) + mode->status = MODE_HSYNC; + + bad = TRUE; + for (i = 0; i < mon->nVrefresh; i++) { + if (i830xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo && + i830xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi) + { + bad = FALSE; + } + } + if (bad) + mode->status = MODE_VSYNC; + + if (mode->next == modeList) + break; + } +} + /** * Marks as bad any modes extending beyond outside of the given clock ranges. * diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 86e5b060..855aa460 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -26,7 +26,10 @@ */ double -I830ModeVRefresh(DisplayModePtr mode); +i830xf86ModeHSync(DisplayModePtr mode); + +double +i830xf86ModeVRefresh(DisplayModePtr mode); void I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); @@ -46,6 +49,10 @@ void i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, int maxX, int maxY, int maxPitch); +void +i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, + MonPtr mon); + void i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, Bool verbose); From 48f27ac62128251640a9b1ca54f63376676b47eb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 28 Jun 2006 15:07:01 +0200 Subject: [PATCH 118/257] Replace i830InjectModes with i830DuplicateModes usage. The remaining functionality of DuplicateModes was OBE, and the name was bad. --- src/i830_modes.c | 54 ++---------------------------------------------- 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index 6b914bc3..cb505230 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -587,56 +587,6 @@ i830DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) return first; } -/** - * Duplicates and appends a list of modes to a mode list. - * - * Take the doubly-linked list of modes we've probed for the device, and injects - * it into the doubly-linked modeList. We don't need to filter, because the - * eventual call to xf86ValidateModes will do this for us. I think. - */ -static int -i830InjectModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, - DisplayModePtr addModes) -{ - DisplayModePtr last = *modeList; - DisplayModePtr first = *modeList; - DisplayModePtr addMode; - int count = 0; - - for (addMode = addModes; addMode != NULL; addMode = addMode->next) { - DisplayModePtr pNew; - - pNew = I830DuplicateMode(addMode); -#if 0 - /* If the user didn't specify any modes, mark all modes as M_T_USERDEF - * so that we can cycle through them, etc. XXX: really need to? - */ - if (pScrn->display->modes[0] == NULL) { - pNew->type |= M_T_USERDEF; - } -#endif - - /* Insert pNew into modeList */ - if (last) { - last->next = pNew; - pNew->prev = last; - } else { - first = pNew; - pNew->prev = NULL; - } - pNew->next = NULL; - last = pNew; - - count++; - } - *modeList = first; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Injected %d modes detected from the monitor\n", count); - - return count; -} - static MonPtr i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) { @@ -1037,9 +987,9 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) * care about enough to make some sort of unioned list. */ if (pI830->pipeMon[1] != NULL) { - i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[1]->Modes); + pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[1]->Modes); } else { - i830InjectModes(pScrn, &pScrn->modes, pI830->pipeMon[0]->Modes); + pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[0]->Modes); } if (pScrn->modes == NULL) { FatalError("No modes found\n"); From 5d07ebdf4f23e16fb8f60eafeadc947701e7877c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Jul 2006 11:59:21 -0700 Subject: [PATCH 119/257] Only override display size with the XFree86 mode's for actual panel scaling. --- src/i830_display.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 24103cb7..e63800da 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -361,8 +361,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); - pipesrc = ((pMasterMode->HDisplay - 1) << 16) | (pMasterMode->VDisplay - 1); - dspsize = ((pMasterMode->VDisplay - 1) << 16) | (pMasterMode->HDisplay - 1); + pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); + dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); pixel_clock = pMode->Clock; if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0) { @@ -390,6 +390,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) ((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff + pI830->panel_fixed_vsyncwidth - 1) << 16); pixel_clock = pI830->panel_fixed_clock; + + if (pMasterMode->HDisplay <= pI830->panel_fixed_hactive && + pMasterMode->HDisplay <= pI830->panel_fixed_vactive) + { + pipesrc = ((pMasterMode->HDisplay - 1) << 16) | + (pMasterMode->VDisplay - 1); + dspsize = ((pMasterMode->VDisplay - 1) << 16) | + (pMasterMode->HDisplay - 1); + } } if (pMode->Clock >= 100000) From dfd7fef457c048c9f0d826e37d91453d9e1485b9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Jul 2006 12:01:57 -0700 Subject: [PATCH 120/257] Bug #7375: Don't double-free the current XF86 mode after a randr reprobe. --- src/i830_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i830_display.c b/src/i830_display.c index e63800da..b5461c2f 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -828,6 +828,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) */ xfree(pI830->savedCurrentMode->name); xfree(pI830->savedCurrentMode); + pI830->savedCurrentMode = NULL; /* If we might have enabled/disabled some pipes, we need to reset * cloning mode support. From ffa6ecc18bc54151061d9956f1d12575fc057da3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 5 Jul 2006 14:41:08 -0700 Subject: [PATCH 121/257] More fixes to "choose closest mode for the pipe" code to select correct refresh. --- src/i830_display.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index b5461c2f..d31c100b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -275,12 +275,19 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL; pScan = pScan->next) { + /* If there's an exact match, we're done. */ + if (I830ModesEqual(pScan, pMode)) { + pBest = pMode; + break; + } + /* Reject if it's larger than the desired mode. */ if (pScan->HDisplay > pMode->HDisplay || pScan->VDisplay > pMode->VDisplay) { continue; } + if (pBest == NULL) { pBest = pScan; continue; @@ -288,8 +295,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* Find if it's closer to the right size than the current best * option. */ - if (pScan->HDisplay >= pBest->HDisplay && - pScan->VDisplay >= pBest->VDisplay) + if ((pScan->HDisplay > pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) || + (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay > pBest->VDisplay)) { pBest = pScan; continue; From e1064f52b0ff69ea7937897b8c951cc3e32cd752 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 5 Jul 2006 16:00:03 -0700 Subject: [PATCH 122/257] Don't try to probe modes on an SDVO device with NULL sdvo_drv. --- src/i830_modes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index cb505230..bb097b8c 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -733,7 +733,9 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) } break; case I830_OUTPUT_SDVO: - if (outputs & PIPE_DFP) { + if (outputs & PIPE_DFP && + pI830->output[i].sdvo_drv != NULL) + { output_index = i; } break; From df333cc9a848bc2299a52a7613fe4ffdff8038a2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 7 Jul 2006 13:41:33 -0700 Subject: [PATCH 123/257] Initial add of DVO support code. Probes my sil164. This is a mostly-untested merge of airlied's work. The I2C modules are intended to be moved into the core server or a separate driver module when they're functional and we're happy with the API. --- configure.ac | 2 + src/Makefile.am | 3 +- src/ch7xxx/Makefile.am | 16 +++ src/ch7xxx/ch7xxx.c | 272 +++++++++++++++++++++++++++++++++++++ src/ch7xxx/ch7xxx.h | 33 +++++ src/ch7xxx/ch7xxx_module.c | 36 +++++ src/ch7xxx/ch7xxx_reg.h | 91 +++++++++++++ src/i2c_vid.h | 16 +++ src/i810_reg.h | 26 +++- src/i830.h | 9 +- src/i830_display.c | 43 +++++- src/i830_driver.c | 36 ++--- src/i830_dvo.c | 84 ++++++++++++ src/sil164/Makefile.am | 16 +++ src/sil164/sil164.c | 192 ++++++++++++++++++++++++++ src/sil164/sil164.h | 33 +++++ src/sil164/sil164_module.c | 36 +++++ src/sil164/sil164_reg.h | 75 ++++++++++ 18 files changed, 995 insertions(+), 24 deletions(-) create mode 100644 src/ch7xxx/Makefile.am create mode 100644 src/ch7xxx/ch7xxx.c create mode 100644 src/ch7xxx/ch7xxx.h create mode 100644 src/ch7xxx/ch7xxx_module.c create mode 100644 src/ch7xxx/ch7xxx_reg.h create mode 100644 src/i2c_vid.h create mode 100644 src/i830_dvo.c create mode 100644 src/sil164/Makefile.am create mode 100644 src/sil164/sil164.c create mode 100644 src/sil164/sil164.h create mode 100644 src/sil164/sil164_module.c create mode 100644 src/sil164/sil164_reg.h diff --git a/configure.ac b/configure.ac index deb99c21..5c9291bf 100644 --- a/configure.ac +++ b/configure.ac @@ -125,5 +125,7 @@ AC_OUTPUT([ src/Makefile src/xvmc/Makefile src/bios_reader/Makefile + src/ch7xxx/Makefile + src/sil164/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index f8aaad1d..50d0ad1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = xvmc bios_reader +SUBDIRS = xvmc bios_reader ch7xxx sil164 # this is obnoxious: # -module lets us name the module exactly how we want # -avoid-version prevents gratuitous .0.0.0 version numbers on the end @@ -54,6 +54,7 @@ i810_drv_la_SOURCES = \ i830_display.c \ i830_display.h \ i830_driver.c \ + i830_dvo.c \ i830.h \ i830_gtf.c \ i830_i2c.c \ diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am new file mode 100644 index 00000000..645ac692 --- /dev/null +++ b/src/ch7xxx/Makefile.am @@ -0,0 +1,16 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +ch7xxx_la_LTLIBRARIES = ch7xxx.la +ch7xxx_la_LDFLAGS = -module -avoid-version +ch7xxx_ladir = @moduledir@/drivers + +ch7xxx_la_SOURCES = \ + ch7xxx.c \ + ch7xxx_module.c \ + ch7xxx.h \ + ch7xxx_reg.h diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c new file mode 100644 index 00000000..77c49b53 --- /dev/null +++ b/src/ch7xxx/ch7xxx.c @@ -0,0 +1,272 @@ +/************************************************************************** + +Copyright © 2006 Dave Airlie + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" + +#include + +#include "../i2c_vid.h" +#include "ch7xxx.h" +#include "ch7xxx_reg.h" + +static void ch7xxxSaveRegs(void *d); + +static CARD8 ch7xxxFreqRegs[][7] = + { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 }, + { 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 }, + { 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } }; + + +static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch) +{ + if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) { + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch) +{ + if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) { + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/* Ch7xxxicon Image 164 driver for chip on i2c bus */ +static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr) +{ + /* this will detect the CH7xxx chip on the specified i2c bus */ + CH7xxxPtr ch7xxx; + unsigned char ch; + + xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n"); + + ch7xxx = xcalloc(1, sizeof(CH7xxxRec)); + if (ch7xxx == NULL) + return NULL; + + ch7xxx->d.DevName = "CH7xxx TMDS Controller"; + ch7xxx->d.SlaveAddr = addr; + ch7xxx->d.pI2CBus = b; + ch7xxx->d.StartTimeout = b->StartTimeout; + ch7xxx->d.BitTimeout = b->BitTimeout; + ch7xxx->d.AcknTimeout = b->AcknTimeout; + ch7xxx->d.ByteTimeout = b->ByteTimeout; + ch7xxx->d.DriverPrivate.ptr = ch7xxx; + + if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch)) + goto out; + + ErrorF("VID is %02X", ch); + if (ch!=(CH7xxx_VID & 0xFF)) + { + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr); + goto out; + } + + + if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch)) + goto out; + + ErrorF("DID is %02X", ch); + if (ch!=(CH7xxx_DID & 0xFF)) + { + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr); + goto out; + } + + + if (!xf86I2CDevInit(&(ch7xxx->d))) + { + goto out; + } + + return ch7xxx; + + out: + xfree(ch7xxx); + return NULL; +} + + +static Bool ch7xxxInit(I2CDevPtr d) +{ + CH7xxxPtr ch7xxx = CH7PTR(d); + + /* not much to do */ + return TRUE; +} + +static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode) +{ + CH7xxxPtr ch7xxx = CH7PTR(d); + + return MODE_OK; +} + +static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode) +{ + CH7xxxPtr ch7xxx = CH7PTR(d); + int ret; + unsigned char pm, idf; + unsigned char tpcp, tpd, tpf, cm; + CARD8 *freq_regs; + int i; + ErrorF("Clock is %d\n", mode->Clock); + + if (mode->Clock < 75000) + freq_regs = ch7xxxFreqRegs[0]; + else if (mode->Clock < 125000) + freq_regs = ch7xxxFreqRegs[1]; + else + freq_regs = ch7xxxFreqRegs[2]; + + for (i = 0x31; i < 0x37; i++) { + ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31]; + ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]); + } + +#if 0 + + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf); + + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm); + + if (mode->Clock < 65000) { + tpcp = 0x08; + tpd = 0x16; + tpf = 0x60; + } else { + tpcp = 0x06; + tpd = 0x26; + tpf = 0xa0; + } + + idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP); + if (mode->Flags & V_PHSYNC) + idf |= CH7xxx_IDF_HSP; + + if (mode->Flags & V_PVSYNC) + idf |= CH7xxx_IDF_HSP; + + /* setup PM Registers */ + pm &= ~CH7xxx_PM_FPD; + pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP; + + // cm |= 1; + + ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm); + ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp); + ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd); + ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf); + ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf); + ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm); + +#endif + /* don't do much */ + return; +} + +/* set the CH7xxx power state */ +static void ch7xxxPower(I2CDevPtr d, Bool On) +{ + CH7xxxPtr ch7xxx = CH7PTR(d); + int ret; + unsigned char ch; + + + ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch); + if (ret == FALSE) + return; + + xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch); + +#if 0 + ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch); + if (ret) + return; + + if (On) + ch |= CH7xxx_8_PD; + else + ch &= ~CH7xxx_8_PD; + + ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch); +#endif + return; +} + +static void ch7xxxPrintRegs(I2CDevPtr d) +{ + CH7xxxPtr ch7xxx = CH7PTR(d); + int i; + + ch7xxxSaveRegs(d); + + for (i = 0; i < CH7xxx_NUM_REGS; i++) { + if (( i % 8 ) == 0 ) + ErrorF("\n %02X: ", i); + ErrorF("%02X ", ch7xxx->ModeReg.regs[i]); + + } +} + +static void ch7xxxSaveRegs(void *d) +{ + CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d)); + int ret; + int i; + + for (i = 0; i < CH7xxx_NUM_REGS; i++) { + ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]); + if (ret == FALSE) + break; + } + + memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS); + + return; +} + +I830I2CVidOutputRec CH7xxxVidOutput = { + ch7xxxDetect, + ch7xxxInit, + ch7xxxModeValid, + ch7xxxMode, + ch7xxxPower, + ch7xxxPrintRegs, + ch7xxxSaveRegs, + NULL, +}; diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h new file mode 100644 index 00000000..5ae0ab8c --- /dev/null +++ b/src/ch7xxx/ch7xxx.h @@ -0,0 +1,33 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef CH7xxx_H +#define CH7xxx_H + +#define CH7xxx_ADDR_1 0x76 + +#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput" + +#endif diff --git a/src/ch7xxx/ch7xxx_module.c b/src/ch7xxx/ch7xxx_module.c new file mode 100644 index 00000000..19dc6cd1 --- /dev/null +++ b/src/ch7xxx/ch7xxx_module.c @@ -0,0 +1,36 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(ch7xxxSetup); + +static XF86ModuleVersionInfo ch7xxxVersRec = + { + "ch7xxx", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } + }; + +_X_EXPORT XF86ModuleData ch7xxxModuleData = { + &ch7xxxVersRec, + ch7xxxSetup, + NULL +}; + +static pointer +ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) { + return (pointer)1; +} diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h new file mode 100644 index 00000000..59de13b8 --- /dev/null +++ b/src/ch7xxx/ch7xxx_reg.h @@ -0,0 +1,91 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef CH7xxx_REG_H +#define CH7xxx_REG_H + +#define CH7xxx_REG_VID 0x4a +#define CH7xxx_REG_DID 0x4b + + +#define CH7011_VID 0x83 +#define CH7009A_VID 0x84 +#define CH7009B_VID 0x85 +#define CH7301_VID 0x95 + +#define CH7xxx_VID 0x84 +#define CH7xxx_DID 0x17 + +#define CH7xxx_NUM_REGS 0x4c + +typedef struct _CH7xxxSaveRec { + CARD8 regs[CH7xxx_NUM_REGS]; +} CH7xxxSaveRec; + +typedef struct { + I2CDevRec d; + CH7xxxSaveRec SavedReg; + CH7xxxSaveRec ModeReg; +} CH7xxxRec, *CH7xxxPtr; + +#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr)) + +#define CH7xxx_CM 0x1C +#define CH7xxx_CM_XCM (1<<0) +#define CH7xxx_CM_MCP (1<<2) +#define CH7xxx_INPUT_CLOCK 0x1D +#define CH7xxx_GPIO 0x1E +#define CH7xxx_IDF 0x1F + +#define CH7xxx_IDF_HSP (1<<3) +#define CH7xxx_IDF_VSP (1<<4) + +#define CH7301_CONNECTION_DETECT 0x20 +#define CH7301_DAC_CNTL 0x21 +#define CH7301_HOTPLUG 0x23 +#define CH7xxx_TCTL 0x31 +#define CH7xxx_TPCP 0x33 +#define CH7xxx_TPD 0x34 +#define CH7xxx_TPVT 0x35 +#define CH7xxx_TPF 0x36 +#define CH7301_TCT 0x37 +#define CH7301_TEST_PATTERN 0x48 +#define CH7xxx_PM 0x49 + +#define CH7xxx_PM_FPD (1<<0) +#define CH7301_PM_DACPD0 (1<<1) +#define CH7301_PM_DACPD1 (1<<2) +#define CH7301_PM_DACPD2 (1<<3) +#define CH7xxx_PM_DVIL (1<<6) +#define CH7xxx_PM_DVIP (1<<7) + +#define CH7301_SYNC_POLARITY 0x56 + +#define CH7301_SYNC_RGB_YUV (1<<0) +#define CH7301_SYNC_POL_DVI (1<<5) + + + +#endif diff --git a/src/i2c_vid.h b/src/i2c_vid.h new file mode 100644 index 00000000..fbf72842 --- /dev/null +++ b/src/i2c_vid.h @@ -0,0 +1,16 @@ +/* this needs to go in the server */ +#ifndef I2C_VID_H +#define I2C_VID_H + +typedef struct _I830I2CVidOutputRec { + void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr); + Bool (*Init)(I2CDevPtr d); + ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode); + void (*Mode)(I2CDevPtr d, DisplayModePtr mode); + void (*Power)(I2CDevPtr d, Bool On); + void (*PrintRegs)(I2CDevPtr d); + void (*SaveRegs)(void *d); + void (*RestoreRegs)(I2CDevPtr d); +} I830I2CVidOutputRec, *I830I2CVidOutputPtr; + +#endif diff --git a/src/i810_reg.h b/src/i810_reg.h index e8462f9d..275d858c 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -823,11 +823,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DVOA 0x61120 #define DVOB 0x61140 #define DVOC 0x61160 -#define DVO_ENABLE (1<<31) +#define DVO_ENABLE (1 << 31) +#define DVO_PIPE_B_SELECT (1 << 30) +#define DVO_PIPE_STALL_UNUSED (0 << 28) +#define DVO_PIPE_STALL (1 << 28) +#define DVO_PIPE_STALL_TV (2 << 28) +#define DVO_USE_VGA_SYNC (1 << 15) +#define DVO_DATA_ORDER_I740 (0 << 14) +#define DVO_DATA_ORDER_FP (1 << 14) +#define DVO_VSYNC_DISABLE (1 << 11) +#define DVO_HSYNC_DISABLE (1 << 10) +#define DVO_VSYNC_TRISTATE (1 << 9) +#define DVO_HSYNC_TRISTATE (1 << 8) +#define DVO_BORDER_ENABLE (1 << 7) +#define DVO_DATA_ORDER_GBRG (1 << 6) +#define DVO_DATA_ORDER_RGGB (0 << 6) +#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) +#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) +#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) +#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define DVO_BLANK_ACTIVE_HIGH (1 << 2) +#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ +#define DVO_PRESERVE_MASK (0x7<<24) #define DVOA_SRCDIM 0x61124 #define DVOB_SRCDIM 0x61144 #define DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 +#define DVO_SRCDIM_VERTICAL_SHIFT 0 #define LVDS 0x61180 # define LVDS_PORT_EN (1 << 31) diff --git a/src/i830.h b/src/i830.h index f1b97745..1123001a 100644 --- a/src/i830.h +++ b/src/i830.h @@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "common.h" #include "i830_sdvo.h" +#include "i2c_vid.h" /* I830 Video BIOS support */ @@ -182,10 +183,8 @@ struct _I830DVODriver { char *fntablename; int address; const char **symbols; -#if 0 I830I2CVidOutputRec *vid_rec; -#endif - void *devpriv; + void *dev_priv; pointer modhandle; }; @@ -593,6 +592,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* i830_dvo.c */ +Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, + struct _I830DVODriver **retdrv); + /* i830_memory.c */ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); diff --git a/src/i830_display.c b/src/i830_display.c index d31c100b..b26c09f6 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -258,8 +258,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; CARD32 pipesrc, dspsize, adpa; - CARD32 sdvob = 0, sdvoc= 0; - Bool ok, is_sdvo; + CARD32 sdvob = 0, sdvoc = 0, dvo = 0; + Bool ok, is_sdvo, is_dvo; int refclk, pixel_clock, sdvo_pixel_multiply; int outputs; DisplayModePtr pMasterMode = pMode; @@ -359,9 +359,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* We'll change how we control outputs soon, but to get the SDVO code up * and running, just check for these two possibilities. */ - is_sdvo = TRUE; + if (IS_I9XX(pI830)) { + is_sdvo = TRUE; + is_dvo = FALSE; + } else { + is_dvo = TRUE; + is_sdvo = FALSE; + } } else { is_sdvo = FALSE; + is_dvo = FALSE; } htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); @@ -471,6 +478,27 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) else dpll |= PLL_REF_INPUT_DREFCLK; + if (is_dvo) { + dpll |= DPLL_DVO_HIGH_SPEED; + + /* Save the data order, since I don't know what it should be set to. */ + dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE; + + if (pipe == 1) + dvo |= DVO_PIPE_B_SELECT; + + if (pMode->Flags & V_PHSYNC) + dvo |= DVO_HSYNC_ACTIVE_HIGH; + if (pMode->Flags & V_PVSYNC) + dvo |= DVO_VSYNC_ACTIVE_HIGH; + + if (IS_I865G(pI830)) + dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS; + + OUTREG(DVOB, dvo & ~DVO_ENABLE); + } + if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; @@ -654,6 +682,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & PIPE_CRT_ACTIVE) OUTREG(ADPA, adpa); + if (is_dvo) { + OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); + /* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */ + OUTREG(DVOB, dvo); + /* OUTREG(DVOC, dvoc); */ + } + if (is_sdvo) { OUTREG(SDVOB, sdvob); OUTREG(SDVOC, sdvoc); diff --git a/src/i830_driver.c b/src/i830_driver.c index ca87951a..501580d0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1053,6 +1053,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int i = 0; + Bool ret; /* everyone has at least a single analog output */ pI830->output[i].type = I830_OUTPUT_ANALOG; @@ -1073,6 +1074,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) pI830->output[i].type = I830_OUTPUT_DVO; I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); + ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, + &pI830->output[i].i2c_drv); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", + pI830->output[i].i2c_drv->modulename, + pI830->output[i].pI2CBus->DriverPrivate.uval); + } i++; break; case PCI_CHIP_E7221_G: @@ -1158,22 +1166,6 @@ I830DetectMonitors(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i, pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); - -#if 0 - /* if we are on an i2C bus > 0 and we see a monitor - try to - * find a controller chip - */ - if (pI830->output[i].MonInfo) { - int ret; - ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, - &pI830->output[i].i2c_drv); - if (ret==TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - pI830->output[i].i2c_drv->modulename, - pI830->output[i].pI2CBus->DriverPrivate.uval); - } - } -#endif break; case I830_OUTPUT_SDVO: if (pI830->output[i].sdvo_drv != NULL) { @@ -2769,6 +2761,12 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveSWF[16] = INREG(SWF32); for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_DVO && + pI830->output[i].i2c_drv != NULL) + { + pI830->output[i].i2c_drv->vid_rec->SaveRegs( + pI830->output[i].i2c_drv->dev_priv); + } if (pI830->output[i].type == I830_OUTPUT_SDVO && pI830->output[i].sdvo_drv != NULL) { @@ -2888,6 +2886,12 @@ RestoreHWState(ScrnInfoPtr pScrn) } for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_DVO && + pI830->output[i].i2c_drv != NULL) + { + pI830->output[i].i2c_drv->vid_rec->RestoreRegs( + pI830->output[i].i2c_drv->dev_priv); + } if (pI830->output[i].type == I830_OUTPUT_SDVO && pI830->output[i].sdvo_drv != NULL) { diff --git a/src/i830_dvo.c b/src/i830_dvo.c new file mode 100644 index 00000000..b82eaee2 --- /dev/null +++ b/src/i830_dvo.c @@ -0,0 +1,84 @@ +/************************************************************************** + +Copyright 2006 Dave Airlie + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" + +#include "sil164/sil164.h" +#include "ch7xxx/ch7xxx.h" + +static const char *SIL164Symbols[] = { + SIL164_SYMBOL_LIST +}; +static const char *CH7xxxSymbols[] = { + CH7xxx_SYMBOL_LIST +}; + +/* driver list */ +struct _I830DVODriver i830_dvo_drivers[] = +{ + { I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", + (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, + { I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", + (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL} +}; + +#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) + +Bool +I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, + struct _I830DVODriver **retdrv) +{ + int i; + void *ret_ptr; + struct _I830DVODriver *drv; + + for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) { + drv = &i830_dvo_drivers[i]; + drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); + if (drv->modhandle == NULL) + continue; + + xf86LoaderReqSymLists(drv->symbols, NULL); + + ret_ptr = NULL; + drv->vid_rec = LoaderSymbol(drv->fntablename); + if (drv->vid_rec != NULL) + ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address); + + if (ret_ptr != NULL) { + drv->dev_priv = ret_ptr; + *retdrv = drv; + return TRUE; + } + xf86UnloadSubModule(drv->modhandle); + } + return FALSE; +} diff --git a/src/sil164/Makefile.am b/src/sil164/Makefile.am new file mode 100644 index 00000000..bb84d036 --- /dev/null +++ b/src/sil164/Makefile.am @@ -0,0 +1,16 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +sil164_la_LTLIBRARIES = sil164.la +sil164_la_LDFLAGS = -module -avoid-version +sil164_ladir = @moduledir@/drivers + +sil164_la_SOURCES = \ + sil164.c \ + sil164_module.c \ + sil164.h \ + sil164_reg.h diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c new file mode 100644 index 00000000..5e35323e --- /dev/null +++ b/src/sil164/sil164.c @@ -0,0 +1,192 @@ +/************************************************************************** + +Copyright © 2006 Dave Airlie + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" + +#include "../i2c_vid.h" +#include "sil164.h" +#include "sil164_reg.h" + +static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch) +{ + if (!xf86I2CReadByte(&(sil->d), addr, ch)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch) +{ + if (!xf86I2CWriteByte(&(sil->d), addr, ch)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/* Silicon Image 164 driver for chip on i2c bus */ +static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr) +{ + /* this will detect the SIL164 chip on the specified i2c bus */ + SIL164Ptr sil; + unsigned char ch; + + xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n"); + + sil = xcalloc(1, sizeof(SIL164Rec)); + if (sil == NULL) + return NULL; + + sil->d.DevName = "SIL164 TMDS Controller"; + sil->d.SlaveAddr = addr; + sil->d.pI2CBus = b; + sil->d.StartTimeout = b->StartTimeout; + sil->d.BitTimeout = b->BitTimeout; + sil->d.AcknTimeout = b->AcknTimeout; + sil->d.ByteTimeout = b->ByteTimeout; + sil->d.DriverPrivate.ptr = sil; + + if (!sil164ReadByte(sil, SIL164_VID_LO, &ch)) + goto out; + + if (ch!=(SIL164_VID & 0xFF)) + { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + goto out; + } + + + if (!sil164ReadByte(sil, SIL164_DID_LO, &ch)) + goto out; + + if (ch!=(SIL164_DID & 0xFF)) + { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + goto out; + } + + + if (!xf86I2CDevInit(&(sil->d))) + { + goto out; + } + + return sil; + + out: + xfree(sil); + return NULL; +} + + +static Bool sil164Init(I2CDevPtr d) +{ + SIL164Ptr sil = SILPTR(d); + + /* not much to do */ + return TRUE; +} + +static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode) +{ + SIL164Ptr sil = SILPTR(d); + + return MODE_OK; +} + +static void sil164Mode(I2CDevPtr d, DisplayModePtr mode) +{ + SIL164Ptr sil = SILPTR(d); + + /* don't do much */ + return; +} + +/* set the SIL164 power state */ +static void sil164Power(I2CDevPtr d, Bool On) +{ + SIL164Ptr sil = SILPTR(d); + int ret; + unsigned char ch; + + ret = sil164ReadByte(sil, SIL164_REG8, &ch); + if (ret == FALSE) + return; + + if (On) + ch |= SIL164_8_PD; + else + ch &= ~SIL164_8_PD; + + sil164WriteByte(sil, SIL164_REG8, ch); + return; +} + +static void sil164PrintRegs(I2CDevPtr d) +{ + SIL164Ptr sil = SILPTR(d); +} + +static void sil164SaveRegs(I2CDevPtr d) +{ + SIL164Ptr sil = SILPTR(d); + + if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo)) + return; + + if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi)) + return; + + if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8)) + return; + + if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9)) + return; + + if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc)) + return; + + return; + +} + +I830I2CVidOutputRec SIL164VidOutput = { + sil164Detect, + sil164Init, + sil164ModeValid, + sil164Mode, + sil164Power, + sil164PrintRegs, + sil164SaveRegs, + NULL, +}; diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h new file mode 100644 index 00000000..ea5c4c9a --- /dev/null +++ b/src/sil164/sil164.h @@ -0,0 +1,33 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef SIL164_H +#define SIL164_H + +#define SIL164_ADDR_1 0x38 + +#define SIL164_SYMBOL_LIST "SIL164VidOutput" + +#endif diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c new file mode 100644 index 00000000..6778e6a1 --- /dev/null +++ b/src/sil164/sil164_module.c @@ -0,0 +1,36 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(sil164Setup); + +static XF86ModuleVersionInfo sil164VersRec = + { + "sil164", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } + }; + +_X_EXPORT XF86ModuleData sil164ModuleData = { + &sil164VersRec, + sil164Setup, + NULL +}; + +static pointer +sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) { + return (pointer)1; +} diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h new file mode 100644 index 00000000..879363ca --- /dev/null +++ b/src/sil164/sil164_reg.h @@ -0,0 +1,75 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef SIL164_REG_H +#define SIL164_REG_H + +#define SIL164_VID 0x0001 +#define SIL164_DID 0x0006 + +#define SIL164_VID_LO 0x00 +#define SIL164_VID_HI 0x01 +#define SIL164_DID_LO 0x02 +#define SIL164_DID_HI 0x03 +#define SIL164_REV 0x04 +#define SIL164_RSVD 0x05 +#define SIL164_FREQ_LO 0x06 +#define SIL164_FREQ_HI 0x07 + +#define SIL164_REG8 0x08 +#define SIL164_8_VEN (1<<5) +#define SIL164_8_HEN (1<<4) +#define SIL164_8_DSEL (1<<3) +#define SIL164_8_BSEL (1<<2) +#define SIL164_8_EDGE (1<<1) +#define SIL164_8_PD (1<<0) + +#define SIL164_REG9 0x09 +#define SIL164_9_VLOW (1<<7) +#define SIL164_9_MSEL_MASK (0x7<<4) +#define SIL164_9_TSEL (1<<3) +#define SIL164_9_RSEN (1<<2) +#define SIL164_9_HTPLG (1<<1) +#define SIL164_9_MDI (1<<0) + +#define SIL164_REGC 0x0c + +typedef struct _Sil164SaveRec { + CARD8 freq_lo; + CARD8 freq_hi; + CARD8 reg8; + CARD8 reg9; + CARD8 regc; +} SIL164SaveRec; + +typedef struct { + I2CDevRec d; + SIL164SaveRec SavedReg; + SIL164SaveRec ModeReg; +} SIL164Rec, *SIL164Ptr; + +#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr)) + +#endif From 5a8f6a486d79f50d2d659e615283289d59f9caa4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 8 Jul 2006 15:26:19 -0700 Subject: [PATCH 124/257] Improve output bus setup to include LVDS setup for pre-i915. --- src/i830_driver.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index ca87951a..5615f4b7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1061,30 +1061,14 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A"); i++; - /* need to add the output busses for each device - * - this function is very incomplete - * - i915GM has LVDS and TVOUT for example - */ - switch(pI830->PciInfo->chipType) { - case PCI_CHIP_I830_M: - case PCI_CHIP_845_G: - case PCI_CHIP_I855_GM: - case PCI_CHIP_I865_G: - pI830->output[i].type = I830_OUTPUT_DVO; - I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); - I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); - i++; - break; - case PCI_CHIP_E7221_G: - /* ??? */ - break; - case PCI_CHIP_I915_GM: - case PCI_CHIP_I945_GM: + if (IS_MOBILE(pI830) && !IS_I830(pI830)) { + /* Set up integrated LVDS */ pI830->output[i].type = I830_OUTPUT_LVDS; I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C"); i++; - case PCI_CHIP_I915_G: - case PCI_CHIP_I945_G: + } + + if (IS_I9XX(pI830)) { /* Set up SDVOB */ pI830->output[i].type = I830_OUTPUT_SDVO; I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); @@ -1096,7 +1080,12 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus; I830SDVOInit(pScrn, i, SDVOC); i++; - break; + } else { + /* set up DVO */ + pI830->output[i].type = I830_OUTPUT_DVO; + I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); + I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); + i++; } pI830->num_outputs = i; } From f76f94a743505da16e121992eb789c1f74eb7673 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 12:04:09 -0700 Subject: [PATCH 125/257] Supply proper NULL-terminated symbol lists to avoid crashing. --- src/ch7xxx/ch7xxx.h | 2 -- src/i830_dvo.c | 6 ++++-- src/sil164/sil164.h | 2 -- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h index 5ae0ab8c..679c5313 100644 --- a/src/ch7xxx/ch7xxx.h +++ b/src/ch7xxx/ch7xxx.h @@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define CH7xxx_ADDR_1 0x76 -#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput" - #endif diff --git a/src/i830_dvo.c b/src/i830_dvo.c index b82eaee2..242e3dd0 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -35,10 +35,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ch7xxx/ch7xxx.h" static const char *SIL164Symbols[] = { - SIL164_SYMBOL_LIST + "Sil164VidOutput", + NULL }; static const char *CH7xxxSymbols[] = { - CH7xxx_SYMBOL_LIST + "CH7xxxVidOutput", + NULL }; /* driver list */ diff --git a/src/sil164/sil164.h b/src/sil164/sil164.h index ea5c4c9a..9f823d6b 100644 --- a/src/sil164/sil164.h +++ b/src/sil164/sil164.h @@ -28,6 +28,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define SIL164_ADDR_1 0x38 -#define SIL164_SYMBOL_LIST "SIL164VidOutput" - #endif From 48ba9273ddfb36d3525e19238b94b18c56667c4d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 15:01:51 -0700 Subject: [PATCH 126/257] Fix validation when the first mode is thrown out, and print hsync in modelines. --- src/i830_xf86Modes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 09f6b342..4c5de4d9 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -249,11 +249,12 @@ PrintModeline(int scrnIndex,DisplayModePtr mode) if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); #endif xf86DrvMsg(scrnIndex, X_ERROR, - "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s\n", + "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s " + "(%.01f kHz)\n", mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, - mode->VTotal, flags); + mode->VTotal, flags, i830xf86ModeHSync(mode)); xfree(flags); } @@ -400,7 +401,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, DisplayModePtr mode; for (mode = *modeList; mode != NULL;) { - DisplayModePtr next = mode->next; + DisplayModePtr next = mode->next, first = *modeList; if (mode->status != MODE_OK) { if (verbose) { @@ -416,7 +417,7 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, xf86DeleteMode(modeList, mode); } - if (next == *modeList) + if (next == first) break; mode = next; } From 23a0ee73bce12f9e0b881af420413aeec4c0517f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 17:16:18 -0700 Subject: [PATCH 127/257] Fix modelist with a configured monitor to not begin with all unvalidated modes. --- src/i830_modes.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index bb097b8c..e1d8570b 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -1,3 +1,4 @@ + #define DEBUG_VERB 2 /* * Copyright © 2002 David Dawes @@ -659,7 +660,6 @@ static MonPtr i830GetConfiguredMonitor(ScrnInfoPtr pScrn) { MonPtr mon; - DisplayModePtr userModes; mon = xnfcalloc(1, sizeof(*mon)); memcpy(mon, pScrn->monitor, sizeof(*mon)); @@ -671,15 +671,12 @@ i830GetConfiguredMonitor(ScrnInfoPtr pScrn) if (pScrn->monitor->model != NULL) mon->model = xnfstrdup(pScrn->monitor->model); - /* Add in VESA standard and user modelines, and do additional validation + /* Use VESA standard and user modelines, and do additional validation * on them beyond what pipe config will do (x/y/pitch, clocks, flags) */ - userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); - i830xf86ValidateModesSync(pScrn, userModes, mon); - i830xf86PruneInvalidModes(pScrn, &userModes, FALSE); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "prune 1\n"); - i830AppendModes(pScrn, &mon->Modes, userModes); - + mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); + i830xf86ValidateModesSync(pScrn, mon->Modes, mon); + i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE); mon->Last = i830GetModeListTail(mon->Modes); return mon; From f5a01a2ef02125611d5fb74c20d53d52e544701a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 17:17:51 -0700 Subject: [PATCH 128/257] Make DVO code light up my sil164-based DVI output, when already set up by BIOS. --- src/i830_display.c | 20 +++++++++----------- src/i830_driver.c | 18 ++++++------------ src/i830_modes.c | 5 +++++ 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index b26c09f6..7b96b3a7 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -482,8 +482,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= DPLL_DVO_HIGH_SPEED; /* Save the data order, since I don't know what it should be set to. */ - dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); - dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE; + dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + dvo |= DVO_ENABLE; + dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; if (pipe == 1) dvo |= DVO_PIPE_B_SELECT; @@ -493,10 +494,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (pMode->Flags & V_PVSYNC) dvo |= DVO_VSYNC_ACTIVE_HIGH; - if (IS_I865G(pI830)) - dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS; - - OUTREG(DVOB, dvo & ~DVO_ENABLE); + OUTREG(DVOC, dvo & ~DVO_ENABLE); } if (is_sdvo) { @@ -683,12 +681,12 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(ADPA, adpa); if (is_dvo) { - OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ + OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); - /* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | - (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */ - OUTREG(DVOB, dvo); - /* OUTREG(DVOC, dvoc); */ + /*OUTREG(DVOB, dvo);*/ + OUTREG(DVOC, dvo); } if (is_sdvo) { diff --git a/src/i830_driver.c b/src/i830_driver.c index 0f472b1c..7815c574 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1087,18 +1087,12 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); - /* if we are on an i2C bus > 0 and we see a monitor - try to - * find a controller chip - */ - if (pI830->output[i].MonInfo) { - int ret; - ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, - &pI830->output[i].i2c_drv); - if (ret==TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - pI830->output[i].i2c_drv->modulename, - pI830->output[i].pI2CBus->DriverPrivate.uval); - } + ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, + &pI830->output[i].i2c_drv); + if (ret == TRUE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", + pI830->output[i].i2c_drv->modulename, + pI830->output[i].pI2CBus->DriverPrivate.uval); } i++; diff --git a/src/i830_modes.c b/src/i830_modes.c index e1d8570b..1a572d16 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -729,6 +729,11 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) output_index = i; } break; + case I830_OUTPUT_DVO: + if (outputs & PIPE_DFP && pI830->output[i].i2c_drv != NULL) { + output_index = i; + } + break; case I830_OUTPUT_SDVO: if (outputs & PIPE_DFP && pI830->output[i].sdvo_drv != NULL) From 8d7987d00242020d29a2574ac0c8b6e55cc22112 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 17:34:57 -0700 Subject: [PATCH 129/257] Move to 4-space indents in sil164. --- src/sil164/sil164.c | 241 +++++++++++++++++++------------------ src/sil164/sil164_module.c | 18 +-- src/sil164/sil164_reg.h | 17 +-- 3 files changed, 146 insertions(+), 130 deletions(-) diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c index 5e35323e..77a7a00e 100644 --- a/src/sil164/sil164.c +++ b/src/sil164/sil164.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 -*- */ /************************************************************************** Copyright © 2006 Dave Airlie @@ -36,157 +37,169 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sil164.h" #include "sil164_reg.h" -static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch) +static Bool +sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch) { - if (!xf86I2CReadByte(&(sil->d), addr, ch)) { - xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr); - return FALSE; - } - return TRUE; + if (!xf86I2CReadByte(&(sil->d), addr, ch)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + return FALSE; + } + return TRUE; } -static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch) +static Bool +sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch) { - if (!xf86I2CWriteByte(&(sil->d), addr, ch)) { - xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr); - return FALSE; - } - return TRUE; + if (!xf86I2CWriteByte(&(sil->d), addr, ch)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + return FALSE; + } + return TRUE; } /* Silicon Image 164 driver for chip on i2c bus */ -static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr) +static void * +sil164Detect(I2CBusPtr b, I2CSlaveAddr addr) { - /* this will detect the SIL164 chip on the specified i2c bus */ - SIL164Ptr sil; - unsigned char ch; + /* this will detect the SIL164 chip on the specified i2c bus */ + SIL164Ptr sil; + unsigned char ch; - xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n"); - - sil = xcalloc(1, sizeof(SIL164Rec)); - if (sil == NULL) + xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n"); + + sil = xcalloc(1, sizeof(SIL164Rec)); + if (sil == NULL) + return NULL; + + sil->d.DevName = "SIL164 TMDS Controller"; + sil->d.SlaveAddr = addr; + sil->d.pI2CBus = b; + sil->d.StartTimeout = b->StartTimeout; + sil->d.BitTimeout = b->BitTimeout; + sil->d.AcknTimeout = b->AcknTimeout; + sil->d.ByteTimeout = b->ByteTimeout; + sil->d.DriverPrivate.ptr = sil; + + if (!sil164ReadByte(sil, SIL164_VID_LO, &ch)) + goto out; + + if (ch!=(SIL164_VID & 0xFF)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, + "sil164 not detected got %d: from %s Slave %d.\n", + ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + goto out; + } + + if (!sil164ReadByte(sil, SIL164_DID_LO, &ch)) + goto out; + + if (ch!=(SIL164_DID & 0xFF)) { + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, + "sil164 not detected got %d: from %s Slave %d.\n", + ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); + goto out; + } + + if (!xf86I2CDevInit(&(sil->d))) { + goto out; + } + + return sil; + +out: + xfree(sil); return NULL; - - sil->d.DevName = "SIL164 TMDS Controller"; - sil->d.SlaveAddr = addr; - sil->d.pI2CBus = b; - sil->d.StartTimeout = b->StartTimeout; - sil->d.BitTimeout = b->BitTimeout; - sil->d.AcknTimeout = b->AcknTimeout; - sil->d.ByteTimeout = b->ByteTimeout; - sil->d.DriverPrivate.ptr = sil; - - if (!sil164ReadByte(sil, SIL164_VID_LO, &ch)) - goto out; - - if (ch!=(SIL164_VID & 0xFF)) - { - xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); - goto out; - } - - - if (!sil164ReadByte(sil, SIL164_DID_LO, &ch)) - goto out; - - if (ch!=(SIL164_DID & 0xFF)) - { - xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); - goto out; - } - - - if (!xf86I2CDevInit(&(sil->d))) - { - goto out; - } - - return sil; - - out: - xfree(sil); - return NULL; } -static Bool sil164Init(I2CDevPtr d) +static Bool +sil164Init(I2CDevPtr d) { - SIL164Ptr sil = SILPTR(d); + SIL164Ptr sil = SILPTR(d); - /* not much to do */ - return TRUE; + /* not much to do */ + return TRUE; } -static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode) +static ModeStatus +sil164ModeValid(I2CDevPtr d, DisplayModePtr mode) { - SIL164Ptr sil = SILPTR(d); - - return MODE_OK; + SIL164Ptr sil = SILPTR(d); + + return MODE_OK; } -static void sil164Mode(I2CDevPtr d, DisplayModePtr mode) +static void +sil164Mode(I2CDevPtr d, DisplayModePtr mode) { - SIL164Ptr sil = SILPTR(d); + SIL164Ptr sil = SILPTR(d); - /* don't do much */ - return; + /* don't do much */ + return; } /* set the SIL164 power state */ -static void sil164Power(I2CDevPtr d, Bool On) +static void +sil164Power(I2CDevPtr d, Bool On) { - SIL164Ptr sil = SILPTR(d); - int ret; - unsigned char ch; - - ret = sil164ReadByte(sil, SIL164_REG8, &ch); - if (ret == FALSE) + SIL164Ptr sil = SILPTR(d); + int ret; + unsigned char ch; + + ret = sil164ReadByte(sil, SIL164_REG8, &ch); + if (ret == FALSE) + return; + + if (On) + ch |= SIL164_8_PD; + else + ch &= ~SIL164_8_PD; + + sil164WriteByte(sil, SIL164_REG8, ch); + return; - - if (On) - ch |= SIL164_8_PD; - else - ch &= ~SIL164_8_PD; - - sil164WriteByte(sil, SIL164_REG8, ch); - return; } -static void sil164PrintRegs(I2CDevPtr d) +static void +sil164PrintRegs(I2CDevPtr d) { - SIL164Ptr sil = SILPTR(d); + SIL164Ptr sil = SILPTR(d); } -static void sil164SaveRegs(I2CDevPtr d) +static void +sil164SaveRegs(I2CDevPtr d) { - SIL164Ptr sil = SILPTR(d); - - if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo)) - return; + SIL164Ptr sil = SILPTR(d); - if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi)) - return; + if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo)) + return; + + if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi)) + return; + + if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8)) + return; + + if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9)) + return; + + if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc)) + return; - if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8)) return; - - if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9)) - return; - - if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc)) - return; - - return; - } I830I2CVidOutputRec SIL164VidOutput = { - sil164Detect, - sil164Init, - sil164ModeValid, - sil164Mode, - sil164Power, - sil164PrintRegs, - sil164SaveRegs, - NULL, + sil164Detect, + sil164Init, + sil164ModeValid, + sil164Mode, + sil164Power, + sil164PrintRegs, + sil164SaveRegs, + NULL, }; diff --git a/src/sil164/sil164_module.c b/src/sil164/sil164_module.c index 6778e6a1..d3bda819 100644 --- a/src/sil164/sil164_module.c +++ b/src/sil164/sil164_module.c @@ -1,3 +1,5 @@ +/* -*- c-basic-offset: 4 -*- */ + #ifdef HAVE_XORG_CONFIG_H #include #endif @@ -10,8 +12,7 @@ static MODULESETUPPROTO(sil164Setup); -static XF86ModuleVersionInfo sil164VersRec = - { +static XF86ModuleVersionInfo sil164VersRec = { "sil164", MODULEVENDORSTRING, MODINFOSTRING1, @@ -22,15 +23,16 @@ static XF86ModuleVersionInfo sil164VersRec = ABI_VIDEODRV_VERSION, MOD_CLASS_NONE, { 0,0,0,0 } - }; +}; _X_EXPORT XF86ModuleData sil164ModuleData = { - &sil164VersRec, - sil164Setup, - NULL + &sil164VersRec, + sil164Setup, + NULL }; static pointer -sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) { - return (pointer)1; +sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (pointer)1; } diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h index 879363ca..dc2abba6 100644 --- a/src/sil164/sil164_reg.h +++ b/src/sil164/sil164_reg.h @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 -*- */ /************************************************************************** Copyright 2006 Dave Airlie @@ -57,17 +58,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define SIL164_REGC 0x0c typedef struct _Sil164SaveRec { - CARD8 freq_lo; - CARD8 freq_hi; - CARD8 reg8; - CARD8 reg9; - CARD8 regc; + CARD8 freq_lo; + CARD8 freq_hi; + CARD8 reg8; + CARD8 reg9; + CARD8 regc; } SIL164SaveRec; typedef struct { - I2CDevRec d; - SIL164SaveRec SavedReg; - SIL164SaveRec ModeReg; + I2CDevRec d; + SIL164SaveRec SavedReg; + SIL164SaveRec ModeReg; } SIL164Rec, *SIL164Ptr; #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr)) From 426d26ea446d646fa8f561ea0e03c8e4a2c0c315 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 18:19:51 -0700 Subject: [PATCH 130/257] Fix prototype for SaveRegs. --- src/i2c_vid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i2c_vid.h b/src/i2c_vid.h index fbf72842..5a743d29 100644 --- a/src/i2c_vid.h +++ b/src/i2c_vid.h @@ -9,7 +9,7 @@ typedef struct _I830I2CVidOutputRec { void (*Mode)(I2CDevPtr d, DisplayModePtr mode); void (*Power)(I2CDevPtr d, Bool On); void (*PrintRegs)(I2CDevPtr d); - void (*SaveRegs)(void *d); + void (*SaveRegs)(I2CDevPtr d); void (*RestoreRegs)(I2CDevPtr d); } I830I2CVidOutputRec, *I830I2CVidOutputPtr; From d75490701cdbf2ab6eab82eaa078790a5fe0aea0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 18:21:04 -0700 Subject: [PATCH 131/257] Hook up SiI164 mode setting (just a matter of turning the chip on). Also adds register dumping in case this turns out to not be enough, and fixes a couple of prototypes. --- src/i830_display.c | 11 +++++++++-- src/sil164/sil164.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 7b96b3a7..e8c8509b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 -*- */ /* * Copyright © 2006 Intel Corporation * @@ -843,8 +844,14 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].sdvo_drv) - I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode); + struct _I830OutputRec *output = &pI830->output[i]; + + if (output->sdvo_drv) + I830SDVOPreSetMode(output->sdvo_drv, pMode); + + if (output->i2c_drv != NULL) + output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, + pMode); } if (pI830->planeEnabled[0]) { diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c index 77a7a00e..93640ae8 100644 --- a/src/sil164/sil164.c +++ b/src/sil164/sil164.c @@ -37,8 +37,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sil164.h" #include "sil164_reg.h" +static void +sil164PrintRegs(I2CDevPtr d); +static void +sil164Power(I2CDevPtr d, Bool On); + static Bool -sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch) +sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch) { if (!xf86I2CReadByte(&(sil->d), addr, ch)) { xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, @@ -50,7 +55,7 @@ sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch) } static Bool -sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch) +sil164WriteByte(SIL164Ptr sil, int addr, CARD8 ch) { if (!xf86I2CWriteByte(&(sil->d), addr, ch)) { xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, @@ -138,6 +143,15 @@ sil164Mode(I2CDevPtr d, DisplayModePtr mode) { SIL164Ptr sil = SILPTR(d); + sil164Power(d, TRUE); + sil164PrintRegs(d); + + /* recommended programming sequence from doc */ + /*sil164WriteByte(sil, 0x08, 0x30); + sil164WriteByte(sil, 0x09, 0x00); + sil164WriteByte(sil, 0x0a, 0x90); + sil164WriteByte(sil, 0x0c, 0x89); + sil164WriteByte(sil, 0x08, 0x31);*/ /* don't do much */ return; } @@ -168,6 +182,20 @@ static void sil164PrintRegs(I2CDevPtr d) { SIL164Ptr sil = SILPTR(d); + CARD8 val; + + sil164ReadByte(sil, SIL164_FREQ_LO, &val); + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n", + val); + sil164ReadByte(sil, SIL164_FREQ_HI, &val); + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n", + val); + sil164ReadByte(sil, SIL164_REG8, &val); + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val); + sil164ReadByte(sil, SIL164_REG9, &val); + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val); + sil164ReadByte(sil, SIL164_REGC, &val); + xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val); } static void From b912bf5673e38e03b0b25c2f5d05fe7e26994ba1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jul 2006 18:35:20 -0700 Subject: [PATCH 132/257] Clean up warnings in sil164 module. --- src/sil164/sil164.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c index 93640ae8..a2742621 100644 --- a/src/sil164/sil164.c +++ b/src/sil164/sil164.c @@ -124,8 +124,6 @@ out: static Bool sil164Init(I2CDevPtr d) { - SIL164Ptr sil = SILPTR(d); - /* not much to do */ return TRUE; } @@ -133,16 +131,12 @@ sil164Init(I2CDevPtr d) static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode) { - SIL164Ptr sil = SILPTR(d); - return MODE_OK; } static void sil164Mode(I2CDevPtr d, DisplayModePtr mode) { - SIL164Ptr sil = SILPTR(d); - sil164Power(d, TRUE); sil164PrintRegs(d); From 7068468ac1951bfca0071bb9b1a99df4f37368a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=5Cu0161=20Hejtm=C3=A1nek?= Date: Tue, 11 Jul 2006 09:51:26 -0700 Subject: [PATCH 133/257] Add support for adjusting saturation value of overlay video. --- src/i830_video.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index a608a7e3..05f7f462 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -116,7 +116,7 @@ static void I830BlockHandler(int, pointer, pointer, pointer); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) -static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer; +static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer; static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH 1920 @@ -278,11 +278,12 @@ static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 1, "XV_PIPE"} }; -#define NUM_ATTRIBUTES 4 +#define NUM_ATTRIBUTES 5 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"}, {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} }; @@ -373,6 +374,7 @@ typedef struct { int brightness; int contrast; + int saturation; int pipe; int doubleBuffer; @@ -500,7 +502,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->SWIDTHSW = 0; overlay->SHEIGHT = 0; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - overlay->OCLRC1 = 0x00000080; /* saturation: bypass */ + overlay->OCLRC1 = pPriv->saturation; overlay->AWINPOS = 0; overlay->AWINSZ = 0; overlay->FASTHSCALE = 0; @@ -709,6 +711,7 @@ I830SetupImageVideo(ScreenPtr pScreen) pPriv->videoStatus = 0; pPriv->brightness = 0; pPriv->contrast = 64; + pPriv->saturation = 128; pPriv->pipe = pI830->pipe; /* default to current pipe */ pPriv->linear = NULL; pPriv->currentBuf = 0; @@ -744,6 +747,7 @@ I830SetupImageVideo(ScreenPtr pScreen) xvColorKey = MAKE_ATOM("XV_COLORKEY"); xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ @@ -863,6 +867,16 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, OVERLAY_UPDATE; #if 1 OVERLAY_OFF; +#endif + } else if (attribute == xvSaturation) { + if ((value < 0) || (value > 1023)) + return BadValue; + pPriv->saturation = value; + overlay->OCLRC1 = pPriv->saturation; + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; #endif } else if (pI830->Clone && attribute == xvPipe) { if ((value < 0) || (value > 1)) @@ -953,6 +967,8 @@ I830GetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->brightness; } else if (attribute == xvContrast) { *value = pPriv->contrast; + } else if (attribute == xvSaturation) { + *value = pPriv->saturation; } else if (pI830->Clone && attribute == xvPipe) { *value = pPriv->pipe; } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { From f9499a68da0ce459fed0b29b998678fd81898a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=5Cu0161=20Hejtm=C3=A1nek?= Date: Tue, 11 Jul 2006 10:13:18 -0700 Subject: [PATCH 134/257] Make gamma settings apply to the cursor as well, and fix clone-mode gamma. --- src/i830.h | 2 + src/i830_cursor.c | 20 +++++----- src/i830_display.c | 8 +++- src/i830_driver.c | 94 ++++++++++++++++++++-------------------------- 4 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/i830.h b/src/i830.h index 1123001a..3a939312 100644 --- a/src/i830.h +++ b/src/i830.h @@ -231,6 +231,8 @@ typedef struct _I830Rec { */ DisplayModePtr savedCurrentMode; + Bool gammaEnabled[MAX_DISPLAY_PIPES]; + Bool Clone; int CloneRefresh; int CloneHDisplay; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 79d950e5..b3736490 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -93,8 +93,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn) MCURSOR_PIPE_SELECT); temp |= CURSOR_MODE_DISABLE; temp |= (pI830->pipe << 28); -/* if(pI830->CursorIsARGB) - temp |= MCURSOR_GAMMA_ENABLE; */ /* Need to set control, then address. */ OUTREG(CURSOR_A_CONTROL, temp); if (pI830->CursorIsARGB) @@ -115,8 +113,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn) temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE | CURSOR_ENABLE | CURSOR_STRIDE_MASK); temp |= (CURSOR_FORMAT_3C); -/* if (pI830->CursorIsARGB) - temp |= CURSOR_GAMMA_ENABLE;*/ /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ @@ -484,9 +480,11 @@ I830ShowCursor(ScrnInfoPtr pScrn) if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); - if (pI830->CursorIsARGB) - temp |= CURSOR_MODE_64_ARGB_AX /* | MCURSOR_GAMMA_ENABLE*/; - else + if (pI830->CursorIsARGB) { + temp |= CURSOR_MODE_64_ARGB_AX; + if (pI830->gammaEnabled[pI830->pipe]) + temp |= MCURSOR_GAMMA_ENABLE; + } else temp |= CURSOR_MODE_64_4C_AX; temp |= (pI830->pipe << 28); /* Connect to correct pipe */ /* Need to set mode, then address. */ @@ -508,9 +506,11 @@ I830ShowCursor(ScrnInfoPtr pScrn) temp = INREG(CURSOR_CONTROL); temp &= ~(CURSOR_FORMAT_MASK); temp |= CURSOR_ENABLE; - if (pI830->CursorIsARGB) - temp |= CURSOR_FORMAT_ARGB /* | CURSOR_GAMMA_ENABLE*/; - else + if (pI830->CursorIsARGB) { + temp |= CURSOR_FORMAT_ARGB; + if (pI830->gammaEnabled[pI830->pipe]) + temp |= CURSOR_GAMMA_ENABLE; + } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); if (pI830->CursorIsARGB) diff --git a/src/i830_display.c b/src/i830_display.c index e8c8509b..1496c3a3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -476,7 +476,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE)) dpll |= PLL_REF_INPUT_TVCLKINBC; - else + else if (outputs & (PIPE_LCD_ACTIVE)) + dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; + else dpll |= PLL_REF_INPUT_DREFCLK; if (is_dvo) { @@ -556,6 +558,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) FatalError("unknown display bpp\n"); } + if (pI830->gammaEnabled[pipe]) { + dspcntr |= DISPPLANE_GAMMA_ENABLE; + } + if (is_sdvo) adpa = ADPA_DAC_DISABLE; else diff --git a/src/i830_driver.c b/src/i830_driver.c index 7815c574..396685a0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -870,8 +870,6 @@ I830UnmapMem(ScrnInfoPtr pScrn) return TRUE; } -static CARD32 val8[256]; - static void I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) @@ -882,33 +880,41 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, CARD32 val, temp; int palreg; int dspreg, dspbase; + int p; DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - if (pI830->pipe == 0) { - palreg = PALETTE_A; - dspreg = DSPACNTR; - dspbase = DSPABASE; - } else { - palreg = PALETTE_B; - dspreg = DSPBCNTR; - dspbase = DSPBBASE; - } + for(p=0; p < pI830->availablePipes; p++) { - /* To ensure gamma is enabled we need to turn off and on the plane */ - temp = INREG(dspreg); - OUTREG(dspreg, temp & ~(1<<31)); - OUTREG(dspbase, INREG(dspbase)); - OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); - OUTREG(dspbase, INREG(dspbase)); + if (p == 0) { + palreg = PALETTE_A; + dspreg = DSPACNTR; + dspbase = DSPABASE; + } else { + palreg = PALETTE_B; + dspreg = DSPBCNTR; + dspbase = DSPBBASE; + } - /* It seems that an initial read is needed. */ - temp = INREG(palreg); + if (pI830->planeEnabled[p] == 0) + continue; - switch(pScrn->depth) { - case 15: - for (i = 0; i < numColors; i++) { + pI830->gammaEnabled[p] = 1; + + /* To ensure gamma is enabled we need to turn off and on the plane */ + temp = INREG(dspreg); + OUTREG(dspreg, temp & ~(1<<31)); + OUTREG(dspbase, INREG(dspbase)); + OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); + OUTREG(dspbase, INREG(dspbase)); + + /* It seems that an initial read is needed. */ + temp = INREG(palreg); + + switch(pScrn->depth) { + case 15: + for (i = 0; i < numColors; i++) { index = indices[i]; r = colors[index].red; g = colors[index].green; @@ -917,10 +923,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, for (j = 0; j < 8; j++) { OUTREG(palreg + index * 32 + (j * 4), val); } - } + } break; - case 16: - for (i = 0; i < numColors; i++) { + case 16: + for (i = 0; i < numColors; i++) { index = indices[i]; r = colors[index / 2].red; g = colors[index].green; @@ -943,42 +949,24 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, OUTREG(palreg + index * 32 + 8, val); OUTREG(palreg + index * 32 + 12, val); } - } - break; - default: -#if 1 - /* Dual head 8bpp modes seem to squish the primary's cmap - reload */ - if (I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) && - pScrn->depth == 8) { - for(i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index].red; - g = colors[index].green; - b = colors[index].blue; - val8[index] = (r << 16) | (g << 8) | b; } - } -#endif - for(i = 0; i < numColors; i++) { + break; + default: + for(i = 0; i < numColors; i++) { index = indices[i]; r = colors[index].red; g = colors[index].green; b = colors[index].blue; val = (r << 16) | (g << 8) | b; OUTREG(palreg + index * 4, val); -#if 1 - /* Dual head 8bpp modes seem to squish the primary's cmap - reload */ - if (!I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) && - pScrn->depth == 8) { - if (palreg == PALETTE_A) - OUTREG(PALETTE_B + index * 4, val8[index]); - else - OUTREG(PALETTE_A + index * 4, val8[index]); - } -#endif - } - break; + } + break; + } } + + /* Enable gamma for Cursor if ARGB */ + if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) + pI830->CursorInfoRec->ShowCursor(pScrn); } #if 0 From 5a2e04bd1b700a8a6e26136b8831ef5e4d11b565 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 11 Jul 2006 10:21:51 -0700 Subject: [PATCH 135/257] Fix crash with DDC when there are no user modes to add. --- src/i830_modes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/i830_modes.c b/src/i830_modes.c index 1a572d16..ac25864c 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 -*- */ #define DEBUG_VERB 2 /* @@ -548,6 +549,9 @@ i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, DisplayModePtr first = *modeList; DisplayModePtr last = i830GetModeListTail(first); + if (addModes == NULL) + return; + if (first == NULL) { *modeList = addModes; } else { From b65f18b05a5fba506b71293b495cab95197037ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 11 Jul 2006 13:29:57 -0700 Subject: [PATCH 136/257] Bug #7443: Respect the user's Modes configuration, and make it more useful. Now, mode names generated by DDC get names of the form "WIDTHxHEIGHTxREFRESH". The matching for user Modes lines takes the user Modes as the prefix that needs to match, rather than an exact string match or "WIDTHxHEIGHT" match. So one can, for example, specify "1024x768" to get any old 1024x768, or 1024x768x60 to get one of the modes named 1024x768x60. --- src/i830_gtf.c | 5 ++-- src/i830_modes.c | 19 ++++++++++----- src/i830_xf86Modes.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ src/i830_xf86Modes.h | 6 +++++ 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/i830_gtf.c b/src/i830_gtf.c index 2eff46a9..663a2f45 100644 --- a/src/i830_gtf.c +++ b/src/i830_gtf.c @@ -45,6 +45,7 @@ #include "vbe.h" #include "vbeModes.h" #include "i830.h" +#include "i830_xf86Modes.h" #include @@ -97,7 +98,6 @@ i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins) float h_sync; float h_front_porch; float v_odd_front_porch_lines; - char modename[20]; DisplayModePtr m; m = xnfcalloc(sizeof(DisplayModeRec), 1); @@ -349,8 +349,7 @@ i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins) m->HSync = h_freq; m->VRefresh = v_frame_rate /* freq */; - snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay); - m->name = xnfstrdup(modename); + i830xf86SetModeDefaultName(m); return (m); } diff --git a/src/i830_modes.c b/src/i830_modes.c index ac25864c..90bd0931 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -176,7 +176,11 @@ I830DuplicateMode(DisplayModePtr pMode) *pNew = *pMode; pNew->next = NULL; pNew->prev = NULL; - pNew->name = xnfstrdup(pMode->name); + if (pNew->name == NULL) { + i830xf86SetModeDefaultName(pMode); + } else { + pNew->name = xnfstrdup(pMode->name); + } return pNew; } @@ -242,6 +246,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0) { DisplayModePtr pNew = I830DuplicateMode(pMode); + i830xf86SetModeDefaultName(pNew); pNew->VRefresh = i830xf86ModeVRefresh(pMode); return pNew; } @@ -257,7 +262,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) DisplayModePtr first = NULL; int count = 0; int j, tmp; - char stmp[32]; if (ddc == NULL) return NULL; @@ -276,10 +280,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) new->HDisplay = d_timings->h_active; new->VDisplay = d_timings->v_active; - sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - new->HTotal = new->HDisplay + d_timings->h_blanking; new->HSyncStart = new->HDisplay + d_timings->h_sync_off; new->HSyncEnd = new->HSyncStart + d_timings->h_sync_width; @@ -291,6 +291,8 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) new->status = MODE_OK; new->type = M_T_DEFAULT; + i830xf86SetModeDefaultName(new); + if (d_timings->sync == 3) { switch (d_timings->misc) { case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break; @@ -806,6 +808,11 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE); + /* silently prune modes down to ones matching the user's configuration. + */ + i830xf86ValidateModesUserConfig(pScrn, pI830->pipeMon[pipe]->Modes); + i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, FALSE); + for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL; pMode = pMode->next) { diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 4c5de4d9..8c34053c 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 -*- */ /* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */ /* @@ -87,6 +88,22 @@ i830xf86ModeVRefresh(DisplayModePtr mode) return refresh; } +/** + * Sets a default mode name of xx on a mode. + * + * The refresh rate doesn't contain decimals, as that's expected to be + * unimportant from the user's perspective for non-custom modelines. + */ +void +i830xf86SetModeDefaultName(DisplayModePtr mode) +{ + if (mode->name != NULL) + xfree(mode->name); + + mode->name = XNFprintf("%dx%dx%.0f", mode->HDisplay, mode->VDisplay, + i830xf86ModeVRefresh(mode)); +} + /* * I830xf86SetModeCrtc * @@ -385,6 +402,45 @@ i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, } } +/** + * If the user has specified a set of mode names to use, mark as bad any modes + * not listed. + * + * The user mode names specified are prefixes to names of modes, so "1024x768" + * will match modes named "1024x768", "1024x768x75", "1024x768-good", but + * "1024x768x75" would only match "1024x768x75" from that list. + * + * MODE_BAD is used as the rejection flag, for lack of a better flag. + * + * \param modeList doubly-linked or circular list of modes. + * + * This is not in xf86Modes.c, but would be part of the proposed new API. + */ +void +i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + DisplayModePtr mode; + + if (pScrn->display->modes[0] == NULL) + return; + + for (mode = modeList; mode != NULL; mode = mode->next) { + int i; + Bool good = FALSE; + + for (i = 0; pScrn->display->modes[i] != NULL; i++) { + if (strncmp(pScrn->display->modes[i], mode->name, + strlen(pScrn->display->modes[i])) == 0) { + good = TRUE; + break; + } + } + if (!good) + mode->status = MODE_BAD; + } +} + + /** * Frees any modes from the list with a status other than MODE_OK. * diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 855aa460..0cba8874 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -31,6 +31,9 @@ i830xf86ModeHSync(DisplayModePtr mode); double i830xf86ModeVRefresh(DisplayModePtr mode); +void +i830xf86SetModeDefaultName(DisplayModePtr mode); + void I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); @@ -61,6 +64,9 @@ void i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, int flags); +void +i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList); + void PrintModeline(int scrnIndex,DisplayModePtr mode); From 05bcbadd130524694e11e372d54cb419cea566cc Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 11 Jul 2006 14:05:38 -0700 Subject: [PATCH 137/257] Avoid NULL dereference if cursor position changes during a mode change. --- src/i830_cursor.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/i830_cursor.c b/src/i830_cursor.c index b3736490..2cb069cc 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -1,4 +1,4 @@ - +/* -*- c-basic-offset: 3 -*- */ /************************************************************************** Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. @@ -398,9 +398,15 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= pScrn->frameX0; y -= pScrn->frameY0; - /* Clamp the cursor position to the visible screen area */ - if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1; - if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1; + /* Clamp the cursor position to the visible screen area. Ignore this if we + * are doing motion (with SilkenMouse) while the currentMode being changed. + */ + if (pScrn->currentMode != NULL) { + if (x >= pScrn->currentMode->HDisplay) + x = pScrn->currentMode->HDisplay - 1; + if (y >= pScrn->currentMode->VDisplay) + y = pScrn->currentMode->VDisplay - 1; + } if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1; if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1; From 22843830ebdd14247aa76d19f89494a56e2ac887 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 13 Jul 2006 17:20:17 -0400 Subject: [PATCH 138/257] Fix a thinko; would only inject the FP native mode if a mode list was already found, which is never the case when there's no xorg.conf. --- src/i830_modes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index 90bd0931..bf480a6a 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -493,7 +493,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) /* If the user hasn't specified modes, add the native mode */ if (!count) { new = i830FPNativeMode(pScrn); - if (first) { + if (new) { I830xf86SortModes(new, &first, &last); count = 1; } From de470aaf5c47f4d2b0f477ac678039ef43af773d Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 13 Jul 2006 19:10:11 -0400 Subject: [PATCH 139/257] In I830xf86SortModes, catch cases where two modes are equal in only one dimension, by comparing the areas of the modes. Otherwise, 800x600 would sort before 1024x600 if it was added later. --- src/i830_modes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i830_modes.c b/src/i830_modes.c index bf480a6a..1965c390 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -198,6 +198,7 @@ I830xf86SortModes(DisplayModePtr new, DisplayModePtr *first, while (p) { if (((new->HDisplay < p->HDisplay) && (new->VDisplay < p->VDisplay)) || + ((new->HDisplay * new->VDisplay) < (p->HDisplay * p->VDisplay)) || ((new->HDisplay == p->HDisplay) && (new->VDisplay == p->VDisplay) && (new->Clock < p->Clock))) { From 6a92a779646ec03a03a3b1f45170b2e705ce8934 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 14 Jul 2006 14:20:41 -0700 Subject: [PATCH 140/257] Don't try to probe on more pipes than we really have. --- src/i830_modes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index 1965c390..1c5e7eb4 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -895,7 +895,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) Bool pipes_reconfigured = FALSE; int originalVirtualX, originalVirtualY; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { I830ReprobePipeModeList(pScrn, pipe); } @@ -944,7 +944,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) /* Set up a virtual size that will cover any clone mode we'd want to set * for either of the two pipes. */ - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { MonPtr mon = pI830->pipeMon[pipe]; DisplayModePtr mode; @@ -969,7 +969,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) * initially. */ if (!first_time) { - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { MonPtr mon = pI830->pipeMon[pipe]; DisplayModePtr mode; From 49b827605628d3e1a6d4d41447cf46c5f38cc0c2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 14 Jul 2006 14:23:04 -0700 Subject: [PATCH 141/257] Add a register restore implementation so we don't crash on LeaveVT. We shouldn't ever need to save/restore the hi/lo frequency regs, as they're read-only. --- src/sil164/sil164.c | 22 +++++++++++++++------- src/sil164/sil164_reg.h | 2 -- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/sil164/sil164.c b/src/sil164/sil164.c index a2742621..0a68d691 100644 --- a/src/sil164/sil164.c +++ b/src/sil164/sil164.c @@ -197,12 +197,6 @@ sil164SaveRegs(I2CDevPtr d) { SIL164Ptr sil = SILPTR(d); - if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo)) - return; - - if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi)) - return; - if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8)) return; @@ -215,6 +209,20 @@ sil164SaveRegs(I2CDevPtr d) return; } +static void +sil164RestoreRegs(I2CDevPtr d) +{ + SIL164Ptr sil = SILPTR(d); + + /* Restore it powered down initially */ + sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1); + + sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9); + sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc); + sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8); +} + + I830I2CVidOutputRec SIL164VidOutput = { sil164Detect, sil164Init, @@ -223,5 +231,5 @@ I830I2CVidOutputRec SIL164VidOutput = { sil164Power, sil164PrintRegs, sil164SaveRegs, - NULL, + sil164RestoreRegs, }; diff --git a/src/sil164/sil164_reg.h b/src/sil164/sil164_reg.h index dc2abba6..ebfcb8c7 100644 --- a/src/sil164/sil164_reg.h +++ b/src/sil164/sil164_reg.h @@ -58,8 +58,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define SIL164_REGC 0x0c typedef struct _Sil164SaveRec { - CARD8 freq_lo; - CARD8 freq_hi; CARD8 reg8; CARD8 reg9; CARD8 regc; From c7083a267209c93b2a91ef00dea2ca840400d160 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 14 Jul 2006 13:23:40 -0700 Subject: [PATCH 142/257] Bug #7404: Only save/restore VGA fonts and not other VGA regs. This fixes a hang on the i945 during restore. It appears that saving/restoring the VGA registers is not important, as we're correctly saving/restoring the registers we touch within the driver anyway. --- src/i830_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 396685a0..8464b39f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2754,7 +2754,7 @@ SaveHWState(ScrnInfoPtr pScrn) } vgaHWUnlock(hwp); - vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); + vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); return TRUE; } @@ -2773,7 +2773,7 @@ RestoreHWState(ScrnInfoPtr pScrn) #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, FALSE); #endif - vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); /* First, disable display planes */ From a6d438ebe3cf141a0331e0cd55eb9b5e137a5e37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jul 2006 14:11:19 -0400 Subject: [PATCH 143/257] Disable spread spectrum clock usage. The spread spectrum clock generator that improves EMI characteristics for laptop screens lives in an external chip that is programmed over an i2c bus. Without correct programming, attempts to use this mode for the LVDS can result in a DC signal being sent to the panel. Until we find programming information for this external chip, we should leave this mode disabled. --- src/i830_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 1496c3a3..6eb2a330 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -476,8 +476,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE)) dpll |= PLL_REF_INPUT_TVCLKINBC; +#if 0 else if (outputs & (PIPE_LCD_ACTIVE)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; +#endif else dpll |= PLL_REF_INPUT_DREFCLK; From e5c572f841b626b8b6f21a6966a33956d3b0b35b Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 2 Aug 2006 20:47:12 -0400 Subject: [PATCH 144/257] Fix a braino in mode list pruning. Interpreting the size of the display in centimeters as the size in pixels, and then clipping the modes list based on that, rarely does what you want. --- src/i830_modes.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index 1c5e7eb4..6bff1d0a 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -638,10 +638,6 @@ i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); i830xf86ValidateModesSync(pScrn, userModes, mon); - if (ddc->features.hsize > 0 && ddc->features.vsize > 0) { - i830xf86ValidateModesSize(pScrn, userModes, ddc->features.hsize, - ddc->features.vsize, -1); - } i830xf86PruneInvalidModes(pScrn, &userModes, TRUE); i830AppendModes(pScrn, &mon->Modes, userModes); From 71e3e2d4e3b2a2c538fe6f1cea41f442fdb8d756 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 4 Aug 2006 20:39:50 +0100 Subject: [PATCH 145/257] Fix a problem creating the I2C bus for the SDVOC interface, due to a name match with SDVOB. Bus names must be unique. --- src/i830_sdvo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 9a18f578..fe0c41a6 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -858,7 +858,10 @@ I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) xfree(sdvo); return NULL; } - ddcbus->BusName = "SDVO DDC Bus"; + if (output_device == SDVOB) + ddcbus->BusName = "SDVOB DDC Bus"; + else + ddcbus->BusName = "SDVOC DDC Bus"; ddcbus->scrnIndex = i2cbus->scrnIndex; ddcbus->I2CGetByte = I830SDVODDCI2CGetByte; ddcbus->I2CPutByte = I830SDVODDCI2CPutByte; From 421b415e23c1ddc78837cd222167d6ed71a3ef88 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 8 Aug 2006 11:28:42 +0100 Subject: [PATCH 146/257] Fix a build problem. --- src/ch7xxx/ch7xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c index 77c49b53..fdc96d0a 100644 --- a/src/ch7xxx/ch7xxx.c +++ b/src/ch7xxx/ch7xxx.c @@ -25,6 +25,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#include #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" @@ -32,7 +33,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "miscstruct.h" #include "xf86i2c.h" -#include #include "../i2c_vid.h" #include "ch7xxx.h" From 6f0d352b83fc9f39dd86edbda9af83243b50c764 Mon Sep 17 00:00:00 2001 From: Ross Burton Date: Thu, 24 Aug 2006 18:16:42 -0700 Subject: [PATCH 147/257] Bug #7957: Fix distcheck. --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 50d0ad1a..71ae2f25 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,6 +32,7 @@ i810_drv_ladir = @moduledir@/drivers i810_drv_la_SOURCES = \ common.h \ + i2c_vid.h \ i810_accel.c \ i810_common.h \ i810_cursor.c \ @@ -65,6 +66,8 @@ i810_drv_la_SOURCES = \ i830_rotate.c \ i830_randr.c \ i830_sdvo.c \ + i830_sdvo.h \ + i830_sdvo_regs.h \ i830_xf86Modes.h \ i830_xf86Modes.c if DRI From cbaf3cf74bd420533d299c4113761ec536097e33 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Aug 2006 18:25:21 -0700 Subject: [PATCH 148/257] verbose debug message for panel sync data --- src/i830_bios.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 4b87351c..b68c4676 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -210,7 +210,13 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) pI830->panel_fixed_vblank = _V_BLANK(timing_ptr); pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr); pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr); - + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n", + pI830->panel_fixed_hactive, pI830->panel_fixed_hblank, + (double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank), + pI830->panel_fixed_vactive, pI830->panel_fixed_vblank, + (double) pI830->panel_fixed_clock / + ((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank))); found_panel_info = TRUE; break; } From 2b9c87bbf8ee5f7f56631114eb98303cd80e4a48 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 8 Sep 2006 11:14:05 -0700 Subject: [PATCH 149/257] Remove xf86_ansic.h usage. --- src/i830_bios.c | 1 - src/i830_debug.c | 1 - src/i830_display.c | 3 ++- src/i830_i2c.c | 1 - src/i830_sdvo.c | 1 - 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/i830_bios.c b/src/i830_bios.c index 4b87351c..556f57b3 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -31,7 +31,6 @@ #define _PARSE_EDID_ #include "xf86.h" -#include "xf86_ansic.h" #include "i830.h" #include "i830_bios.h" #include "edid.h" diff --git a/src/i830_debug.c b/src/i830_debug.c index e2a28b27..a48e9f2f 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -30,7 +30,6 @@ #endif #include "xf86.h" -#include "xf86_ansic.h" #include "i830.h" #include "i830_debug.h" diff --git a/src/i830_display.c b/src/i830_display.c index 6eb2a330..2fb918a3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -30,8 +30,9 @@ #include "config.h" #endif +#include + #include "xf86.h" -#include "xf86_ansic.h" #include "i830.h" #include "i830_bios.h" #include "i830_display.h" diff --git a/src/i830_i2c.c b/src/i830_i2c.c index fa0ca301..cee7bb51 100644 --- a/src/i830_i2c.c +++ b/src/i830_i2c.c @@ -30,7 +30,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #endif #include "xf86.h" -#include "xf86_ansic.h" #include "xf86_OSproc.h" #include "xf86Resources.h" #include "xf86RAC.h" diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index fe0c41a6..cbc9c6b0 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -27,7 +27,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "config.h" #endif #include "xf86.h" -#include "xf86_ansic.h" #include "xf86_OSproc.h" #include "compiler.h" #include "i830.h" From e3f4caf40708478ef327b029d0a75944c51ea905 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 15 Sep 2006 13:51:18 -0400 Subject: [PATCH 150/257] Add model-specific tweaks for some funky 945GM boards. For the Aopen Mini-PC, ignore the claimed attached 800x600 LVDS panel. Likewise for the Apple Mac Mini, but done slightly differently since it shares PCI IDs with the Macbook Pro. --- src/i830_driver.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 8464b39f..75ea480c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1231,7 +1231,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) int i, n; char *s; pointer pVBEModule = NULL; - Bool enable, has_lvds; + Bool enable, has_lvds, is_apple_945gm = FALSE; const char *chipname; unsigned int ver; char v[5]; @@ -1672,16 +1672,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) if (!i830GetLVDSInfoFromBIOS(pScrn)) has_lvds = FALSE; - /* If the panel sequencing, status, and control registers are all zero, - * assume there's no panel attached. This is the case on the Mac mini, - * which is an i945GM but has no LVDS. If we tried to power something on - * with zeroed panel sequencing registers, it probably wouldn't be a good - * thing anyway. - */ - if (INREG(PP_STATUS) == 0 && INREG(PP_CONTROL) == 0 && - INREG(LVDSPP_ON) == 0 && INREG(LVDSPP_OFF) == 0) - { - has_lvds = FALSE; + /* Blacklist machines with known broken BIOSes */ + if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) { + if ((pI830->PciInfo->subsysVendor == 0xa0a0) && + (pI830->PciInfo->subsysCard == 0x0589)) /* aopen mini pc */ + has_lvds = FALSE; + + if ((pI830->PciInfo->subsysVendor == 0x8086) && + (pI830->PciInfo->subsysCard == 0x7270)) /* mini, macbook pro... */ + is_apple_945gm = TRUE; } if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && @@ -1772,6 +1771,20 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. */ + + /* + * Apple hardware is out to get us. The macbook pro has a real LVDS + * panel, but the mac mini does not, and they have the same device IDs. + * We'll distinguish by panel size, on the assumption that Apple isn't + * about to make any machines with an 800x600 display. + */ + if (is_apple_945gm && pI830->PanelXRes == 800 && pI830->PanelYRes == 600) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Suspected Mac Mini, ignoring the LFP\n"); + has_lvds = FALSE; + } + if (has_lvds) { pI830->MonType2 |= PIPE_LFP; } From daade50ca271d1cdf236bbe84afade85d4111ac9 Mon Sep 17 00:00:00 2001 From: Linus Torvals Date: Wed, 20 Sep 2006 12:07:09 -0700 Subject: [PATCH 151/257] Add standard C headers to fix build on some systems after xf86_ansic.h removal. This appears to have been hidden for others by header pollution in X Server headers. --- src/i830_bios.c | 3 +++ src/i830_display.c | 4 ++++ src/i830_sdvo.c | 3 +++ 3 files changed, 10 insertions(+) diff --git a/src/i830_bios.c b/src/i830_bios.c index 556f57b3..14e354ed 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -29,6 +29,9 @@ #undef VERSION /* XXX edid.h has a VERSION too */ #endif +#include +#include + #define _PARSE_EDID_ #include "xf86.h" #include "i830.h" diff --git a/src/i830_display.c b/src/i830_display.c index 2fb918a3..ef7e8322 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -31,6 +31,10 @@ #endif #include +#include +#include +#include +#include #include "xf86.h" #include "i830.h" diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index cbc9c6b0..c7625419 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -26,6 +26,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef HAVE_CONFIG_H #include "config.h" #endif + +#include + #include "xf86.h" #include "xf86_OSproc.h" #include "compiler.h" From f6500e94fec0d6db8c1f1350bee1d137bf06a09e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 20 Sep 2006 22:38:55 -0700 Subject: [PATCH 152/257] Update driver for RandR 1.2 X server API. This is not entirely what I'd like to see, but it's at least functional. Limitations: Can't disable/enable crtcs Can't move outputs on/off crtcs But, it does handle monitor hot-plug, detecting changes in VGA and SDVO status on-the fly. Which makes for good demo material. --- configure.ac | 3 +- src/Makefile.am | 2 +- src/i830.h | 22 ++- src/i830_cursor.c | 351 ++++++++++++++++++----------------- src/i830_display.c | 8 +- src/i830_display.h | 1 + src/i830_driver.c | 25 +-- src/i830_modes.c | 5 + src/i830_randr.c | 450 +++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 677 insertions(+), 190 deletions(-) diff --git a/configure.ac b/configure.ac index 5c9291bf..3375fa95 100644 --- a/configure.ac +++ b/configure.ac @@ -99,8 +99,6 @@ if test "x$GCC" = "xyes"; then -Wnested-externs -fno-strict-aliasing" fi -CFLAGS="$CFLAGS $WARN_CFLAGS" - AM_CONDITIONAL(DRI, test x$DRI = xyes) if test "$DRI" = yes; then PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto]) @@ -110,6 +108,7 @@ fi AC_SUBST([DRI_CFLAGS]) AC_SUBST([XORG_CFLAGS]) +AC_SUBST([WARN_CFLAGS]) AC_SUBST([moduledir]) DRIVER_NAME=i810 diff --git a/src/Makefile.am b/src/Makefile.am index 50d0ad1a..03b5fe67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ SUBDIRS = xvmc bios_reader ch7xxx sil164 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV +AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV i810_drv_la_LTLIBRARIES = i810_drv.la i810_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/i830.h b/src/i830.h index 3a939312..fcd03efb 100644 --- a/src/i830.h +++ b/src/i830.h @@ -79,6 +79,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Paulo César Pereira de Andrade . */ +#define PIPE_CRT_ID 0 +#define PIPE_TV_ID 1 +#define PIPE_DFP_ID 2 +#define PIPE_LFP_ID 3 +#define PIPE_CRT2_ID 4 +#define PIPE_TV2_ID 5 +#define PIPE_DFP2_ID 6 +#define PIPE_LFP2_ID 7 +#define PIPE_NUM_ID 8 + #define PIPE_NONE 0<<0 #define PIPE_CRT 1<<0 #define PIPE_TV 1<<1 @@ -201,10 +211,12 @@ typedef struct _I830SDVODriver { CARD32 save_SDVOX; } I830SDVORec, *I830SDVOPtr; +extern const char *i830_output_type_names[]; + struct _I830OutputRec { int type; - int pipe; - int flags; +/* int pipe; + int flags;*/ xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; @@ -233,6 +245,10 @@ typedef struct _I830Rec { Bool gammaEnabled[MAX_DISPLAY_PIPES]; + int pipeX[MAX_DISPLAY_PIPES]; + int pipeY[MAX_DISPLAY_PIPES]; + Bool cursorInRange[MAX_DISPLAY_PIPES]; + Bool cursorShown[MAX_DISPLAY_PIPES]; Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -518,6 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI830); extern void I830PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); +extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe); extern Bool I830CursorInit(ScreenPtr pScreen); extern void I830EmitInvarientState(ScrnInfoPtr pScrn); extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer); @@ -610,6 +627,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); /* i830_randr.c */ +Bool I830RandRCreateScreenResources (ScreenPtr pScreen); Bool I830RandRInit(ScreenPtr pScreen, int rotation); Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 2cb069cc..1e7beef2 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -79,13 +79,107 @@ static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs); static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); #endif +void +I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + Bool show; + + if (!pI830->planeEnabled[pipe]) + return; + + show = pI830->cursorOn && pI830->cursorInRange[pipe]; + if (show && !pI830->cursorShown[pipe]) + { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { + int cursor_control, cursor_base; + if (pipe == 0) + { + cursor_control = CURSOR_A_CONTROL; + cursor_base = CURSOR_A_BASE; + } + else + { + cursor_control = CURSOR_B_CONTROL; + cursor_base = CURSOR_B_BASE; + } + temp = INREG(cursor_control); + temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + if (pI830->CursorIsARGB) { + temp |= CURSOR_MODE_64_ARGB_AX; + if (pI830->gammaEnabled[pipe]) + temp |= MCURSOR_GAMMA_ENABLE; + } else + temp |= CURSOR_MODE_64_4C_AX; + + temp |= (pipe << 28); /* Connect to correct pipe */ + /* Need to set mode, then address. */ + OUTREG(cursor_control, temp); + if (pI830->CursorIsARGB) + OUTREG(cursor_base, pI830->CursorMemARGB->Physical); + else + OUTREG(cursor_base, pI830->CursorMem->Physical); + } else { + temp = INREG(CURSOR_CONTROL); + temp &= ~(CURSOR_FORMAT_MASK); + temp |= CURSOR_ENABLE; + if (pI830->CursorIsARGB) { + temp |= CURSOR_FORMAT_ARGB; + if (pI830->gammaEnabled[pipe]) + temp |= CURSOR_GAMMA_ENABLE; + } else + temp |= CURSOR_FORMAT_3C; + OUTREG(CURSOR_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); + } + pI830->cursorShown[pipe] = TRUE; + } + else if (!show && pI830->cursorShown[pipe]) + { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) + { + int cursor_control, cursor_base; + if (pipe == 0) + { + cursor_control = CURSOR_A_CONTROL; + cursor_base = CURSOR_A_BASE; + } + else + { + cursor_control = CURSOR_B_CONTROL; + cursor_base = CURSOR_B_BASE; + } + temp = INREG(cursor_control); + temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); + temp |= CURSOR_MODE_DISABLE; + OUTREG(cursor_control, temp); + /* This is needed to flush the above change. */ + if (pI830->CursorIsARGB) + OUTREG(cursor_base, pI830->CursorMemARGB->Physical); + else + OUTREG(cursor_base, pI830->CursorMem->Physical); + } else { + temp = INREG(CURSOR_CONTROL); + temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); + OUTREG(CURSOR_CONTROL, temp); + } + pI830->cursorShown[pipe] = FALSE; + } +} + void I830InitHWCursor(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; + int i; DPRINTF(PFX, "I830InitHWCursor\n"); + for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); @@ -356,121 +450,109 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp = 0; - Bool hide = FALSE, show = FALSE; - int oldx = x, oldy = y; - int hotspotx = 0, hotspoty = 0; -#if 0 - static Bool outsideViewport = FALSE; -#endif + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + Bool inrange; + int oldx = x, oldy = y; + int hotspotx = 0, hotspoty = 0; + int pipe; - oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ - oldy += pScrn->frameY0; + oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ + oldy += pScrn->frameY0; - switch (pI830->rotation) { - case RR_Rotate_0: - x = oldx; - y = oldy; - break; - case RR_Rotate_90: - x = oldy; - y = pScrn->pScreen->width - oldx; - hotspoty = I810_CURSOR_X; - break; - case RR_Rotate_180: - x = pScrn->pScreen->width - oldx; - y = pScrn->pScreen->height - oldy; - hotspotx = I810_CURSOR_X; - hotspoty = I810_CURSOR_Y; - break; - case RR_Rotate_270: - x = pScrn->pScreen->height - oldy; - y = oldx; - hotspotx = I810_CURSOR_Y; - break; - } + switch (pI830->rotation) { + case RR_Rotate_0: + x = oldx; + y = oldy; + break; + case RR_Rotate_90: + x = oldy; + y = pScrn->pScreen->width - oldx; + hotspoty = I810_CURSOR_X; + break; + case RR_Rotate_180: + x = pScrn->pScreen->width - oldx; + y = pScrn->pScreen->height - oldy; + hotspotx = I810_CURSOR_X; + hotspoty = I810_CURSOR_Y; + break; + case RR_Rotate_270: + x = pScrn->pScreen->height - oldy; + y = oldx; + hotspotx = I810_CURSOR_Y; + break; + } - x -= hotspotx; - y -= hotspoty; + x -= hotspotx; + y -= hotspoty; - /* Now, readjust */ - x -= pScrn->frameX0; - y -= pScrn->frameY0; + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + { + DisplayModePtr mode = &pI830->pipeCurMode[pipe]; + int thisx = x - pI830->pipeX[pipe]; + int thisy = y - pI830->pipeY[pipe]; - /* Clamp the cursor position to the visible screen area. Ignore this if we - * are doing motion (with SilkenMouse) while the currentMode being changed. - */ - if (pScrn->currentMode != NULL) { - if (x >= pScrn->currentMode->HDisplay) - x = pScrn->currentMode->HDisplay - 1; - if (y >= pScrn->currentMode->VDisplay) - y = pScrn->currentMode->VDisplay - 1; - } - if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1; - if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1; + if (!pI830->planeEnabled[pipe]) + continue; -#if 0 - /* - * There is a screen display problem when the cursor position is set - * wholely outside of the viewport. We trap that here, turning the - * cursor off when that happens, and back on when it comes back into - * the viewport. - */ - if (x >= pScrn->currentMode->HDisplay || - y >= pScrn->currentMode->VDisplay || - x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) { - hide = TRUE; - outsideViewport = TRUE; - } else if (outsideViewport) { - show = TRUE; - outsideViewport = FALSE; - } -#endif + /* + * There is a screen display problem when the cursor position is set + * wholely outside of the viewport. We trap that here, turning the + * cursor off when that happens, and back on when it comes back into + * the viewport. + */ + inrange = TRUE; + if (thisx >= mode->HDisplay || + thisy >= mode->VDisplay || + thisx <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y) + { + inrange = FALSE; + thisx = 0; + thisy = 0; + } - if (x < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); - x = -x; - } - if (y < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); - y = -y; - } - temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); - temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + temp = 0; + if (thisx < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + thisx = -thisx; + } + if (thisy < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + thisy = -thisy; + } + temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - OUTREG(CURSOR_A_POSITION, temp); - if (pI830->Clone) - OUTREG(CURSOR_B_POSITION, temp); + if (pipe == 0) + OUTREG(CURSOR_A_POSITION, temp); + if (pipe == 1) + OUTREG(CURSOR_B_POSITION, temp); - if (pI830->cursorOn) { - if (hide) - pI830->CursorInfoRec->HideCursor(pScrn); - else if (show) - pI830->CursorInfoRec->ShowCursor(pScrn); - pI830->cursorOn = TRUE; - } + pI830->cursorInRange[pipe] = inrange; + + I830SetPipeCursor (pScrn, pipe); + } - /* have to upload the base for the new position */ - if (IS_I9XX(pI830)) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } + /* have to upload the base for the new position */ + if (IS_I9XX(pI830)) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } + } } static void I830ShowCursor(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; + int pipe; DPRINTF(PFX, "I830ShowCursor\n"); DPRINTF(PFX, @@ -482,81 +564,22 @@ I830ShowCursor(ScrnInfoPtr pScrn) " Value of CursorMemARGB->Start is %x ", pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); - pI830->cursorOn = TRUE; - if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); - if (pI830->CursorIsARGB) { - temp |= CURSOR_MODE_64_ARGB_AX; - if (pI830->gammaEnabled[pI830->pipe]) - temp |= MCURSOR_GAMMA_ENABLE; - } else - temp |= CURSOR_MODE_64_4C_AX; - temp |= (pI830->pipe << 28); /* Connect to correct pipe */ - /* Need to set mode, then address. */ - OUTREG(CURSOR_A_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - temp &= ~MCURSOR_PIPE_SELECT; - temp |= (!pI830->pipe << 28); - OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } else { - temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_FORMAT_MASK); - temp |= CURSOR_ENABLE; - if (pI830->CursorIsARGB) { - temp |= CURSOR_FORMAT_ARGB; - if (pI830->gammaEnabled[pI830->pipe]) - temp |= CURSOR_GAMMA_ENABLE; - } else - temp |= CURSOR_FORMAT_3C; - OUTREG(CURSOR_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); - else - OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); - } + pI830->cursorOn = TRUE; + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + I830SetPipeCursor (pScrn, pipe); } static void I830HideCursor(ScrnInfoPtr pScrn) { - CARD32 temp; I830Ptr pI830 = I830PTR(pScrn); + int pipe; DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); - temp |= CURSOR_MODE_DISABLE; - OUTREG(CURSOR_A_CONTROL, temp); - /* This is needed to flush the above change. */ - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } else { - temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); - OUTREG(CURSOR_CONTROL, temp); - } + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + I830SetPipeCursor (pScrn, pipe); } static void diff --git a/src/i830_display.c b/src/i830_display.c index 6eb2a330..52d488a4 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -245,13 +245,15 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); else OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + pI830->pipeX[pipe] = x; + pI830->pipeY[pipe] = y; } /** * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. */ -static Bool +Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) { I830Ptr pI830 = I830PTR(pScrn); @@ -608,7 +610,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPASIZE, dspsize); OUTREG(DSPAPOS, 0); - i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); + i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]); OUTREG(PIPEASRC, pipesrc); /* Then, turn the pipe on first */ @@ -656,7 +658,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPBSIZE, dspsize); OUTREG(DSPBPOS, 0); - i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); + i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]); OUTREG(PIPEBSRC, pipesrc); if (outputs & PIPE_LCD_ACTIVE) { diff --git a/src/i830_display.h b/src/i830_display.h index 2e61afce..e5bca1c8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -26,6 +26,7 @@ */ /* i830_display.c */ +Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_driver.c b/src/i830_driver.c index 8464b39f..dc136a3a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -273,7 +273,7 @@ static OptionInfoRec I830BIOSOptions[] = { }; /* *INDENT-ON* */ -static const char *output_type_names[] = { +const char *i830_output_type_names[] = { "Unused", "Analog", "DVO", @@ -1133,7 +1133,7 @@ I830DetectMonitors(ScrnInfoPtr pScrn) pI830->output[i].pDDCBus); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n", - output_type_names[pI830->output[i].type], i, + i830_output_type_names[pI830->output[i].type], i, pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); break; @@ -3164,22 +3164,8 @@ I830CreateScreenResources (ScreenPtr pScreen) if (!(*pScreen->CreateScreenResources)(pScreen)) return FALSE; - if (pI830->rotation != RR_Rotate_0) { - RRScreenSize p; - Rotation requestedRotation = pI830->rotation; - - pI830->rotation = RR_Rotate_0; - - /* Just setup enough for an initial rotate */ - p.width = pScreen->width; - p.height = pScreen->height; - p.mmWidth = pScreen->mmWidth; - p.mmHeight = pScreen->mmHeight; - - pI830->starting = TRUE; /* abuse this for dual head & rotation */ - I830RandRSetConfig (pScreen, requestedRotation, 0, &p); - pI830->starting = FALSE; - } + if (!I830RandRCreateScreenResources (pScreen)) + return FALSE; return TRUE; } @@ -3507,6 +3493,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!I830BIOSEnterVT(scrnIndex, 0)) return FALSE; + if (pScrn->virtualX > pScrn->displayWidth) + pScrn->displayWidth = pScrn->virtualX; + DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, pScrn->virtualX, pScrn->virtualY, diff --git a/src/i830_modes.c b/src/i830_modes.c index 6bff1d0a..3b70d5d4 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -954,6 +954,11 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) maxY = mode->VDisplay; } } + /* let the user specify a bigger virtual size if they like */ + if (pScrn->display->virtualX > maxX) + maxX = pScrn->display->virtualX; + if (pScrn->display->virtualY > maxY) + maxY = pScrn->display->virtualY; pScrn->virtualX = maxX; pScrn->virtualY = maxY; pScrn->displayWidth = (maxX + 63) & ~63; diff --git a/src/i830_randr.c b/src/i830_randr.c index 4c7c087e..4132eb2e 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -23,6 +23,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xf86.h" #include "os.h" #include "mibank.h" @@ -33,9 +37,11 @@ #include "mipointer.h" #include "windowstr.h" #include +#include #include "i830.h" #include "i830_xf86Modes.h" +#include "i830_display.h" typedef struct _i830RandRInfo { int virtualX; @@ -46,8 +52,18 @@ typedef struct _i830RandRInfo { int maxY; Rotation rotation; /* current mode */ Rotation supported_rotations; /* driver supported */ +#ifdef RANDR_12_INTERFACE + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + RROutputPtr outputs[MAX_OUTPUTS]; + DisplayModePtr modes[MAX_DISPLAY_PIPES]; +#endif } XF86RandRInfoRec, *XF86RandRInfoPtr; +#ifdef RANDR_12_INTERFACE +static Bool I830RandRInit12 (ScreenPtr pScreen); +static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen); +#endif + static int i830RandRIndex; static int i830RandRGeneration; @@ -316,6 +332,40 @@ I830GetRotation(ScreenPtr pScreen) return randrp->rotation; } +Bool +I830RandRCreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif +#if RANDR_12_INTERFACE + if (I830RandRCreateScreenResources12 (pScreen)) + return TRUE; +#endif + if (pI830->rotation != RR_Rotate_0) { + RRScreenSize p; + Rotation requestedRotation = pI830->rotation; + + pI830->rotation = RR_Rotate_0; + + /* Just setup enough for an initial rotate */ + p.width = pScreen->width; + p.height = pScreen->height; + p.mmWidth = pScreen->mmWidth; + p.mmHeight = pScreen->mmHeight; + + pI830->starting = TRUE; /* abuse this for dual head & rotation */ + I830RandRSetConfig (pScreen, requestedRotation, 0, &p); + pI830->starting = FALSE; + } + return TRUE; +} + + Bool I830RandRInit (ScreenPtr pScreen, int rotation) { @@ -359,6 +409,10 @@ I830RandRInit (ScreenPtr pScreen, int rotation) pScreen->devPrivates[i830RandRIndex].ptr = randrp; +#if RANDR_12_INTERFACE + if (!I830RandRInit12 (pScreen)) + return FALSE; +#endif return TRUE; } @@ -379,3 +433,399 @@ I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) *y = randrp->virtualY; } } + +#if RANDR_12_INTERFACE +static Bool +I830RandRScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + WindowPtr pRoot = WindowTable[pScreen->myNum]; + Bool ret = TRUE; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); + pScrn->virtualX = width; + pScrn->virtualY = height; + + pScreen->width = pScrn->virtualX; + pScreen->height = pScrn->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); + if (WindowTable[pScreen->myNum]) + RRScreenSizeNotify (pScreen); + return ret; +} + +static Bool +I830RandRCrtcNotify (RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + RRModePtr mode = NULL; + int x; + int y; + Rotation rotation; + int numOutputs; + RROutputPtr outputs[MAX_OUTPUTS]; + struct _I830OutputRec *output; + RROutputPtr rrout; + int pipe = (int) crtc->devPrivate; + int i, j; + DisplayModePtr pipeMode = &pI830->pipeCurMode[pipe]; + int pipe_type; + + x = pI830->pipeX[pipe]; + y = pI830->pipeY[pipe]; + rotation = RR_Rotate_0; + numOutputs = 0; + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + /* + * Valid crtcs + */ + switch (output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + pipe_type = PIPE_DFP; + break; + case I830_OUTPUT_ANALOG: + pipe_type = PIPE_CRT; + break; + case I830_OUTPUT_LVDS: + pipe_type = PIPE_LFP; + break; + case I830_OUTPUT_TVOUT: + pipe_type = PIPE_TV; + break; + default: + pipe_type = PIPE_NONE; + break; + } + if (pI830->operatingDevices & (pipe_type << (pipe << 3))) + { + rrout = randrp->outputs[i]; + outputs[numOutputs++] = rrout; + for (j = 0; j < rrout->numModes; j++) + { + DisplayModePtr outMode = rrout->modes[j]->devPrivate; + if (I830ModesEqual(pipeMode, outMode)) + mode = rrout->modes[j]; + } + } + } + return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs); +} + +static Bool +I830RandRCrtcSet (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int pipe = (int) (crtc->devPrivate); + DisplayModePtr display_mode = mode->devPrivate; + + /* Sync the engine before adjust mode */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + + if (display_mode != randrp->modes[pipe]) + { + if (!i830PipeSetMode (pScrn, display_mode, pipe)) + return FALSE; + randrp->modes[pipe] = display_mode; + } + i830PipeSetBase(pScrn, pipe, x, y); + return I830RandRCrtcNotify (crtc); +} + +static Bool +I830RandRCrtcSetGamma (ScreenPtr pScreen, + RRCrtcPtr crtc) +{ + return FALSE; +} + +/* + * Mirror the current mode configuration to RandR + */ +static Bool +I830RandRSetInfo12 (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + RROutputPtr clones[MAX_OUTPUTS]; + RRCrtcPtr crtc; + int nclone; + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + int ncrtc; + RRModePtr *modes; + int nmode; + struct _I830OutputRec *output; + int i; + int j; + int clone_types; + int crtc_types; + int connection; + int pipe_type; + int pipe; + int subpixel; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + RRScreenSetSizeRange (pScreen, 320, 240, + randrp->virtualX, randrp->virtualY); + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + /* + * Valid crtcs + */ + switch (output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + crtc_types = ((1 << 0)| + (1 << 1)); + clone_types = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + pipe_type = PIPE_DFP; + subpixel = SubPixelHorizontalRGB; + break; + case I830_OUTPUT_ANALOG: + crtc_types = (1 << 0); + clone_types = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + pipe_type = PIPE_CRT; + subpixel = SubPixelNone; + break; + case I830_OUTPUT_LVDS: + crtc_types = (1 << 1); + clone_types = (1 << I830_OUTPUT_LVDS); + pipe_type = PIPE_LFP; + subpixel = SubPixelHorizontalRGB; + break; + case I830_OUTPUT_TVOUT: + crtc_types = ((1 << 0) | + (1 << 1)); + clone_types = (1 << I830_OUTPUT_TVOUT); + pipe_type = PIPE_TV; + subpixel = SubPixelNone; + break; + default: + crtc_types = 0; + clone_types = 0; + pipe_type = PIPE_NONE; + subpixel = SubPixelUnknown; + break; + } + ncrtc = 0; + pipe = -1; + crtc = NULL; + for (j = 0; j < MAX_DISPLAY_PIPES; j++) + { +#if 0 + /* Can't flip outputs among crtcs yet */ + if (crtc_types & (1 << j)) + crtcs[ncrtc++] = randrp->crtcs[j]; +#endif + if (pI830->operatingDevices & (pipe_type << (j << 3))) + { + pipe = j; + crtc = randrp->crtcs[j]; + crtcs[ncrtc++] = crtc; + } + } + if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc)) + return FALSE; + + RROutputSetCrtc (randrp->outputs[i], crtc); + + if (pipe >= 0) + { + MonPtr mon = pI830->pipeMon[pipe]; + DisplayModePtr mode; + xRRModeInfo modeInfo; + RRModePtr rrmode; + + nmode = 0; + for (mode = mon->Modes; mode; mode = mode->next) + nmode++; + + if (nmode) + { + modes = xalloc (nmode * sizeof (RRModePtr)); + if (!modes) + return FALSE; + nmode = 0; + for (mode = mon->Modes; mode; mode = mode->next) + { + modeInfo.nameLength = strlen (mode->name); + modeInfo.mmWidth = mon->widthmm; + modeInfo.mmHeight = mon->heightmm; + + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (pScreen, &modeInfo, mode->name); + rrmode->devPrivate = mode; + if (rrmode) + modes[nmode++] = rrmode; + } + if (!RROutputSetModes (randrp->outputs[i], modes, nmode)) + { + xfree (modes); + return FALSE; + } + + xfree (modes); + } + } + connection = RR_Disconnected; + if (pipe >= 0) + connection = RR_Connected; + + RROutputSetConnection (randrp->outputs[i], connection); + + RROutputSetSubpixelOrder (randrp->outputs[i], subpixel); + + /* + * Valid clones + */ + nclone = 0; + for (j = 0; j < pI830->num_outputs; j++) + { + if (i != j && ((1 << pI830->output[j].type) & clone_types)) + clones[nclone++] = randrp->outputs[j]; + } + if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) + return FALSE; + } + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + I830RandRCrtcNotify (randrp->crtcs[i]); + return TRUE; +} + + +/* + * Query the hardware for the current state, then mirror + * that to RandR + */ +static Bool +I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + /* Re-probe the outputs for new monitors or modes */ + I830ValidateXF86ModeList(pScrn, FALSE); + return I830RandRSetInfo12 (pScreen); +} + +static Bool +I830RandRCreateScreenResources12 (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + struct _I830OutputRec *output; + const char *name; + int i; + DisplayModePtr mode; + + /* + * Create RandR resources, then probe them + */ + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + { + randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); + RRCrtcGammaSetSize (randrp->crtcs[i], 256); + } + + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + name = i830_output_type_names[output->type]; + randrp->outputs[i] = RROutputCreate (pScreen, + name, strlen (name), + (void *) i); + } + + mode = pScrn->currentMode; + if (mode) + { + I830RandRScreenSetSize (pScreen, + mode->HDisplay, + mode->VDisplay, + pScreen->mmWidth, + pScreen->mmHeight); + + } + + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + i830PipeSetBase(pScrn, i, 0, 0); + + return I830RandRSetInfo12 (pScreen); +} + +static void +I830RandRPointerMoved (int scrnIndex, int x, int y) +{ +} + +static Bool +I830RandRInit12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + + rp->rrGetInfo = I830RandRGetInfo12; + rp->rrScreenSetSize = I830RandRScreenSetSize; + rp->rrCrtcSet = I830RandRCrtcSet; + rp->rrCrtcSetGamma = I830RandRCrtcSetGamma; + rp->rrSetConfig = NULL; + memset (rp->modes, '\0', sizeof (rp->modes)); + pScrn->PointerMoved = I830RandRPointerMoved; + return TRUE; +} +#endif From c11c445bdeac34253b48192a5d406b55ff8b2be7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Sep 2006 01:23:10 -0700 Subject: [PATCH 153/257] Consistently use Cursor A on Pipe 0 and Cursor B on Pipe 1. Mixing random cursors and pipes didn't work very well. I'm left wondering whether the palette stuff will work on pre-9xx series hardware though; it is special cased everwhere else. --- src/i830.h | 2 +- src/i830_cursor.c | 76 ++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/i830.h b/src/i830.h index fcd03efb..a0ded025 100644 --- a/src/i830.h +++ b/src/i830.h @@ -534,7 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI830); extern void I830PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); -extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe); +extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force); extern Bool I830CursorInit(ScreenPtr pScreen); extern void I830EmitInvarientState(ScrnInfoPtr pScrn); extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer); diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 1e7beef2..7389b665 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -80,7 +80,7 @@ static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); #endif void -I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe) +I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; @@ -90,7 +90,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe) return; show = pI830->cursorOn && pI830->cursorInRange[pipe]; - if (show && !pI830->cursorShown[pipe]) + if (show && (force || !pI830->cursorShown[pipe])) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { int cursor_control, cursor_base; @@ -138,7 +138,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe) } pI830->cursorShown[pipe] = TRUE; } - else if (!show && pI830->cursorShown[pipe]) + else if (!show && (force || pI830->cursorShown[pipe])) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { @@ -182,25 +182,22 @@ I830InitHWCursor(ScrnInfoPtr pScrn) for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL | - MCURSOR_PIPE_SELECT); - temp |= CURSOR_MODE_DISABLE; - temp |= (pI830->pipe << 28); - /* Need to set control, then address. */ - OUTREG(CURSOR_A_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - temp &= ~MCURSOR_PIPE_SELECT; - temp |= (!pI830->pipe << 28); - OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + { + int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; + int cursor_base = i == 0 ? CURSOR_A_BASE : CURSOR_B_BASE; + temp = INREG(cursor_control); + temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | + MCURSOR_MEM_TYPE_LOCAL | + MCURSOR_PIPE_SELECT); + temp |= CURSOR_MODE_DISABLE; + temp |= (i << 28); + /* Need to set control, then address. */ + OUTREG(cursor_control, temp); + if (pI830->CursorIsARGB) + OUTREG(cursor_base, pI830->CursorMemARGB->Physical); + else + OUTREG(cursor_base, pI830->CursorMem->Physical); } } else { temp = INREG(CURSOR_CONTROL); @@ -530,20 +527,15 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) pI830->cursorInRange[pipe] = inrange; - I830SetPipeCursor (pScrn, pipe); - } + I830SetPipeCursor (pScrn, pipe, FALSE); - /* have to upload the base for the new position */ - if (IS_I9XX(pI830)) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { + /* have to upload the base for the new position */ + if (IS_I9XX(pI830)) { + int base = pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE; if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + OUTREG(base, pI830->CursorMemARGB->Physical); else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + OUTREG(base, pI830->CursorMem->Physical); } } } @@ -566,7 +558,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->cursorOn = TRUE; for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) - I830SetPipeCursor (pScrn, pipe); + I830SetPipeCursor (pScrn, pipe, TRUE); } static void @@ -579,7 +571,7 @@ I830HideCursor(ScrnInfoPtr pScrn) pI830->cursorOn = FALSE; for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) - I830SetPipeCursor (pScrn, pipe); + I830SetPipeCursor (pScrn, pipe, TRUE); } static void @@ -595,11 +587,15 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); - if (pI830->Clone) { + if (pI830->planeEnabled[0]) + { + OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); + OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); + OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); + OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); + } + if (pI830->planeEnabled[1]) + { OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff); From 4820caf46e050761d9b347b8a440381e1b1f4727 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Sep 2006 01:47:27 -0700 Subject: [PATCH 154/257] Make planeEnabled track pipes controlled by randr. Also add code to deal with disabling pipes. --- src/i830_display.c | 2 +- src/i830_display.h | 1 + src/i830_randr.c | 22 +++++++++++++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 3bd662de..24ce50f7 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -719,7 +719,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) return TRUE; } -static void +void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); diff --git a/src/i830_display.h b/src/i830_display.h index e5bca1c8..2b808ad8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -27,6 +27,7 @@ /* i830_display.c */ Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); +void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_randr.c b/src/i830_randr.c index 4132eb2e..7c67aea2 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -548,7 +548,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int pipe = (int) (crtc->devPrivate); - DisplayModePtr display_mode = mode->devPrivate; + DisplayModePtr display_mode = mode ? mode->devPrivate : NULL; /* Sync the engine before adjust mode */ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { @@ -558,8 +558,24 @@ I830RandRCrtcSet (ScreenPtr pScreen, if (display_mode != randrp->modes[pipe]) { - if (!i830PipeSetMode (pScrn, display_mode, pipe)) - return FALSE; + pI830->planeEnabled[pipe] = mode != NULL; + if (display_mode) + { + if (!i830PipeSetMode (pScrn, display_mode, pipe)) + return FALSE; + /* XXX need I830SDVOPostSetMode here */ + } + else + { + CARD32 operatingDevices = pI830->operatingDevices; + + if (pipe == 0) + pI830->operatingDevices &= ~0xff; + else + pI830->operatingDevices &= ~0xff00; + i830DisableUnusedFunctions (pScrn); + pI830->operatingDevices = operatingDevices; + } randrp->modes[pipe] = display_mode; } i830PipeSetBase(pScrn, pipe, x, y); From d87d1f5bb0475c6f651fcb7e2cab2a7d46edcc69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Sep 2006 02:20:35 +0100 Subject: [PATCH 155/257] Remove BIOS from non-BIOS related names. Lots of names included BIOS for no apparent reason; as we try to eliminate BIOS calls from the driver, these only serve to confuse us. (cherry picked from 8e5d280d94ad3d3ba3c75871c17abec9da62ed34 commit) --- src/common.h | 2 +- src/i810_driver.c | 4 +-- src/i830.h | 2 +- src/i830_driver.c | 90 +++++++++++++++++++++++------------------------ 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/common.h b/src/common.h index 21977af4..6a55bfda 100644 --- a/src/common.h +++ b/src/common.h @@ -68,7 +68,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif /* I830 hooks for the I810 driver setup/probe. */ -extern const OptionInfoRec *I830BIOSAvailableOptions(int chipid, int busid); +extern const OptionInfoRec *I830AvailableOptions(int chipid, int busid); extern void I830InitpScrn(ScrnInfoPtr pScrn); /* Symbol lists shared by the i810 and i830 parts. */ diff --git a/src/i810_driver.c b/src/i810_driver.c index b87601e0..c8cb6071 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -477,11 +477,11 @@ I810AvailableOptions(int chipid, int busid) #ifndef I830_ONLY const OptionInfoRec *pOptions; - if ((pOptions = I830BIOSAvailableOptions(chipid, busid))) + if ((pOptions = I830AvailableOptions(chipid, busid))) return pOptions; return I810Options; #else - return I830BIOSAvailableOptions(chipid, busid); + return I830AvailableOptions(chipid, busid); #endif } diff --git a/src/i830.h b/src/i830.h index 3a939312..57d65065 100644 --- a/src/i830.h +++ b/src/i830.h @@ -72,7 +72,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_sdvo.h" #include "i2c_vid.h" -/* I830 Video BIOS support */ +/* I830 Video support */ /* * The mode handling is based upon the VESA driver written by diff --git a/src/i830_driver.c b/src/i830_driver.c index 75ea480c..d21bf9f2 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -198,7 +198,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define NB_OF(x) (sizeof (x) / sizeof (*x)) /* *INDENT-OFF* */ -static SymTabRec I830BIOSChipsets[] = { +static SymTabRec I830Chipsets[] = { {PCI_CHIP_I830_M, "i830"}, {PCI_CHIP_845_G, "845G"}, {PCI_CHIP_I855_GM, "852GM/855GM"}, @@ -211,7 +211,7 @@ static SymTabRec I830BIOSChipsets[] = { {-1, NULL} }; -static PciChipsets I830BIOSPciChipsets[] = { +static PciChipsets I830PciChipsets[] = { {PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA}, {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA}, {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, @@ -251,7 +251,7 @@ typedef enum { OPTION_LINEARALLOC } I830Opts; -static OptionInfoRec I830BIOSOptions[] = { +static OptionInfoRec I830Options[] = { {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, @@ -285,9 +285,9 @@ static const char *output_type_names[] = { static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); -static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen); -static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack); -static Bool I830BIOSEnterVT(int scrnIndex, int flags); +static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool I830SaveScreen(ScreenPtr pScreen, int unblack); +static Bool I830EnterVT(int scrnIndex, int flags); #if 0 static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock *block); @@ -325,21 +325,21 @@ I830DPRINTF_stub(const char *filename, int line, const char *function, } #endif /* #ifdef I830DEBUG */ -/* XXX Check if this is still needed. */ +/* Export I830 options to i830 driver where necessary */ const OptionInfoRec * -I830BIOSAvailableOptions(int chipid, int busid) +I830AvailableOptions(int chipid, int busid) { int i; - for (i = 0; I830BIOSPciChipsets[i].PCIid > 0; i++) { - if (chipid == I830BIOSPciChipsets[i].PCIid) - return I830BIOSOptions; + for (i = 0; I830PciChipsets[i].PCIid > 0; i++) { + if (chipid == I830PciChipsets[i].PCIid) + return I830Options; } return NULL; } static Bool -I830BIOSGetRec(ScrnInfoPtr pScrn) +I830GetRec(ScrnInfoPtr pScrn) { I830Ptr pI830; @@ -351,7 +351,7 @@ I830BIOSGetRec(ScrnInfoPtr pScrn) } static void -I830BIOSFreeRec(ScrnInfoPtr pScrn) +I830FreeRec(ScrnInfoPtr pScrn) { I830Ptr pI830; VESAPtr pVesa; @@ -398,7 +398,7 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn) } static void -I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index) +I830ProbeDDC(ScrnInfoPtr pScrn, int index) { vbeInfoPtr pVbe; @@ -1201,7 +1201,7 @@ PreInitCleanup(ScrnInfoPtr pScrn) } if (pI830->MMIOBase) I830UnmapMMIO(pScrn); - I830BIOSFreeRec(pScrn); + I830FreeRec(pScrn); } Bool @@ -1218,7 +1218,7 @@ I830IsPrimary(ScrnInfoPtr pScrn) } static Bool -I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) +I830PreInit(ScrnInfoPtr pScrn, int flags) { vgaHWPtr hwp; I830Ptr pI830; @@ -1252,7 +1252,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (flags & PROBE_DETECT) { - I830BIOSProbeDDC(pScrn, pEnt->index); + I830ProbeDDC(pScrn, pEnt->index); return TRUE; } @@ -1266,7 +1266,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; /* Allocate driverPrivate */ - if (!I830BIOSGetRec(pScrn)) + if (!I830GetRec(pScrn)) return FALSE; pI830 = I830PTR(pScrn); @@ -1355,9 +1355,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* Process the options */ xf86CollectOptions(pScrn, NULL); - if (!(pI830->Options = xalloc(sizeof(I830BIOSOptions)))) + if (!(pI830->Options = xalloc(sizeof(I830Options)))) return FALSE; - memcpy(pI830->Options, I830BIOSOptions, sizeof(I830BIOSOptions)); + memcpy(pI830->Options, I830Options, sizeof(I830Options)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options); /* We have to use PIO to probe, because we haven't mapped yet. */ @@ -1446,14 +1446,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pScrn->chipset = pI830->pEnt->device->chipset; from = X_CONFIG; } else if (pI830->pEnt->device->chipID >= 0) { - pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets, + pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, pI830->pEnt->device->chipID); from = X_CONFIG; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", pI830->pEnt->device->chipID); } else { from = X_PROBED; - pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets, + pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, pI830->PciInfo->chipType); } @@ -3238,7 +3238,7 @@ I830InitFBManager( } static Bool -I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn; vgaHWPtr hwp; @@ -3515,9 +3515,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* Clear SavedReg */ memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg)); - DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n"); + DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n"); - if (!I830BIOSEnterVT(scrnIndex, 0)) + if (!I830EnterVT(scrnIndex, 0)) return FALSE; DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); @@ -3628,9 +3628,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n"); #endif - pScreen->SaveScreen = I830BIOSSaveScreen; + pScreen->SaveScreen = I830SaveScreen; pI830->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = I830BIOSCloseScreen; + pScreen->CloseScreen = I830CloseScreen; if (pI830->shadowReq.minorversion >= 1) { /* Rotation */ @@ -3685,9 +3685,9 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) } static void -I830BIOSFreeScreen(int scrnIndex, int flags) +I830FreeScreen(int scrnIndex, int flags) { - I830BIOSFreeRec(xf86Screens[scrnIndex]); + I830FreeRec(xf86Screens[scrnIndex]); if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(xf86Screens[scrnIndex]); } @@ -3721,7 +3721,7 @@ RestoreHWOperatingState(ScrnInfoPtr pScrn) #endif static void -I830BIOSLeaveVT(int scrnIndex, int flags) +I830LeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); @@ -3927,7 +3927,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) * This gets called when gaining control of the VT, and from ScreenInit(). */ static Bool -I830BIOSEnterVT(int scrnIndex, int flags) +I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); @@ -4015,7 +4015,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) } static Bool -I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; @@ -4023,7 +4023,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) Bool ret = TRUE; PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen); - DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode); + DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode); #ifdef I830_XV /* Give the video overlay code a chance to see the new mode. */ @@ -4083,7 +4083,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } static Bool -I830BIOSSaveScreen(ScreenPtr pScreen, int mode) +I830SaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); @@ -4091,7 +4091,7 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) CARD32 temp, ctrl, base; int i; - DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); + DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { for (i = 0; i < pI830->availablePipes; i++) { @@ -4215,7 +4215,7 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, } static Bool -I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) +I830CloseScreen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); @@ -4230,7 +4230,7 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif if (pScrn->vtSema == TRUE) { - I830BIOSLeaveVT(scrnIndex, 0); + I830LeaveVT(scrnIndex, 0); } if (pI830->devicesTimer) @@ -4668,7 +4668,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) } pI830->currentMode = NULL; - I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); + I830SwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); if (xf86IsEntityShared(pScrn->entityList[0])) { @@ -4687,7 +4687,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) miPointerPosition(&x, &y); pI8302->currentMode = NULL; - I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); + I830SwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); @@ -4734,13 +4734,13 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) void I830InitpScrn(ScrnInfoPtr pScrn) { - pScrn->PreInit = I830BIOSPreInit; - pScrn->ScreenInit = I830BIOSScreenInit; - pScrn->SwitchMode = I830BIOSSwitchMode; + pScrn->PreInit = I830PreInit; + pScrn->ScreenInit = I830ScreenInit; + pScrn->SwitchMode = I830SwitchMode; pScrn->AdjustFrame = i830AdjustFrame; - pScrn->EnterVT = I830BIOSEnterVT; - pScrn->LeaveVT = I830BIOSLeaveVT; - pScrn->FreeScreen = I830BIOSFreeScreen; + pScrn->EnterVT = I830EnterVT; + pScrn->LeaveVT = I830LeaveVT; + pScrn->FreeScreen = I830FreeScreen; pScrn->ValidMode = I830ValidMode; pScrn->PMEvent = I830PMEvent; } From 2cd28be71472d67956f47c7d49283ebabefa089a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 08:55:55 -0700 Subject: [PATCH 156/257] Remove empty SAVERESTORE_HWSTATE code. --- src/i830.h | 1 - src/i830_driver.c | 40 ---------------------------------------- 2 files changed, 41 deletions(-) diff --git a/src/i830.h b/src/i830.h index 57d65065..9f65f882 100644 --- a/src/i830.h +++ b/src/i830.h @@ -337,7 +337,6 @@ typedef struct _I830Rec { int NumScanlineColorExpandBuffers; int nextColorExpandBuf; - I830RegRec SavedReg; I830RegRec ModeReg; Bool noAccel; diff --git a/src/i830_driver.c b/src/i830_driver.c index d21bf9f2..6000300a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3512,9 +3512,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!vgaHWMapMem(pScrn)) return FALSE; - /* Clear SavedReg */ - memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg)); - DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n"); if (!I830EnterVT(scrnIndex, 0)) @@ -3692,34 +3689,6 @@ I830FreeScreen(int scrnIndex, int flags) vgaHWFreeHWRec(xf86Screens[scrnIndex]); } -#ifndef SAVERESTORE_HWSTATE -#define SAVERESTORE_HWSTATE 0 -#endif - -#if SAVERESTORE_HWSTATE -static void -SaveHWOperatingState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830RegPtr save = &pI830->SavedReg; - - DPRINTF(PFX, "SaveHWOperatingState\n"); - - return; -} - -static void -RestoreHWOperatingState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830RegPtr save = &pI830->SavedReg; - - DPRINTF(PFX, "RestoreHWOperatingState\n"); - - return; -} -#endif - static void I830LeaveVT(int scrnIndex, int flags) { @@ -3760,11 +3729,6 @@ I830LeaveVT(int scrnIndex, int flags) } #endif -#if SAVERESTORE_HWSTATE - if (!pI830->closing) - SaveHWOperatingState(pScrn); -#endif - if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor) pI830->CursorInfoRec->HideCursor(pScrn); @@ -3982,10 +3946,6 @@ I830EnterVT(int scrnIndex, int flags) pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); -#if SAVERESTORE_HWSTATE - RestoreHWOperatingState(pScrn); -#endif - #ifdef XF86DRI if (pI830->directRenderingEnabled) { if (!pI830->starting) { From 20956a5d6f1eb518717a680e58938f31461ca5e4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 09:27:30 -0700 Subject: [PATCH 157/257] Remove unused display{Attached,Present} fields. --- src/i830.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9f65f882..3460c707 100644 --- a/src/i830.h +++ b/src/i830.h @@ -397,10 +397,6 @@ typedef struct _I830Rec { int toggleDevices; int lastDevice0, lastDevice1, lastDevice2; - /* These are indexed by the display types */ - Bool displayAttached[NumDisplayTypes]; - Bool displayPresent[NumDisplayTypes]; - /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; /* [0] is display plane A, [1] is display plane B. */ From b6ba268d0d5f22c6a18ce45416452fce83438620 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 09:31:37 -0700 Subject: [PATCH 158/257] Remove the no-longer-connected VBERestore option. --- man/i810.man | 7 ------- src/i830.h | 1 - src/i830_driver.c | 11 ----------- 3 files changed, 19 deletions(-) diff --git a/man/i810.man b/man/i810.man index f6b73689..3aaa165b 100644 --- a/man/i810.man +++ b/man/i810.man @@ -117,13 +117,6 @@ The following driver .B Options are supported for the 830M and later chipsets: .TP -.BI "Option \*qVBERestore\*q \*q" boolean \*q -Enable or disable the use of VBE save/restore for saving and restoring -the initial text mode. This is disabled by default because it causes -lockups on some platforms. However, there are some cases where it must -enabled for the correct restoration of the initial video mode. If you are -having a problem with that, try enabling this option. Default: Disabled. -.TP .BI "Option \*qVideoKey\*q \*q" integer \*q This is the same as the .B \*qColorKey\*q diff --git a/src/i830.h b/src/i830.h index 3460c707..35e0391d 100644 --- a/src/i830.h +++ b/src/i830.h @@ -416,7 +416,6 @@ typedef struct _I830Rec { int yoffset; unsigned int SaveGeneration; - Bool vbeRestoreWorkaround; Bool devicePresence; OsTimerPtr devicesTimer; diff --git a/src/i830_driver.c b/src/i830_driver.c index 6000300a..5e0cff6e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -260,7 +260,6 @@ static OptionInfoRec I830Options[] = { {OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, - {OPTION_VBE_RESTORE, "VBERestore", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0}, FALSE}, {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, @@ -2426,16 +2425,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pVbe = NULL; #endif - /* Use the VBE mode restore workaround by default. */ - pI830->vbeRestoreWorkaround = TRUE; - from = X_DEFAULT; - if (xf86ReturnOptValBool(pI830->Options, OPTION_VBE_RESTORE, FALSE)) { - pI830->vbeRestoreWorkaround = FALSE; - from = X_CONFIG; - } - xf86DrvMsg(pScrn->scrnIndex, from, "VBE Restore workaround: %s.\n", - pI830->vbeRestoreWorkaround ? "enabled" : "disabled"); - #if defined(XF86DRI) /* Load the dri module if requested. */ if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) && From c2446be9b444b16c95f78dab17bf130f9f491ee2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 09:38:11 -0700 Subject: [PATCH 159/257] Remove the GetDevicePresence BIOS call which just printed BIOS information. Because we aren't using the BIOS to set modes any more, what the BIOS thinks is present is probably even less important than before. --- man/i810.man | 7 ------- src/i830.h | 1 - src/i830_driver.c | 50 ----------------------------------------------- 3 files changed, 58 deletions(-) diff --git a/man/i810.man b/man/i810.man index 3aaa165b..59766a6e 100644 --- a/man/i810.man +++ b/man/i810.man @@ -172,13 +172,6 @@ NOTE: Using this option may cause text mode to be restored incorrectly, and thus should be used with caution. Default: disabled. .TP -.BI "Option \*qDevicePresence\*q \*q" boolean \*q -Tell the driver to perform an active detect of the currently connected -monitors. This option is useful if the monitor was not connected when -the machine has booted, but unfortunately it doesn't always work and -is extremely dependent upon the Video BIOS. -Default: disabled -.TP .BI "Option \*qRotate\*q \*q90\*q" Rotate the desktop 90 degrees counterclockwise. Other valid options are 0, 90, 180 and 270 degrees. The RandR extension is used for rotation diff --git a/src/i830.h b/src/i830.h index 35e0391d..9fc67122 100644 --- a/src/i830.h +++ b/src/i830.h @@ -416,7 +416,6 @@ typedef struct _I830Rec { int yoffset; unsigned int SaveGeneration; - Bool devicePresence; OsTimerPtr devicesTimer; int MaxClock; diff --git a/src/i830_driver.c b/src/i830_driver.c index 5e0cff6e..fd3bf2ee 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -260,7 +260,6 @@ static OptionInfoRec I830Options[] = { {OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, - {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0}, FALSE}, {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE}, @@ -623,31 +622,6 @@ GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) return FALSE; } -static Bool -GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached, - int *encoderPresent) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetDevicePresence\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x200; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - if (required) - *required = ((pVbe->pInt10->bx & 0x1) == 0); - if (attached) - *attached = (pVbe->pInt10->cx >> 8) & 0xff; - if (encoderPresent) - *encoderPresent = pVbe->pInt10->cx & 0xff; - return TRUE; - } else - return FALSE; -} - /* * Returns a string matching the device corresponding to the first bit set * in "device". savedDevice is then set to device with that bit cleared. @@ -2071,30 +2045,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } else pI830->newPipeSwitch = FALSE; - pI830->devicePresence = FALSE; - from = X_DEFAULT; - if (xf86ReturnOptValBool(pI830->Options, OPTION_DEVICE_PRESENCE, FALSE)) { - pI830->devicePresence = TRUE; - from = X_CONFIG; - } - xf86DrvMsg(pScrn->scrnIndex, from, "Device Presence: %s.\n", - pI830->devicePresence ? "enabled" : "disabled"); - - /* This performs an active detect of the currently attached monitors - * or, at least it's meant to..... alas it doesn't seem to always work. - */ - if (pI830->devicePresence) { - int req=0, att=0, enc=0; - GetDevicePresence(pScrn, &req, &att, &enc); - for (i = 0; i < NumDisplayTypes; i++) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Display Presence: %s: attached: %s, encoder: %s\n", - displayDevices[i], - BOOLTOSTRING(((1<>i), - BOOLTOSTRING(((1<>i)); - } - } - PrintDisplayDeviceInfo(pScrn); if (xf86IsEntityShared(pScrn->entityList[0])) { From c52242c22779a51aa12b18a7a589080ce44c8484 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 09:41:07 -0700 Subject: [PATCH 160/257] Remove some dead code related to clock ranges. --- src/i830.h | 1 - src/i830_driver.c | 2 -- src/i830_modes.c | 14 -------------- 3 files changed, 17 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9fc67122..53302ee4 100644 --- a/src/i830.h +++ b/src/i830.h @@ -418,7 +418,6 @@ typedef struct _I830Rec { unsigned int SaveGeneration; OsTimerPtr devicesTimer; - int MaxClock; int ddc2; int num_outputs; diff --git a/src/i830_driver.c b/src/i830_driver.c index fd3bf2ee..31e3b17e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2161,8 +2161,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum space available for video modes: %d kByte\n", memsize); - pI830->MaxClock = 300000; - n = I830ValidateXF86ModeList(pScrn, TRUE); if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); diff --git a/src/i830_modes.c b/src/i830_modes.c index 6bff1d0a..f1cdbe1f 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -1025,20 +1025,6 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) last->next = pScrn->modes; pScrn->modes->prev = last; -#if 0 - /* XXX: do I need this any more? Maybe XF86VidMode uses it? - * Set up the ClockRanges, which describe what clock ranges are available, - * and what sort of modes they can be used for. - */ - clockRanges = xnfcalloc(sizeof(ClockRange), 1); - clockRanges->next = NULL; - clockRanges->minClock = 25000; - clockRanges->maxClock = pI830->MaxClock; - clockRanges->clockIndex = -1; /* programmable */ - clockRanges->interlaceAllowed = TRUE; /* XXX check this */ - clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ -#endif - #if DEBUG_REPROBE xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n"); do { From 965609f6fa63e28e5a28128f5bc44f8c4d7b9f68 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Sep 2006 09:51:45 -0700 Subject: [PATCH 161/257] Restructure i830_bios.c so we don't leak a copy of the BIOS per generation. --- src/i830.h | 2 -- src/i830_bios.c | 76 +++++++++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/i830.h b/src/i830.h index 53302ee4..92c91114 100644 --- a/src/i830.h +++ b/src/i830.h @@ -442,8 +442,6 @@ typedef struct _I830Rec { Bool panel_wants_dither; - unsigned char *VBIOS; - CARD32 saveDSPACNTR; CARD32 saveDSPBCNTR; CARD32 savePIPEACONF; diff --git a/src/i830_bios.c b/src/i830_bios.c index 14e354ed..07dd67d4 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -38,21 +38,20 @@ #include "i830_bios.h" #include "edid.h" -#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr]) -#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \ - (pI830->VBIOS[_addr + 1] << 8)) -#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \ - (pI830->VBIOS[_addr + 1] << 8) \ - (pI830->VBIOS[_addr + 2] << 16) \ - (pI830->VBIOS[_addr + 3] << 24)) +#define INTEL_BIOS_8(_addr) (bios[_addr]) +#define INTEL_BIOS_16(_addr) (bios[_addr] | \ + (bios[_addr + 1] << 8)) +#define INTEL_BIOS_32(_addr) (bios[_addr] | \ + (bios[_addr + 1] << 8) \ + (bios[_addr + 2] << 16) \ + (bios[_addr + 3] << 24)) /* XXX */ #define INTEL_VBIOS_SIZE (64 * 1024) static void -i830DumpBIOSToFile(ScrnInfoPtr pScrn) +i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios) { - I830Ptr pI830 = I830PTR(pScrn); const char *filename = "/tmp/xf86-video-intel-VBIOS"; FILE *f; @@ -61,7 +60,7 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename); return; } - if (fwrite(pI830->VBIOS, INTEL_VBIOS_SIZE, 1, f) != 1) { + if (fwrite(bios, INTEL_VBIOS_SIZE, 1, f) != 1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n"); } @@ -78,48 +77,46 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn) * feed an updated VBT back through that, compared to what we'll fetch using * this method of groping around in the BIOS data. */ -static Bool +static unsigned char * i830GetBIOS(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); struct vbt_header *vbt; int vbt_off; + unsigned char *bios; - if (pI830->VBIOS != NULL) - return TRUE; - - pI830->VBIOS = xalloc(INTEL_VBIOS_SIZE); - if (pI830->VBIOS == NULL) - return FALSE; + bios = xalloc(INTEL_VBIOS_SIZE); + if (bios == NULL) + return NULL; if (pI830->pVbe != NULL) { - memcpy(pI830->VBIOS, xf86int10Addr(pI830->pVbe->pInt10, + memcpy(bios, xf86int10Addr(pI830->pVbe->pInt10, pI830->pVbe->pInt10->BIOSseg << 4), INTEL_VBIOS_SIZE); } else { - xf86ReadPciBIOS(0, pI830->PciTag, 0, pI830->VBIOS, INTEL_VBIOS_SIZE); + xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE); } if (0) - i830DumpBIOSToFile(pScrn); + i830DumpBIOSToFile(pScrn, bios); vbt_off = INTEL_BIOS_16(0x1a); if (vbt_off >= INTEL_VBIOS_SIZE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", vbt_off); - xfree(pI830->VBIOS); - return FALSE; + xfree(bios); + return NULL; } - vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); + vbt = (struct vbt_header *)(bios + vbt_off); if (memcmp(vbt->signature, "$VBT", 4) != 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n"); - xfree(pI830->VBIOS); - return FALSE; + xfree(bios); + return NULL; } - return TRUE; + return bios; } Bool @@ -130,18 +127,22 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) struct bdb_header *bdb; int vbt_off, bdb_off, bdb_block_off, block_size; int panel_type = -1; + unsigned char *bios; Bool found_panel_info = FALSE; - if (!i830GetBIOS(pScrn)) + bios = i830GetBIOS(pScrn); + + if (bios == NULL) return FALSE; vbt_off = INTEL_BIOS_16(0x1a); - vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off); + vbt = (struct vbt_header *)(bios + vbt_off); bdb_off = vbt_off + vbt->bdb_offset; - bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off); + bdb = (struct bdb_header *)(bios + bdb_off); if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n"); + xfree(bios); return FALSE; } @@ -161,7 +162,7 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id); switch (id) { case 40: - lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start); + lvds1 = (struct lvds_bdb_1 *)(bios + start); panel_type = lvds1->panel_type; if (lvds1->caps & LVDS_CAP_DITHER) pI830->panel_wants_dither = TRUE; @@ -170,23 +171,23 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) if (panel_type == -1) break; - lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start); - fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + lvds2 = (struct lvds_bdb_2 *)(bios + start); + fpparam = (struct lvds_bdb_2_fp_params *)(bios + bdb_off + lvds2->panels[panel_type].fp_params_offset); - fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset); - timing_ptr = pI830->VBIOS + bdb_off + + timing_ptr = bios + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset; if (fpparam->terminator != 0xffff) { /* Apparently the offsets are wrong for some BIOSes, so we * try the other offsets if we find a bad terminator. */ - fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS + + fpparam = (struct lvds_bdb_2_fp_params *)(bios + bdb_off + lvds2->panels[panel_type].fp_params_offset + 8); - fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS + + fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8); - timing_ptr = pI830->VBIOS + bdb_off + + timing_ptr = bios + bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8; if (fpparam->terminator != 0xffff) @@ -218,5 +219,6 @@ i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn) } } + xfree(bios); return found_panel_info; } From c34490bbda6604a21809d15c798607806fa6c725 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Sep 2006 12:00:43 +0100 Subject: [PATCH 162/257] Construct default monitor description for hotplug non-DDC monitor. When detecting a monitor that doesn't support DDC, construct a default monitor with "sensible" values instead of using whatever the builtin LCD screen uses. Clearly we need a way to set the monitor parameters when we cannot detect them. --- src/i830_display.c | 2 +- src/i830_modes.c | 38 ++++++++++++++++++++++++++++++++++++-- src/i830_randr.c | 8 ++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 24ce50f7..88280bb3 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1081,7 +1081,7 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb) * pipe, as it seems having other outputs on that pipe will result in a * false positive. */ - if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { + if (1 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { return i830LoadDetectCRT(pScrn); } diff --git a/src/i830_modes.c b/src/i830_modes.c index 3b70d5d4..3d2b8f31 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -685,6 +685,36 @@ i830GetConfiguredMonitor(ScrnInfoPtr pScrn) return mon; } +static MonPtr +i830GetDefaultMonitor(ScrnInfoPtr pScrn) +{ + MonPtr mon; + + mon = xnfcalloc(1, sizeof(*mon)); + + mon->id = xnfstrdup("Unknown Id"); + mon->vendor = xnfstrdup("Unknown Vendor"); + mon->model = xnfstrdup("Unknown Model"); + + mon->nHsync = 1; + mon->hsync[0].lo = 31.0; + mon->hsync[0].hi = 100.0; + mon->nVrefresh = 1; + mon->vrefresh[0].lo = 50.0; + mon->vrefresh[0].hi = 70.0; + mon->widthmm = 400; + mon->heightmm = 300; + /* Use VESA standard and user modelines, and do additional validation + * on them beyond what pipe config will do (x/y/pitch, clocks, flags) + */ + mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); + i830xf86ValidateModesSync(pScrn, mon->Modes, mon); + i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE); + mon->Last = i830GetModeListTail(mon->Modes); + + return mon; +} + static void i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon) { @@ -771,8 +801,12 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) * know if a monitor is attached, and this detect process should be * infrequent. */ - if (i830DetectCRT(pScrn, TRUE)) - pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); + if (i830DetectCRT(pScrn, TRUE)) { +/* if (pipe == pI830->pipe) + pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); + else */ + pI830->pipeMon[pipe] = i830GetDefaultMonitor(pScrn); + } break; default: pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); diff --git a/src/i830_randr.c b/src/i830_randr.c index 7c67aea2..d86911ce 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -773,7 +773,15 @@ static Bool I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int found_crt; + /* Re-probe the outputs for new monitors or modes */ + pI830->operatingDevices = pI830->operatingDevices & ~PIPE_CRT; + found_crt = i830DetectCRT(pScrn, FALSE); + if (found_crt) + pI830->operatingDevices = pI830->operatingDevices | PIPE_CRT; + I830ValidateXF86ModeList(pScrn, FALSE); return I830RandRSetInfo12 (pScreen); } From 4bd3b89c73b6c5aa9b0eb553ad5d553ee0e8a489 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Sep 2006 16:41:38 +0100 Subject: [PATCH 163/257] Oops, duplicated CRT-redetect code. --- src/i830_randr.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index d86911ce..d9731733 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -776,12 +776,6 @@ I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) I830Ptr pI830 = I830PTR(pScrn); int found_crt; - /* Re-probe the outputs for new monitors or modes */ - pI830->operatingDevices = pI830->operatingDevices & ~PIPE_CRT; - found_crt = i830DetectCRT(pScrn, FALSE); - if (found_crt) - pI830->operatingDevices = pI830->operatingDevices | PIPE_CRT; - I830ValidateXF86ModeList(pScrn, FALSE); return I830RandRSetInfo12 (pScreen); } From 117ff04b504578a24dff70659e2db1b81aaa1177 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 21 Sep 2006 17:03:34 -0700 Subject: [PATCH 164/257] Attempt to make the ACPI hotkey support a little more modesetting-compatible. Previously, we watched for the BIOS to have changed the layout, and repaired the resulting configuration. Now, we request that the BIOS make no changes, but leave a note in a register for when the key has been pressed. When we notice this, we reprobe monitors and turn on/off the things we find. This is a temporary solution until we can get the hotkey hooked up as an input key to external applications to control the change using RandR 1.2. It is also untested as neither of my laptops do anything with the hotkey. However, this code does result in many fewer BIOS calls. --- src/i810_reg.h | 4 + src/i830.h | 3 - src/i830_driver.c | 517 ++++++---------------------------------------- 3 files changed, 71 insertions(+), 453 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 275d858c..3a15a464 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -94,6 +94,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define LINEAR_MODE_ENABLE 0x02 #define PAGE_MAPPING_ENABLE 0x01 +#define HOTKEY_VBIOS_SWITCH_BLOCK 0x80 +#define HOTKEY_SWITCH 0x20 +#define HOTKEY_TOGGLE 0x10 + /* Blitter control, p378 */ #define BITBLT_CNTL 0x7000c diff --git a/src/i830.h b/src/i830.h index 3a939312..4a95441c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -393,10 +393,7 @@ typedef struct _I830Rec { CARD32 saveSWF4; Bool checkDevices; - int monitorSwitch; int operatingDevices; - int toggleDevices; - int lastDevice0, lastDevice1, lastDevice2; /* These are indexed by the display types */ Bool displayAttached[NumDisplayTypes]; diff --git a/src/i830_driver.c b/src/i830_driver.c index 75ea480c..c3ae8c30 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -438,116 +438,6 @@ Check5fStatus(ScrnInfoPtr pScrn, int func, int ax) } } -static int -GetToggleList(ScrnInfoPtr pScrn, int toggle) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetToggleList\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x500; - - pVbe->pInt10->bx |= toggle; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx); - return pVbe->pInt10->cx & 0xffff; - } - - return 0; -} - -static int -GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - int devices = 0; - int pipe = 0; - int i; - - DPRINTF(PFX, "GetNextDisplayDeviceList\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0xA00; - pVbe->pInt10->bx |= toggle; - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) - return 0; - - for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) { - CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i]; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n", - i, (unsigned long) VODA); - - /* Check if it's a custom Video Output Device Attribute */ - if (!(VODA & 0x80000000)) - continue; - - pipe = (VODA & 0x000000F0) >> 4; - - if (pipe != 0 && pipe != 1) { - pipe = 0; -#if 0 - ErrorF("PIPE %d\n",pipe); -#endif - } - - switch ((VODA & 0x00000F00) >> 8) { - case 0x0: - case 0x1: /* CRT */ - devices |= PIPE_CRT << (pipe == 1 ? 8 : 0); - break; - case 0x2: /* TV/HDTV */ - devices |= PIPE_TV << (pipe == 1 ? 8 : 0); - break; - case 0x3: /* DFP */ - devices |= PIPE_DFP << (pipe == 1 ? 8 : 0); - break; - case 0x4: /* LFP */ - devices |= PIPE_LFP << (pipe == 1 ? 8 : 0); - break; - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle devices 0x%x\n", devices); - - return devices; -} - -static int -GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - int i; - - DPRINTF(PFX, "GetAttachableDisplayDeviceList\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f64; - pVbe->pInt10->bx = 0x900; - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) - return 0; - - for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attachable device 0x%lx.\n", - (unsigned long) ((CARD32*)pVbe->memory)[i]); - - return pVbe->pInt10->cx & 0xffff; -} - struct panelid { short hsize; short vsize; @@ -1217,6 +1107,31 @@ I830IsPrimary(ScrnInfoPtr pScrn) return TRUE; } +#define HOTKEY_BIOS_SWITCH 0 +#define HOTKEY_DRIVER_NOTIFY 1 + +/** + * Controls the BIOS's behavior on hotkey switch. + * + * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch + * on its own and update the state in the scratch register. + * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and + * will just update the state to represent what it would have been switched to. + */ +static void +i830SetHotkeyControl(ScrnInfoPtr pScrn, int mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD8 gr18; + + gr18 = pI830->readControl(pI830, GRX, 0x18); + if (mode == HOTKEY_BIOS_SWITCH) + gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK; + else + gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK; + pI830->writeControl(pI830, GRX, 0x18, gr18); +} + static Bool I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) { @@ -2179,28 +2094,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - /* XXX Move this to a header. */ -#define VIDEO_BIOS_SCRATCH 0x18 - -#if 1 - /* - * XXX This should be in ScreenInit/EnterVT. PreInit should not leave the - * state changed. - */ - /* Enable hot keys by writing the proper value to GR18 */ - { - CARD8 gr18; - - gr18 = pI830->readControl(pI830, GRX, VIDEO_BIOS_SCRATCH); - gr18 &= ~0x80; /* - * Clear Hot key bit so that Video - * BIOS performs the hot key - * servicing - */ - pI830->writeControl(pI830, GRX, VIDEO_BIOS_SCRATCH, gr18); - } -#endif - /* * Limit videoram available for mode selection to what the video * BIOS can see. @@ -3734,6 +3627,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags) TimerCancel(pI830->devicesTimer); pI830->devicesTimer = NULL; + i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH); + #ifdef I830_XV /* Give the video overlay code a chance to shutdown. */ I830VideoSwitchModeBefore(pScrn, NULL); @@ -3951,9 +3846,6 @@ I830BIOSEnterVT(int scrnIndex, int flags) pScrn->virtualY * pScrn->displayWidth * pI830->cpp); #endif - /* Setup for device monitoring status */ - pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF; - if (I830IsPrimary(pScrn)) if (!I830BindAGPMemory(pScrn)) return FALSE; @@ -4003,6 +3895,13 @@ I830BIOSEnterVT(int scrnIndex, int flags) } #endif + /* Set the hotkey to just notify us. We can check its results periodically + * in the CheckDevicesTimer. Eventually we want the kernel to just hand us + * an input event when someone presses the button, but for now we just have + * to poll. + */ + i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY); + if (pI830->checkDevices) pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn); @@ -4367,15 +4266,6 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo) ErrorF("I830PMEvent: Capability change\n"); - /* ACPI Toggle */ - pI830->toggleDevices = GetNextDisplayDeviceList(pScrn, 1); - if (xf86IsEntityShared(pScrn->entityList[0])) { - I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - pI8302->toggleDevices = pI830->toggleDevices; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle to 0x%x\n",pI830->toggleDevices); - I830CheckDevicesTimer(NULL, 0, pScrn); SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); break; @@ -4385,27 +4275,16 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo) return TRUE; } -static int CountBits(int a) -{ - int i; - int b = 0; - - for (i=0;i<8;i++) { - if (a & (1<vtSema) @@ -4431,303 +4310,41 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n", found_sdvo ? "connected" : "disconnected", finish - start); } +} #endif - if (pScrn->vtSema) { - /* Check for monitor lid being closed/opened and act accordingly */ - CARD32 adjust; - CARD32 temp = INREG(SWF0) & 0x0000FFFF; - int fixup = 0; - I830Ptr pI8301; - I830Ptr pI8302 = NULL; +static CARD32 +I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) +{ + ScrnInfoPtr pScrn = (ScrnInfoPtr) arg; + I830Ptr pI830 = I830PTR(pScrn); + CARD8 gr18; - if (I830IsPrimary(pScrn)) - pI8301 = pI830; - else - pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - - if (xf86IsEntityShared(pScrn->entityList[0])) - pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - - /* this avoids several BIOS calls if possible */ - if (pI830->monitorSwitch != temp || pI830->monitorSwitch != pI830->toggleDevices) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Hotkey switch to 0x%lx.\n", (unsigned long) temp); - - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - if (xf86IsEntityShared(pScrn->entityList[0])) - pI8302->AccelInfoRec->NeedToSync = FALSE; - } - - GetAttachableDisplayDeviceList(pScrn); - - pI8301->lastDevice0 = pI8301->lastDevice1; - pI8301->lastDevice1 = pI8301->lastDevice2; - pI8301->lastDevice2 = pI8301->monitorSwitch; - - if (temp != pI8301->lastDevice1 && - temp != pI8301->lastDevice2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected three device configs.\n"); - } else - if (CountBits(temp & 0xff) > 1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected cloned pipe mode (A).\n"); - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) - temp = pI8301->MonType2 << 8 | pI8301->MonType1; - } else - if (CountBits((temp & 0xff00) >> 8) > 1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected cloned pipe mode (B).\n"); - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) - temp = pI8301->MonType2 << 8 | pI8301->MonType1; - } else - if (pI8301->lastDevice1 && pI8301->lastDevice2) { - if ( ((pI8301->lastDevice1 & 0xFF00) == 0) && - ((pI8301->lastDevice2 & 0x00FF) == 0) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected last devices (1).\n"); - cloned = 1; - } else if ( ((pI8301->lastDevice2 & 0xFF00) == 0) && - ((pI8301->lastDevice1 & 0x00FF) == 0) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected last devices (2).\n"); - cloned = 1; - } else - cloned = 0; - } - - if (cloned && - ((CountBits(pI8301->lastDevice1 & 0xff) > 1) || - ((CountBits((pI8301->lastDevice1 & 0xff00) >> 8) > 1))) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected duplicate (1).\n"); - cloned = 0; - } else - if (cloned && - ((CountBits(pI8301->lastDevice2 & 0xff) > 1) || - ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected duplicate (2).\n"); - cloned = 0; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Requested display devices 0x%lx.\n", - (unsigned long) temp); - - - /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake - * it here as it seems some just flip between CRT and LFP. Ugh! - * - * So this pushes them onto Pipe B and clones the displays, which - * is what most BIOS' should be doing. - * - * Cloned pipe mode should only be done when running single head. - */ - if (xf86IsEntityShared(pScrn->entityList[0])) { - cloned = 0; - - /* Some BIOS' don't realize we may be in true dual head mode. - * And only display the primary output on both when switching. - * We detect this here and cycle back to both pipes. - */ - if ((pI830->lastDevice0 == temp) && - ((CountBits(pI8301->lastDevice2 & 0xff) > 1) || - ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected cloned pipe mode when dual head on previous switch. (0x%x -> 0x%x)\n", (int)temp, pI8301->MonType2 << 8 | pI8301->MonType1); - temp = pI8301->MonType2 << 8 | pI8301->MonType1; - } - - } - - if (cloned) { - if (pI830->Clone) - temp = pI8301->MonType2 << 8 | pI8301->MonType1; - else if (pI8301->lastDevice1 & 0xFF) - temp = pI8301->lastDevice1 << 8 | pI8301->lastDevice2; - else - temp = pI8301->lastDevice2 << 8 | pI8301->lastDevice1; - } - - /* Jump to our next mode if we detect we've been here before */ - if (temp == pI8301->lastDevice1 || temp == pI8301->lastDevice2) { - temp = GetToggleList(pScrn, 1); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected duplicate devices. Toggling (0x%lx)\n", - (unsigned long) temp); - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected display change operation (0x%x, 0x%x, 0x%lx).\n", - pI8301->lastDevice1, pI8301->lastDevice2, - (unsigned long) temp); - - /* So that if we close on the wrong config, we restore correctly */ - pI830->specifiedMonitor = TRUE; - - if (!xf86IsEntityShared(pScrn->entityList[0])) { - if ((temp & 0xFF00) && (temp & 0x00FF)) { - pI830->Clone = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n"); - } else { - pI830->Clone = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clearing Clone mode\n"); - } - } - - { - /* Turn Cursor off before switching */ - Bool on = pI830->cursorOn; - if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor) - pI830->CursorInfoRec->HideCursor(pScrn); - pI830->cursorOn = on; - } - -#if 0 /* Disable -- I'll need to look at this whole function later. */ - /* double check the display devices are what's configured and try - * not to do it twice because of dual heads with the code above */ - if (!SetDisplayDevices(pScrn, temp)) { - if ( cloned && - ((CountBits(temp & 0xff) > 1) || - (CountBits((temp & 0xff00) >> 8) > 1)) ) { - temp = pI8301->lastDevice2 | pI8301->lastDevice1; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, " - "trying dual pipe clone mode (0x%lx)\n", - (unsigned long) temp); - if (!SetDisplayDevices(pScrn, temp)) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch " - "to configured display devices (0x%lx).\n", - (unsigned long) temp); - else { - pI830->Clone = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n"); - } - } - } -#endif - - pI8301->monitorSwitch = temp; - pI8301->operatingDevices = temp; - pI8301->toggleDevices = temp; - - if (xf86IsEntityShared(pScrn->entityList[0])) { - pI8302->operatingDevices = pI8301->operatingDevices; - pI8302->monitorSwitch = pI8301->monitorSwitch; - pI8302->toggleDevices = pI8301->toggleDevices; - } - - fixup = 1; + if (!pScrn->vtSema) + return 1000; #if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "ACPI _DGS queried devices is 0x%x, but probed is 0x%x monitorSwitch=0x%x\n", - pI830->toggleDevices, INREG(SWF0), pI830->monitorSwitch); + i830MonitorDetectDebugger(pScrn); #endif - } else { - int offset = -1; - if (I830IsPrimary(pScrn)) - offset = pI8301->FrontBuffer.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp); - else { - offset = pI8301->FrontBuffer2.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp); - } - if (pI830->pipe == 0) - adjust = INREG(DSPABASE); - else - adjust = INREG(DSPBBASE); + /* Check for a hotkey press report from the BIOS. */ + gr18 = pI830->readControl(pI830, GRX, 0x18); + if ((gr18 & (HOTKEY_TOGGLE | HOTKEY_SWITCH)) != 0) { + /* The user has pressed the hotkey requesting a toggle or switch. + * Re-probe our connected displays and turn on whatever we find. + * + * In the future, we want the hotkey to dump down to a user app which + * implements a sensible policy using RandR-1.2. For now, all we get + * is this. + */ + I830ValidateXF86ModeList(pScrn, FALSE); + xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); - if (adjust != offset) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Fixing display offsets.\n"); - - i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); - } - } - - if (fixup) { - ScreenPtr pCursorScreen; - int x = 0, y = 0; - - - pCursorScreen = miPointerCurrentScreen(); - if (pScrn->pScreen == pCursorScreen) - miPointerPosition(&x, &y); - - /* Now, when we're single head, make sure we switch pipes */ - if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) || cloned) { - if (temp & 0xFF00) - pI830->pipe = 1; - else - pI830->pipe = 0; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A"); - } - - pI830->currentMode = NULL; - I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); - i830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); - - if (xf86IsEntityShared(pScrn->entityList[0])) { - ScrnInfoPtr pScrn2; - I830Ptr pI8302; - - if (I830IsPrimary(pScrn)) { - pScrn2 = pI830->entityPrivate->pScrn_2; - pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); - } else { - pScrn2 = pI830->entityPrivate->pScrn_1; - pI8302 = I830PTR(pI830->entityPrivate->pScrn_1); - } - - if (pScrn2->pScreen == pCursorScreen) - miPointerPosition(&x, &y); - - pI8302->currentMode = NULL; - I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); - i830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); - - (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); - (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); - - if (pScrn2->pScreen == pCursorScreen) { - int sigstate = xf86BlockSIGIO (); - miPointerWarpCursor(pScrn2->pScreen,x,y); - - /* xf86Info.currentScreen = pScrn->pScreen; */ - xf86UnblockSIGIO (sigstate); - if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) { - pI8302->CursorInfoRec->HideCursor(pScrn); - xf86SetCursor(pScrn2->pScreen, pI830->pCurs, x, y); - pI8302->CursorInfoRec->ShowCursor(pScrn); - pI8302->cursorOn = TRUE; - } - } - } - - (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE); - (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE); - - if (pScrn->pScreen == pCursorScreen) { - int sigstate = xf86BlockSIGIO (); - miPointerWarpCursor(pScrn->pScreen,x,y); - - /* xf86Info.currentScreen = pScrn->pScreen; */ - xf86UnblockSIGIO (sigstate); - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { - pI830->CursorInfoRec->HideCursor(pScrn); - xf86SetCursor(pScrn->pScreen, pI830->pCurs, x, y); - pI830->CursorInfoRec->ShowCursor(pScrn); - pI830->cursorOn = TRUE; - } - } - } + /* Clear the BIOS's hotkey press flags */ + gr18 &= ~(HOTKEY_TOGGLE | HOTKEY_SWITCH); + pI830->writeControl(pI830, GRX, 0x18, gr18); } - return 1000; } From fdb6de663579d3b9f31bf9e8a93430b8505ca73f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Sep 2006 13:59:41 -0700 Subject: [PATCH 165/257] Re-disable broken load-based CRT detection. --- src/i830_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 88280bb3..24ce50f7 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1081,7 +1081,7 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb) * pipe, as it seems having other outputs on that pipe will result in a * false positive. */ - if (1 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { + if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { return i830LoadDetectCRT(pScrn); } From 3e6f81f70f65a5ba6b5c3a4e0eeaf67776a5f54d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Oct 2006 09:53:57 -0700 Subject: [PATCH 166/257] Move cursor base address register setting to a separate function. --- src/i830_cursor.c | 102 +++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 73 deletions(-) diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 55bbe6a2..92239f1b 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -79,6 +79,28 @@ static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs); static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); #endif +static void +I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); + I830MemRange *cursor_mem; + + if (pipe >= pI830->availablePipes) + FatalError("Bad pipe number for cursor base setting\n"); + + if (pI830->CursorIsARGB) + cursor_mem = pI830->CursorMemARGB; + else + cursor_mem = pI830->CursorMem; + + if (pI830->CursorNeedsPhysical) { + OUTREG(cursor_base, cursor_mem->Physical); + } else { + OUTREG(cursor_base, cursor_mem->Start); + } +} + void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) { @@ -93,17 +115,11 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) if (show && (force || !pI830->cursorShown[pipe])) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - int cursor_control, cursor_base; + int cursor_control; if (pipe == 0) - { cursor_control = CURSOR_A_CONTROL; - cursor_base = CURSOR_A_BASE; - } else - { cursor_control = CURSOR_B_CONTROL; - cursor_base = CURSOR_B_BASE; - } temp = INREG(cursor_control); temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) { @@ -116,17 +132,6 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp |= (pipe << 28); /* Connect to correct pipe */ /* Need to set mode, then address. */ OUTREG(cursor_control, temp); - if (pI830->CursorNeedsPhysical) { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Physical); - else - OUTREG(cursor_base, pI830->CursorMem->Physical); - } else { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Start); - else - OUTREG(cursor_base, pI830->CursorMem->Start); - } } else { temp = INREG(CURSOR_CONTROL); temp &= ~(CURSOR_FORMAT_MASK); @@ -138,10 +143,6 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); - else - OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); } pI830->cursorShown[pipe] = TRUE; } @@ -149,33 +150,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - int cursor_control, cursor_base; + int cursor_control; if (pipe == 0) - { cursor_control = CURSOR_A_CONTROL; - cursor_base = CURSOR_A_BASE; - } else - { cursor_control = CURSOR_B_CONTROL; - cursor_base = CURSOR_B_BASE; - } temp = INREG(cursor_control); temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); temp |= CURSOR_MODE_DISABLE; OUTREG(cursor_control, temp); - /* This is needed to flush the above change. */ - if (pI830->CursorNeedsPhysical) { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Physical); - else - OUTREG(cursor_base, pI830->CursorMem->Physical); - } else { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Start); - else - OUTREG(cursor_base, pI830->CursorMem->Start); - } } else { temp = INREG(CURSOR_CONTROL); temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); @@ -183,6 +166,9 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) } pI830->cursorShown[pipe] = FALSE; } + + /* Flush cursor changes. */ + I830SetPipeCursorBase(pScrn, pipe); } void @@ -199,7 +185,6 @@ I830InitHWCursor(ScrnInfoPtr pScrn) for (i = 0; i < MAX_DISPLAY_PIPES; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; - int cursor_base = i == 0 ? CURSOR_A_BASE : CURSOR_B_BASE; temp = INREG(cursor_control); temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL | @@ -211,17 +196,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) temp |= CURSOR_MODE_64_4C_AX; /* Need to set control, then address. */ OUTREG(cursor_control, temp); - if (pI830->CursorNeedsPhysical) { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Physical); - else - OUTREG(cursor_base, pI830->CursorMem->Physical); - } else { - if (pI830->CursorIsARGB) - OUTREG(cursor_base, pI830->CursorMemARGB->Start); - else - OUTREG(cursor_base, pI830->CursorMem->Start); - } + I830SetPipeCursorBase(pScrn, i); } } else { temp = INREG(CURSOR_CONTROL); @@ -234,10 +209,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ - if (pI830->CursorIsARGB) - OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); - else - OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); + I830SetPipeCursorBase(pScrn, 0); temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) | ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT); OUTREG(CURSOR_SIZE, temp); @@ -555,22 +527,6 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) pI830->cursorInRange[pipe] = inrange; I830SetPipeCursor (pScrn, pipe, FALSE); - - /* have to upload the base for the new position */ - if (IS_I9XX(pI830)) { - int base = pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE; - if (pI830->CursorNeedsPhysical) { - if (pI830->CursorIsARGB) - OUTREG(base, pI830->CursorMemARGB->Physical); - else - OUTREG(base, pI830->CursorMem->Physical); - } else { - if (pI830->CursorIsARGB) - OUTREG(base, pI830->CursorMemARGB->Start); - else - OUTREG(base, pI830->CursorMem->Start); - } - } } } From 33629ed304b64e45d5640397bd1807c5a98907d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Oct 2006 09:39:22 -0700 Subject: [PATCH 167/257] Always register list of modes for outputs, even when disabled. --- src/i830_randr.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index d9731733..7abfb3b4 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -614,6 +614,9 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int pipe_type; int pipe; int subpixel; + DisplayModePtr modes, mode; + xRRModeInfo modeInfo; + RRModePtr rrmode, *rrmodes; if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -689,24 +692,22 @@ I830RandRSetInfo12 (ScreenPtr pScreen) RROutputSetCrtc (randrp->outputs[i], crtc); - if (pipe >= 0) + nmode = 0; + rrmodes = NULL; + if (pipe >= 0) { - MonPtr mon = pI830->pipeMon[pipe]; - DisplayModePtr mode; - xRRModeInfo modeInfo; - RRModePtr rrmode; - - nmode = 0; - for (mode = mon->Modes; mode; mode = mode->next) + modes = pI830->pipeMon[pipe]->Modes; + + for (mode = modes; mode; mode = mode->next) nmode++; - + if (nmode) { - modes = xalloc (nmode * sizeof (RRModePtr)); - if (!modes) + rrmodes = xalloc (nmode * sizeof (RRModePtr)); + if (!rrmodes) return FALSE; nmode = 0; - for (mode = mon->Modes; mode; mode = mode->next) + for (mode = modes; mode; mode = mode->next) { modeInfo.nameLength = strlen (mode->name); modeInfo.mmWidth = mon->widthmm; @@ -728,17 +729,19 @@ I830RandRSetInfo12 (ScreenPtr pScreen) rrmode = RRModeGet (pScreen, &modeInfo, mode->name); rrmode->devPrivate = mode; if (rrmode) - modes[nmode++] = rrmode; + rrmodes[nmode++] = rrmode; } - if (!RROutputSetModes (randrp->outputs[i], modes, nmode)) - { - xfree (modes); - return FALSE; - } - - xfree (modes); } } + + if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode)) + { + xfree (rrmodes); + return FALSE; + } + + xfree (rrmodes); + connection = RR_Disconnected; if (pipe >= 0) connection = RR_Connected; From 1bc1cedbcdf6ea4d2a3e8b07b553ac50b3c126f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Oct 2006 22:00:14 -0700 Subject: [PATCH 168/257] Enable XV_PORT attribute even when not in Clone mode. As Clone mode is now something that can change after server startup, always enable the XV_PORT attribute as we cannot change the list of reported attributes. --- src/i830_video.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 83c032bc..6a18f932 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -689,8 +689,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) adapt->pPortPrivates[0].ptr = (pointer) (pPriv); adapt->nAttributes = NUM_ATTRIBUTES; - if (pI830->Clone) - adapt->nAttributes += CLONE_ATTRIBUTES; + adapt->nAttributes += CLONE_ATTRIBUTES; if (IS_I9XX(pI830)) adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */ adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes); @@ -698,10 +697,8 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) att = adapt->pAttributes; memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES); att+=NUM_ATTRIBUTES; - if (pI830->Clone) { - memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES); - att+=CLONE_ATTRIBUTES; - } + memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES); + att+=CLONE_ATTRIBUTES; if (IS_I9XX(pI830)) { memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES); att+=GAMMA_ATTRIBUTES; @@ -764,8 +761,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ - if (pI830->Clone) - xvPipe = MAKE_ATOM("XV_PIPE"); + xvPipe = MAKE_ATOM("XV_PIPE"); if (IS_I9XX(pI830)) { xvGamma0 = MAKE_ATOM("XV_GAMMA0"); @@ -1073,7 +1069,7 @@ I830GetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->contrast; } else if (attribute == xvSaturation) { *value = pPriv->saturation; - } else if (pI830->Clone && attribute == xvPipe) { + } else if (attribute == xvPipe) { *value = pPriv->pipe; } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { *value = pPriv->gamma0; From 5a060002487e16c53dc96e32af72cd1bfcf6a227 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Oct 2006 18:43:07 -0700 Subject: [PATCH 169/257] Add mode origins for randr --- src/i830_modes.c | 14 +++++++------- src/i830_randr.c | 26 +++++++++++++++++++++----- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index da1ccde8..ac7c4c51 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -290,7 +290,10 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) new->Clock = d_timings->clock / 1000; new->Flags = (d_timings->interlaced ? V_INTERLACE : 0); new->status = MODE_OK; - new->type = M_T_DEFAULT; + if (PREFERRED_TIMING_MODE(ddc->features.msc)) + new->type = M_T_PREFERRED; + else + new->type = M_T_DRIVER; i830xf86SetModeDefaultName(new); @@ -419,7 +422,7 @@ i830FPNativeMode(ScrnInfoPtr pScrn) new->VTotal = new->VSyncEnd + 1; new->Clock = pI830->panel_fixed_clock; - new->type = M_T_USERDEF; + new->type = M_T_PREFERRED; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No valid mode specified, force to native mode\n"); @@ -475,7 +478,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) } new = i830GetGTF(width, height, 60.0, FALSE, FALSE); - new->type |= M_T_USERDEF; + new->type |= M_T_DEFAULT; new->next = NULL; new->prev = last; @@ -510,10 +513,7 @@ i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) } if (!tmp) { new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE); - if (ppModeName[i] == NULL) - new->type |= M_T_USERDEF; - else - new->type |= M_T_DEFAULT; + new->type |= M_T_DEFAULT; I830xf86SortModes(new, &first, &last); diff --git a/src/i830_randr.c b/src/i830_randr.c index 7abfb3b4..37bd6a10 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -542,7 +542,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, int y, Rotation rotation, int numOutputs, - RROutputPtr *outputs) + RROutputConfigPtr outputs) { XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -603,7 +603,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int nclone; RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; int ncrtc; - RRModePtr *modes; int nmode; struct _I830OutputRec *output; int i; @@ -617,6 +616,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen) DisplayModePtr modes, mode; xRRModeInfo modeInfo; RRModePtr rrmode, *rrmodes; + CARD32 possibleOptions = 0; + CARD32 currentOptions = 0; if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -655,6 +656,10 @@ I830RandRSetInfo12 (ScreenPtr pScreen) clone_types = (1 << I830_OUTPUT_LVDS); pipe_type = PIPE_LFP; subpixel = SubPixelHorizontalRGB; + possibleOptions = (RROutputOptionScaleNone| + RROutputOptionScaleMaxAspect | + RROutputOptionScaleMax); + currentOptions = RROutputOptionScaleMax; break; case I830_OUTPUT_TVOUT: crtc_types = ((1 << 0) | @@ -692,11 +697,14 @@ I830RandRSetInfo12 (ScreenPtr pScreen) RROutputSetCrtc (randrp->outputs[i], crtc); + RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); + RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); nmode = 0; rrmodes = NULL; if (pipe >= 0) { - modes = pI830->pipeMon[pipe]->Modes; + MonPtr mon = pI830->pipeMon[pipe]; + modes = mon->Modes; for (mode = modes; mode; mode = mode->next) nmode++; @@ -725,6 +733,16 @@ I830RandRSetInfo12 (ScreenPtr pScreen) modeInfo.vSyncEnd = mode->VSyncEnd; modeInfo.vTotal = mode->VTotal; modeInfo.modeFlags = mode->Flags; + if (mode->type & M_T_PREFERRED) + modeInfo.origin = RRModeOriginPreferred; + else if (mode->type & M_T_DRIVER) + modeInfo.origin = RRModeOriginDetailed; + else if (mode->type & M_T_USERDEF) + modeInfo.origin = RRModeOriginConfig; + else if (mode->type & M_T_DEFAULT) + modeInfo.origin = RRModeOriginVESA; + else + modeInfo.origin = RRModeOriginOther; rrmode = RRModeGet (pScreen, &modeInfo, mode->name); rrmode->devPrivate = mode; @@ -776,8 +794,6 @@ static Bool I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - int found_crt; I830ValidateXF86ModeList(pScrn, FALSE); return I830RandRSetInfo12 (pScreen); From 103b4edce7859ddf58f3e1fadeb427a5e85c7acd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Oct 2006 15:00:19 -0700 Subject: [PATCH 170/257] Move the save, restore, and DPMS per-output settings to per-output files. --- src/Makefile.am | 2 + src/i830.h | 32 ++++++++++ src/i830_crt.c | 75 ++++++++++++++++++++++ src/i830_display.c | 6 +- src/i830_driver.c | 152 +++++++++------------------------------------ src/i830_dvo.c | 45 ++++++++++++++ src/i830_lvds.c | 81 ++++++++++++++++++++++++ src/i830_sdvo.c | 26 +++++--- src/i830_sdvo.h | 6 +- 9 files changed, 288 insertions(+), 137 deletions(-) create mode 100644 src/i830_crt.c create mode 100644 src/i830_lvds.c diff --git a/src/Makefile.am b/src/Makefile.am index 7af2dd7e..cab6fe92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ i810_drv_la_SOURCES = \ i830_bios.c \ i830_bios.h \ i830_common.h \ + i830_crt.c \ i830_cursor.c \ i830_debug.c \ i830_debug.h \ @@ -65,6 +66,7 @@ i810_drv_la_SOURCES = \ i830_gtf.c \ i830_i2c.c \ i830_io.c \ + i830_lvds.c \ i830_memory.c \ i830_modes.c \ i830_video.c \ diff --git a/src/i830.h b/src/i830.h index 7def141e..f92704b0 100644 --- a/src/i830.h +++ b/src/i830.h @@ -69,6 +69,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_dri.h" #endif +typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr; + #include "common.h" #include "i830_sdvo.h" #include "i2c_vid.h" @@ -222,6 +224,23 @@ struct _I830OutputRec { int type; /* int pipe; int flags;*/ + + /** + * Turns the output on/off, or sets intermediate power levels if available. + * Unsupported intermediate modes drop to the lower power setting. + */ + void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); + + /** + * Saves the output's state for restoration on VT switch. + */ + void (*save)(ScrnInfoPtr pScrn, I830OutputPtr output); + + /** + * Restore's the output's state at VT switch. + */ + void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output); + xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; @@ -613,10 +632,23 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* i830_crt.c */ +void I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); +void I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output); +void I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output); + /* i830_dvo.c */ +void I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); +void I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output); +void I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output); Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv); +/* i830_lvds.c */ +void I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); +void I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output); +void I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output); + /* i830_memory.c */ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); diff --git a/src/i830_crt.c b/src/i830_crt.c new file mode 100644 index 00000000..1a0dd0b5 --- /dev/null +++ b/src/i830_crt.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" + +void +I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + + temp = INREG(ADPA); + temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); + + switch(mode) { + case DPMSModeOn: + break; + case DPMSModeStandby: + temp |= ADPA_HSYNC_CNTL_DISABLE; + break; + case DPMSModeSuspend: + temp |= ADPA_VSYNC_CNTL_DISABLE; + break; + case DPMSModeOff: + temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; + break; + } + + OUTREG(ADPA, temp); +} + +void +I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pI830->saveADPA = INREG(ADPA); +} + +void +I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + OUTREG(ADPA, pI830->saveADPA); +} diff --git a/src/i830_display.c b/src/i830_display.c index 2b53128c..5a0fb9d8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -864,10 +864,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } for (i = 0; i < pI830->num_outputs; i++) { - struct _I830OutputRec *output = &pI830->output[i]; + I830OutputPtr output = &pI830->output[i]; - if (output->sdvo_drv) - I830SDVOPreSetMode(output->sdvo_drv, pMode); + if (pI830->output[i].sdvo_drv != NULL) + pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); if (output->i2c_drv != NULL) output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, diff --git a/src/i830_driver.c b/src/i830_driver.c index d46fc1bd..93c7fc42 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -909,6 +909,9 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) /* everyone has at least a single analog output */ pI830->output[i].type = I830_OUTPUT_ANALOG; + pI830->output[i].dpms = I830CRTDPMS; + pI830->output[i].save = I830CRTSave; + pI830->output[i].restore = I830CRTRestore; /* setup the DDC bus for the analog output */ I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A"); @@ -917,6 +920,9 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) if (IS_MOBILE(pI830) && !IS_I830(pI830)) { /* Set up integrated LVDS */ pI830->output[i].type = I830_OUTPUT_LVDS; + pI830->output[i].dpms = I830LVDSDPMS; + pI830->output[i].save = I830LVDSSave; + pI830->output[i].restore = I830LVDSRestore; I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C"); i++; } @@ -924,18 +930,27 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn) if (IS_I9XX(pI830)) { /* Set up SDVOB */ pI830->output[i].type = I830_OUTPUT_SDVO; + pI830->output[i].dpms = i830SDVODPMS; + pI830->output[i].save = i830SDVOSave; + pI830->output[i].restore = i830SDVORestore; I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); I830SDVOInit(pScrn, i, SDVOB); i++; /* Set up SDVOC */ pI830->output[i].type = I830_OUTPUT_SDVO; + pI830->output[i].dpms = i830SDVODPMS; + pI830->output[i].save = i830SDVOSave; + pI830->output[i].restore = i830SDVORestore; pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus; I830SDVOInit(pScrn, i, SDVOC); i++; } else { /* set up DVO */ pI830->output[i].type = I830_OUTPUT_DVO; + pI830->output[i].dpms = I830DVODPMS; + pI830->output[i].save = I830DVOSave; + pI830->output[i].restore = I830DVORestore; I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); @@ -2600,31 +2615,6 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV); pI830->saveVGACNTRL = INREG(VGACNTRL); - pI830->saveADPA = INREG(ADPA); - - pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); - pI830->savePP_ON = INREG(LVDSPP_ON); - pI830->savePP_OFF = INREG(LVDSPP_OFF); - pI830->saveLVDS = INREG(LVDS); - pI830->savePP_CONTROL = INREG(PP_CONTROL); - pI830->savePP_CYCLE = INREG(PP_CYCLE); - pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); - pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - /* - * If the light is off at server startup, just make it full brightness - */ - if (!pI830->backlight_duty_cycle) - pI830->backlight_duty_cycle = ((pI830->saveBLC_PWM_CTL & - BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT); - - if (!IS_I9XX(pI830)) { - pI830->saveDVOA = INREG(DVOA); - pI830->saveDVOB = INREG(DVOB); - pI830->saveDVOC = INREG(DVOC); - } - for(i = 0; i < 7; i++) { pI830->saveSWF[i] = INREG(SWF0 + (i << 2)); pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2)); @@ -2634,17 +2624,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveSWF[16] = INREG(SWF32); for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_DVO && - pI830->output[i].i2c_drv != NULL) - { - pI830->output[i].i2c_drv->vid_rec->SaveRegs( - pI830->output[i].i2c_drv->dev_priv); - } - if (pI830->output[i].type == I830_OUTPUT_SDVO && - pI830->output[i].sdvo_drv != NULL) - { - i830SDVOSave(pScrn, i); - } + if (pI830->output[i].save != NULL) + pI830->output[i].save(pScrn, &pI830->output[i]); } vgaHWUnlock(hwp); @@ -2670,6 +2651,11 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); + /* Disable outputs */ + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); + } + /* First, disable display planes */ temp = INREG(DSPACNTR); OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); @@ -2682,18 +2668,7 @@ RestoreHWState(ScrnInfoPtr pScrn) temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - /* XXX: Wait for a vblank */ - sleep(1); - - i830SetLVDSPanelPower(pScrn, FALSE); - - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_SDVO && - pI830->output[i].sdvo_drv != NULL) - { - i830SDVOPreRestore(pScrn, i); - } - } + i830WaitForVblank(pScrn); OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); @@ -2738,12 +2713,6 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBSURF, pI830->saveDSPBBASE); } - OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); - OUTREG(LVDSPP_ON, pI830->savePP_ON); - OUTREG(LVDSPP_OFF, pI830->savePP_OFF); - OUTREG(PP_CYCLE, pI830->savePP_CYCLE); - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); @@ -2755,30 +2724,10 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - OUTREG(ADPA, pI830->saveADPA); - OUTREG(LVDS, pI830->saveLVDS); - if (!IS_I9XX(pI830)) { - OUTREG(DVOA, pI830->saveDVOA); - OUTREG(DVOB, pI830->saveDVOB); - OUTREG(DVOC, pI830->saveDVOC); - } - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_DVO && - pI830->output[i].i2c_drv != NULL) - { - pI830->output[i].i2c_drv->vid_rec->RestoreRegs( - pI830->output[i].i2c_drv->dev_priv); - } - if (pI830->output[i].type == I830_OUTPUT_SDVO && - pI830->output[i].sdvo_drv != NULL) - { - i830SDVOPostRestore(pScrn, i); - } + pI830->output[i].restore(pScrn, &pI830->output[i]); } - OUTREG(PP_CONTROL, pI830->savePP_CONTROL); - for(i = 0; i < 7; i++) { OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); @@ -4204,39 +4153,6 @@ I830SaveScreen(ScreenPtr pScreen, int mode) return TRUE; } -static void -I830DPMSCRT(ScrnInfoPtr pScrn, int mode) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; - - temp = INREG(ADPA); - temp &= ~(ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE); - switch(mode) { - case DPMSModeOn: - break; - case DPMSModeStandby: - temp |= ADPA_HSYNC_CNTL_DISABLE; - break; - case DPMSModeSuspend: - temp |= ADPA_VSYNC_CNTL_DISABLE; - break; - case DPMSModeOff: - temp |= ADPA_HSYNC_CNTL_DISABLE|ADPA_VSYNC_CNTL_DISABLE; - break; - } - OUTREG(ADPA, temp); -} - -static void -I830DPMSLVDS(ScrnInfoPtr pScrn, int mode) -{ - if (mode == DPMSModeOn) - i830SetLVDSPanelPower(pScrn, TRUE); - else - i830SetLVDSPanelPower(pScrn, FALSE); -} - /* Use the VBE version when available. */ static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, @@ -4246,6 +4162,10 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int i; CARD32 temp, ctrl, base; + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode); + } + for (i = 0; i < pI830->availablePipes; i++) { if (i == 0) { ctrl = DSPACNTR; @@ -4267,22 +4187,6 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, } } - if (pI830->operatingDevices & (PIPE_CRT_ACTIVE | (PIPE_CRT_ACTIVE<<8))) { - I830DPMSCRT(pScrn, PowerManagementMode); - } - - if (pI830->operatingDevices & (PIPE_LCD_ACTIVE | (PIPE_LCD_ACTIVE<<8))) { - I830DPMSLVDS(pScrn, PowerManagementMode); - } - - if (pI830->operatingDevices & (PIPE_DFP_ACTIVE | (PIPE_DFP_ACTIVE<<8))) { - /* TBD */ - } - - if (pI830->operatingDevices & (PIPE_DFP2_ACTIVE | (PIPE_DFP2_ACTIVE<<8))) { - /* TBD */ - } - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { if (PowerManagementMode == DPMSModeOn) pI830->CursorInfoRec->ShowCursor(pScrn); diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 242e3dd0..f64a8e85 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -54,6 +54,51 @@ struct _I830DVODriver i830_dvo_drivers[] = #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) +void +I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +{ + if (output->i2c_drv == NULL) + return; + + if (mode == DPMSModeOn) + output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE); + else + output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE); +} + +void +I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (output->i2c_drv == NULL) + return; + + /* Each output should probably just save the registers it touches, but for + * now, use more overkill. + */ + pI830->saveDVOA = INREG(DVOA); + pI830->saveDVOB = INREG(DVOB); + pI830->saveDVOC = INREG(DVOC); + + output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv); +} + +void +I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (output->i2c_drv == NULL) + return; + + OUTREG(DVOA, pI830->saveDVOA); + OUTREG(DVOB, pI830->saveDVOB); + OUTREG(DVOC, pI830->saveDVOC); + + output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv); +} + Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv) diff --git a/src/i830_lvds.c b/src/i830_lvds.c new file mode 100644 index 00000000..fcd8fee6 --- /dev/null +++ b/src/i830_lvds.c @@ -0,0 +1,81 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" + +void +I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +{ + if (mode == DPMSModeOn) + i830SetLVDSPanelPower(pScrn, TRUE); + else + i830SetLVDSPanelPower(pScrn, FALSE); +} + +void +I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); + pI830->savePP_ON = INREG(LVDSPP_ON); + pI830->savePP_OFF = INREG(LVDSPP_OFF); + pI830->saveLVDS = INREG(LVDS); + pI830->savePP_CONTROL = INREG(PP_CONTROL); + pI830->savePP_CYCLE = INREG(PP_CYCLE); + pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); + pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + + /* + * If the light is off at server startup, just make it full brightness + */ + if (pI830->backlight_duty_cycle == 0) { + pI830->backlight_duty_cycle = + (pI830->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >> + BACKLIGHT_MODULATION_FREQ_SHIFT; + } +} + +void +I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); + OUTREG(LVDSPP_ON, pI830->savePP_ON); + OUTREG(LVDSPP_OFF, pI830->savePP_OFF); + OUTREG(PP_CYCLE, pI830->savePP_CYCLE); + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + OUTREG(LVDS, pI830->saveLVDS); + OUTREG(PP_CONTROL, pI830->savePP_CONTROL); +} diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index c7625419..a07e7c9d 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -640,10 +640,13 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) } void -i830SDVOSave(ScrnInfoPtr pScrn, int output_index) +i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + I830SDVOPtr sdvo = output->sdvo_drv; + + if (sdvo == NULL) + return; sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo); I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1, @@ -677,19 +680,28 @@ i830SDVOSave(ScrnInfoPtr pScrn, int output_index) } void -i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index) +i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + I830SDVOPtr sdvo = output->sdvo_drv; - I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); + if (sdvo == NULL) + return; + + if (mode != DPMSModeOn) + I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); + else + I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE); } void -i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index) +i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv; + I830SDVOPtr sdvo = output->sdvo_drv; + + if (sdvo == NULL) + return; if (sdvo->caps.caps & 0x1) { I830SDVOSetTargetInput(sdvo, FALSE, FALSE); diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 52621e03..73ecf32b 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -56,13 +56,13 @@ typedef struct _i830_sdvo_dtd { } __attribute__((packed)) i830_sdvo_dtd; void -i830SDVOSave(ScrnInfoPtr pScrn, int output_index); +i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); void -i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index); +i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output); void -i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index); +i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output); Bool I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); From 4ac81d58b7e0fbffbb4981deffe6a576be821a9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Oct 2006 23:22:52 -0700 Subject: [PATCH 171/257] Remove mode origins, add preferred mode count. Just tracking changes in the 1.2 protocol spec. --- src/i830_randr.c | 69 ++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 37bd6a10..3c594d8a 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -603,10 +603,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int nclone; RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; int ncrtc; - int nmode; + int nmode, npreferred; struct _I830OutputRec *output; int i; int j; + int p; int clone_types; int crtc_types; int connection; @@ -700,6 +701,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); nmode = 0; + npreferred = 0; rrmodes = NULL; if (pipe >= 0) { @@ -715,44 +717,43 @@ I830RandRSetInfo12 (ScreenPtr pScreen) if (!rrmodes) return FALSE; nmode = 0; - for (mode = modes; mode; mode = mode->next) + for (p = 1; p >= 0; p--) { - modeInfo.nameLength = strlen (mode->name); - modeInfo.mmWidth = mon->widthmm; - modeInfo.mmHeight = mon->heightmm; - - modeInfo.width = mode->HDisplay; - modeInfo.dotClock = mode->Clock * 1000; - modeInfo.hSyncStart = mode->HSyncStart; - modeInfo.hSyncEnd = mode->HSyncEnd; - modeInfo.hTotal = mode->HTotal; - modeInfo.hSkew = mode->HSkew; - - modeInfo.height = mode->VDisplay; - modeInfo.vSyncStart = mode->VSyncStart; - modeInfo.vSyncEnd = mode->VSyncEnd; - modeInfo.vTotal = mode->VTotal; - modeInfo.modeFlags = mode->Flags; - if (mode->type & M_T_PREFERRED) - modeInfo.origin = RRModeOriginPreferred; - else if (mode->type & M_T_DRIVER) - modeInfo.origin = RRModeOriginDetailed; - else if (mode->type & M_T_USERDEF) - modeInfo.origin = RRModeOriginConfig; - else if (mode->type & M_T_DEFAULT) - modeInfo.origin = RRModeOriginVESA; - else - modeInfo.origin = RRModeOriginOther; - - rrmode = RRModeGet (pScreen, &modeInfo, mode->name); - rrmode->devPrivate = mode; - if (rrmode) - rrmodes[nmode++] = rrmode; + for (mode = modes; mode; mode = mode->next) + { + if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) + { + modeInfo.nameLength = strlen (mode->name); + modeInfo.mmWidth = mon->widthmm; + modeInfo.mmHeight = mon->heightmm; + + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (pScreen, &modeInfo, mode->name); + rrmode->devPrivate = mode; + if (rrmode) + { + rrmodes[nmode++] = rrmode; + npreferred += p; + } + } + } } } } - if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode)) + if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred)) { xfree (rrmodes); return FALSE; From 0a5504e59f90abecedd81a8435b88a60fe098f29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Oct 2006 09:11:29 -0700 Subject: [PATCH 172/257] Fix DPI at startup in RandR 1.2 code. Use requested monitor resolution to compute the appropriate screen size when resizing the screen during RandR initialization. --- src/i830_randr.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 3c594d8a..e4075f26 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -832,12 +832,25 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mode = pScrn->currentMode; if (mode) { + int mmWidth, mmHeight; + + if (mode->HDisplay == pScreen->width && + mode->VDisplay == pScreen->height) + { + mmWidth = pScrn->widthmm; + mmHeight = pScrn->heightmm; + } + else + { +#define MMPERINCH 25.4 + mmWidth = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH; + mmHeight = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH; + } I830RandRScreenSetSize (pScreen, mode->HDisplay, mode->VDisplay, - pScreen->mmWidth, - pScreen->mmHeight); - + mmWidth, + mmHeight); } for (i = 0; i < MAX_DISPLAY_PIPES; i++) From ada8f62da263d1e93e22df4e0b1149bf1dbe24d4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Oct 2006 15:55:07 -0700 Subject: [PATCH 173/257] Give each output type an init method in its file, making other methods static. --- src/i830.h | 14 +-- src/i830_crt.c | 29 ++++-- src/i830_display.h | 2 - src/i830_driver.c | 71 +++----------- src/i830_dvo.c | 51 ++++++++-- src/i830_lvds.c | 31 ++++-- src/i830_sdvo.c | 236 ++++++++++++++++++++++++--------------------- src/i830_sdvo.h | 8 +- 8 files changed, 240 insertions(+), 202 deletions(-) diff --git a/src/i830.h b/src/i830.h index f92704b0..ae84846b 100644 --- a/src/i830.h +++ b/src/i830.h @@ -633,21 +633,13 @@ extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); /* i830_crt.c */ -void I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); -void I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output); -void I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output); +void i830_crt_init(ScrnInfoPtr pScrn); /* i830_dvo.c */ -void I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); -void I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output); -void I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output); -Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, - struct _I830DVODriver **retdrv); +void i830_dvo_init(ScrnInfoPtr pScrn); /* i830_lvds.c */ -void I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); -void I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output); -void I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output); +void i830_lvds_init(ScrnInfoPtr pScrn); /* i830_memory.c */ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); diff --git a/src/i830_crt.c b/src/i830_crt.c index 1a0dd0b5..72df6bc5 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -32,8 +32,8 @@ #include "xf86.h" #include "i830.h" -void -I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +static void +i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; @@ -58,18 +58,35 @@ I830CRTDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) OUTREG(ADPA, temp); } -void -I830CRTSave(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); pI830->saveADPA = INREG(ADPA); } -void -I830CRTRestore(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); OUTREG(ADPA, pI830->saveADPA); } + +void +i830_crt_init(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG; + pI830->output[pI830->num_outputs].dpms = i830_crt_dpms; + pI830->output[pI830->num_outputs].save = i830_crt_save; + pI830->output[pI830->num_outputs].restore = i830_crt_restore; + + /* Set up the DDC bus. */ + I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, + GPIOA, "CRTDDC_A"); + + pI830->num_outputs++; +} diff --git a/src/i830_display.h b/src/i830_display.h index 2b808ad8..91450fe0 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -34,7 +34,5 @@ void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); /* i830_sdvo.c */ -I830SDVOPtr I830SDVOInit(ScrnInfoPtr pScrn, int output_index, - CARD32 output_device); Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 93c7fc42..5da31a6f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -900,71 +900,30 @@ I830UseDDC(ScrnInfoPtr pScrn) } #endif +/** + * Set up the outputs according to what type of chip we are. + * + * Some outputs may not initialize, due to allocation failure or because a + * controller chip isn't found. + */ static void -I830SetupOutputBusses(ScrnInfoPtr pScrn) +I830SetupOutputs(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int i = 0; - Bool ret; /* everyone has at least a single analog output */ - pI830->output[i].type = I830_OUTPUT_ANALOG; - pI830->output[i].dpms = I830CRTDPMS; - pI830->output[i].save = I830CRTSave; - pI830->output[i].restore = I830CRTRestore; + i830_crt_init(pScrn); - /* setup the DDC bus for the analog output */ - I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOA, "CRTDDC_A"); - i++; - - if (IS_MOBILE(pI830) && !IS_I830(pI830)) { - /* Set up integrated LVDS */ - pI830->output[i].type = I830_OUTPUT_LVDS; - pI830->output[i].dpms = I830LVDSDPMS; - pI830->output[i].save = I830LVDSSave; - pI830->output[i].restore = I830LVDSRestore; - I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOC, "LVDSDDC_C"); - i++; - } + /* Set up integrated LVDS */ + if (IS_MOBILE(pI830) && !IS_I830(pI830)) + i830_lvds_init(pScrn); if (IS_I9XX(pI830)) { - /* Set up SDVOB */ - pI830->output[i].type = I830_OUTPUT_SDVO; - pI830->output[i].dpms = i830SDVODPMS; - pI830->output[i].save = i830SDVOSave; - pI830->output[i].restore = i830SDVORestore; - I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "SDVOCTRL_E"); - I830SDVOInit(pScrn, i, SDVOB); - i++; - - /* Set up SDVOC */ - pI830->output[i].type = I830_OUTPUT_SDVO; - pI830->output[i].dpms = i830SDVODPMS; - pI830->output[i].save = i830SDVOSave; - pI830->output[i].restore = i830SDVORestore; - pI830->output[i].pI2CBus = pI830->output[i-1].pI2CBus; - I830SDVOInit(pScrn, i, SDVOC); - i++; + i830_sdvo_init(pScrn, SDVOB); + i830_sdvo_init(pScrn, SDVOC); } else { - /* set up DVO */ - pI830->output[i].type = I830_OUTPUT_DVO; - pI830->output[i].dpms = I830DVODPMS; - pI830->output[i].save = I830DVOSave; - pI830->output[i].restore = I830DVORestore; - I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); - I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); - - ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, - &pI830->output[i].i2c_drv); - if (ret == TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - pI830->output[i].i2c_drv->modulename, - pI830->output[i].pI2CBus->DriverPrivate.uval); - } - - i++; + i830_dvo_init(pScrn); } - pI830->num_outputs = i; } static void @@ -985,7 +944,7 @@ I830PreInitDDC(ScrnInfoPtr pScrn) if (xf86LoadSubModule(pScrn, "i2c")) { xf86LoaderReqSymLists(I810i2cSymbols, NULL); - I830SetupOutputBusses(pScrn); + I830SetupOutputs(pScrn); pI830->ddc2 = TRUE; } else { diff --git a/src/i830_dvo.c b/src/i830_dvo.c index f64a8e85..86d7d73b 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -54,8 +54,8 @@ struct _I830DVODriver i830_dvo_drivers[] = #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) -void -I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +static void +i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { if (output->i2c_drv == NULL) return; @@ -66,8 +66,8 @@ I830DVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE); } -void -I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); @@ -84,8 +84,8 @@ I830DVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv); } -void -I830DVORestore(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); @@ -129,3 +129,42 @@ I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, } return FALSE; } + +void +i830_dvo_init(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool ret; + int i = pI830->num_outputs; + + pI830->output[i].type = I830_OUTPUT_DVO; + pI830->output[i].dpms = i830_dvo_dpms; + pI830->output[i].save = i830_dvo_save; + pI830->output[i].restore = i830_dvo_restore; + + /* Set up the I2C and DDC buses */ + ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); + if (!ret) + return; + + ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); + if (!ret) { + xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE); + return; + } + + /* Now, try to find a controller */ + ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, + &pI830->output[i].i2c_drv); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", + pI830->output[i].i2c_drv->modulename, + pI830->output[i].pI2CBus->DriverPrivate.uval); + } else { + xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE); + xf86DestroyI2CBusRec(pI830->output[i].pDDCBus, TRUE, TRUE); + return; + } + + pI830->num_outputs++; +} diff --git a/src/i830_lvds.c b/src/i830_lvds.c index fcd8fee6..3ce8cb6e 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -32,8 +32,8 @@ #include "xf86.h" #include "i830.h" -void -I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +static void +i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { if (mode == DPMSModeOn) i830SetLVDSPanelPower(pScrn, TRUE); @@ -41,8 +41,8 @@ I830LVDSDPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) i830SetLVDSPanelPower(pScrn, FALSE); } -void -I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); @@ -66,8 +66,8 @@ I830LVDSSave(ScrnInfoPtr pScrn, I830OutputPtr output) } } -void -I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); @@ -79,3 +79,22 @@ I830LVDSRestore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(LVDS, pI830->saveLVDS); OUTREG(PP_CONTROL, pI830->savePP_CONTROL); } + +void +i830_lvds_init(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS; + pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms; + pI830->output[pI830->num_outputs].save = i830_lvds_save; + pI830->output[pI830->num_outputs].restore = i830_lvds_restore; + + /* Set up the LVDS DDC channel. Most panels won't support it, but it can + * be useful if available. + */ + I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, + GPIOC, "LVDSDDC_C"); + + pI830->num_outputs++; +} diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index a07e7c9d..9792904d 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -639,8 +639,22 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) return ret; } -void -i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +{ + I830SDVOPtr sdvo = output->sdvo_drv; + + if (sdvo == NULL) + return; + + if (mode != DPMSModeOn) + I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); + else + I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE); +} + +static void +i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = output->sdvo_drv; @@ -679,23 +693,8 @@ i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output) sdvo->save_SDVOX = INREG(sdvo->output_device); } -void -i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = output->sdvo_drv; - - if (sdvo == NULL) - return; - - if (mode != DPMSModeOn) - I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); - else - I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE); -} - -void -i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output) +static void +i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = output->sdvo_drv; @@ -827,95 +826,6 @@ I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr) return FALSE; } -I830SDVOPtr -I830SDVOInit(ScrnInfoPtr pScrn, int output_index, CARD32 output_device) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo; - int i; - unsigned char ch[0x40]; - I2CBusPtr i2cbus, ddcbus; - - i2cbus = pI830->output[output_index].pI2CBus; - - sdvo = xcalloc(1, sizeof(I830SDVORec)); - if (sdvo == NULL) - return NULL; - - if (output_device == SDVOB) { - sdvo->d.DevName = "SDVO Controller B"; - sdvo->d.SlaveAddr = 0x70; - } else { - sdvo->d.DevName = "SDVO Controller C"; - sdvo->d.SlaveAddr = 0x72; - } - sdvo->d.pI2CBus = i2cbus; - sdvo->d.DriverPrivate.ptr = sdvo; - sdvo->output_device = output_device; - - if (!xf86I2CDevInit(&sdvo->d)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to initialize SDVO I2C device %s\n", - output_device == SDVOB ? "SDVOB" : "SDVOC"); - xfree(sdvo); - return NULL; - } - - /* Set up our wrapper I2C bus for DDC. It acts just like the regular I2C - * bus, except that it does the control bus switch to DDC mode before every - * Start. While we only need to do it at Start after every Stop after a - * Start, extra attempts should be harmless. - */ - ddcbus = xf86CreateI2CBusRec(); - if (ddcbus == NULL) { - xf86DestroyI2CDevRec(&sdvo->d, 0); - xfree(sdvo); - return NULL; - } - if (output_device == SDVOB) - ddcbus->BusName = "SDVOB DDC Bus"; - else - ddcbus->BusName = "SDVOC DDC Bus"; - ddcbus->scrnIndex = i2cbus->scrnIndex; - ddcbus->I2CGetByte = I830SDVODDCI2CGetByte; - ddcbus->I2CPutByte = I830SDVODDCI2CPutByte; - ddcbus->I2CStart = I830SDVODDCI2CStart; - ddcbus->I2CStop = I830SDVODDCI2CStop; - ddcbus->I2CAddress = I830SDVODDCI2CAddress; - ddcbus->DriverPrivate.ptr = sdvo; - if (!xf86I2CBusInit(ddcbus)) { - xf86DestroyI2CDevRec(&sdvo->d, 0); - xfree(sdvo); - return NULL; - } - - pI830->output[output_index].pDDCBus = ddcbus; - - /* Read the regs to test if we can talk to the device */ - for (i = 0; i < 0x40; i++) { - if (!sReadByte(sdvo, i, &ch[i])) { - xf86DestroyI2CBusRec(pI830->output[output_index].pDDCBus, FALSE, - FALSE); - xf86DestroyI2CDevRec(&sdvo->d, 0); - xfree(sdvo); - return NULL; - } - } - - pI830->output[output_index].sdvo_drv = sdvo; - - I830SDVOGetCapabilities(sdvo, &sdvo->caps); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "SDVO device VID/DID: %02X:%02X.%02X, %02X, output 1: %c, output 2: %c\n", - sdvo->caps.vendor_id, sdvo->caps.device_id, - sdvo->caps.device_rev_id, sdvo->caps.caps, - sdvo->caps.output_0_supported ? 'Y' : 'N', - sdvo->caps.output_1_supported ? 'Y' : 'N'); - - return sdvo; -} - static void I830DumpSDVOCmd (I830SDVOPtr s, int opcode) { @@ -991,3 +901,113 @@ I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index) return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 || s->sdvo_regs[SDVO_I2C_RETURN_1] != 0); } + +void +i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830SDVOPtr sdvo; + int i; + unsigned char ch[0x40]; + I2CBusPtr i2cbus = NULL, ddcbus; + + pI830->output[pI830->num_outputs].type = I830_OUTPUT_SDVO; + pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms; + pI830->output[pI830->num_outputs].save = i830_sdvo_save; + pI830->output[pI830->num_outputs].restore = i830_sdvo_restore; + + /* Find an existing SDVO I2CBus from another output, or allocate it. */ + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO) + i2cbus = pI830->output[i].pI2CBus; + } + if (i2cbus == NULL) + I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E"); + if (i2cbus == NULL) + return; + + /* Allocate the SDVO output private data */ + sdvo = xcalloc(1, sizeof(I830SDVORec)); + if (sdvo == NULL) { + xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + return; + } + + if (output_device == SDVOB) { + sdvo->d.DevName = "SDVO Controller B"; + sdvo->d.SlaveAddr = 0x70; + } else { + sdvo->d.DevName = "SDVO Controller C"; + sdvo->d.SlaveAddr = 0x72; + } + sdvo->d.pI2CBus = i2cbus; + sdvo->d.DriverPrivate.ptr = sdvo; + sdvo->output_device = output_device; + + if (!xf86I2CDevInit(&sdvo->d)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize SDVO I2C device %s\n", + output_device == SDVOB ? "SDVOB" : "SDVOC"); + xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + xfree(sdvo); + return; + } + + /* Set up our wrapper I2C bus for DDC. It acts just like the regular I2C + * bus, except that it does the control bus switch to DDC mode before every + * Start. While we only need to do it at Start after every Stop after a + * Start, extra attempts should be harmless. + */ + ddcbus = xf86CreateI2CBusRec(); + if (ddcbus == NULL) { + xf86DestroyI2CDevRec(&sdvo->d, FALSE); + xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + xfree(sdvo); + return; + } + if (output_device == SDVOB) + ddcbus->BusName = "SDVOB DDC Bus"; + else + ddcbus->BusName = "SDVOC DDC Bus"; + ddcbus->scrnIndex = i2cbus->scrnIndex; + ddcbus->I2CGetByte = I830SDVODDCI2CGetByte; + ddcbus->I2CPutByte = I830SDVODDCI2CPutByte; + ddcbus->I2CStart = I830SDVODDCI2CStart; + ddcbus->I2CStop = I830SDVODDCI2CStop; + ddcbus->I2CAddress = I830SDVODDCI2CAddress; + ddcbus->DriverPrivate.ptr = sdvo; + if (!xf86I2CBusInit(ddcbus)) { + xf86DestroyI2CDevRec(&sdvo->d, FALSE); + xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + xfree(sdvo); + return; + } + + pI830->output[pI830->num_outputs].pI2CBus = ddcbus; + pI830->output[pI830->num_outputs].pDDCBus = ddcbus; + pI830->output[pI830->num_outputs].sdvo_drv = sdvo; + + /* Read the regs to test if we can talk to the device */ + for (i = 0; i < 0x40; i++) { + if (!sReadByte(sdvo, i, &ch[i])) { + xf86DestroyI2CBusRec(pI830->output[pI830->num_outputs].pDDCBus, + FALSE, FALSE); + xf86DestroyI2CDevRec(&sdvo->d, FALSE); + xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + xfree(sdvo); + return; + } + } + + I830SDVOGetCapabilities(sdvo, &sdvo->caps); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SDVO device VID/DID: %02X:%02X.%02X, %02X," + "output 1: %c, output 2: %c\n", + sdvo->caps.vendor_id, sdvo->caps.device_id, + sdvo->caps.device_rev_id, sdvo->caps.caps, + sdvo->caps.output_0_supported ? 'Y' : 'N', + sdvo->caps.output_1_supported ? 'Y' : 'N'); + + pI830->num_outputs++; +} diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 73ecf32b..9a3586f2 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -56,13 +56,7 @@ typedef struct _i830_sdvo_dtd { } __attribute__((packed)) i830_sdvo_dtd; void -i830SDVODPMS(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); - -void -i830SDVOSave(ScrnInfoPtr pScrn, I830OutputPtr output); - -void -i830SDVORestore(ScrnInfoPtr pScrn, I830OutputPtr output); +i830_sdvo_init(ScrnInfoPtr pScrn, int output_device); Bool I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); From 9bb7736ab36f172db58703c4664bb1b0cd7f80c3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Oct 2006 16:02:02 -0700 Subject: [PATCH 174/257] Remove checks for output privates in various bits of code. Now, the output is only set up if it fully initializes, so it will never exist if the private it requires doesn't. --- src/i830_display.c | 6 +++--- src/i830_driver.c | 20 +++++++------------- src/i830_dvo.c | 11 +---------- src/i830_modes.c | 6 ++---- src/i830_sdvo.c | 9 --------- 5 files changed, 13 insertions(+), 39 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 5a0fb9d8..e3c3062f 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -866,10 +866,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) for (i = 0; i < pI830->num_outputs; i++) { I830OutputPtr output = &pI830->output[i]; - if (pI830->output[i].sdvo_drv != NULL) + if (pI830->output[i].type == I830_OUTPUT_SDVO) pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); - if (output->i2c_drv != NULL) + if (pI830->output[i].type == I830_OUTPUT_DVO) output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode); } @@ -885,7 +885,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) goto done; } for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].sdvo_drv) + if (pI830->output[i].type == I830_OUTPUT_SDVO) I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode); } diff --git a/src/i830_driver.c b/src/i830_driver.c index 5da31a6f..4b558559 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -985,14 +985,12 @@ I830DetectMonitors(ScrnInfoPtr pScrn) xf86PrintEDID(pI830->output[i].MonInfo); break; case I830_OUTPUT_SDVO: - if (pI830->output[i].sdvo_drv != NULL) { - pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[i].pDDCBus); + pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, + pI830->output[i].pDDCBus); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i, - pI830->output[i].pDDCBus->DriverPrivate.uval); - xf86PrintEDID(pI830->output[i].MonInfo); - } + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i, + pI830->output[i].pDDCBus->DriverPrivate.uval); + xf86PrintEDID(pI830->output[i].MonInfo); break; case I830_OUTPUT_UNUSED: break; @@ -1675,8 +1673,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * treat different SDVO outputs differently. */ for (i = 0; i < MAX_OUTPUTS; i++) { - if (pI830->output[i].type == I830_OUTPUT_SDVO && - pI830->output[i].sdvo_drv != NULL) { + if (pI830->output[i].type == I830_OUTPUT_SDVO) { if (!I830DetectSDVODisplays(pScrn, i)) continue; @@ -4339,11 +4336,8 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) for (i = 0; i < MAX_OUTPUTS; i++) { Bool found_sdvo = TRUE; - if (pI830->output[i].type != I830_OUTPUT_SDVO || - pI830->output[i].sdvo_drv == NULL) - { + if (pI830->output[i].type != I830_OUTPUT_SDVO) continue; - } start = GetTimeInMillis(); found_sdvo = I830DetectSDVODisplays(pScrn, i); finish = GetTimeInMillis(); diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 86d7d73b..27f1755f 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -57,9 +57,6 @@ struct _I830DVODriver i830_dvo_drivers[] = static void i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { - if (output->i2c_drv == NULL) - return; - if (mode == DPMSModeOn) output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE); else @@ -71,9 +68,6 @@ i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - if (output->i2c_drv == NULL) - return; - /* Each output should probably just save the registers it touches, but for * now, use more overkill. */ @@ -89,9 +83,6 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - if (output->i2c_drv == NULL) - return; - OUTREG(DVOA, pI830->saveDVOA); OUTREG(DVOB, pI830->saveDVOB); OUTREG(DVOC, pI830->saveDVOC); @@ -99,7 +90,7 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv); } -Bool +static Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv) { diff --git a/src/i830_modes.c b/src/i830_modes.c index da1ccde8..f7d46950 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -763,14 +763,12 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) } break; case I830_OUTPUT_DVO: - if (outputs & PIPE_DFP && pI830->output[i].i2c_drv != NULL) { + if (outputs & PIPE_DFP) { output_index = i; } break; case I830_OUTPUT_SDVO: - if (outputs & PIPE_DFP && - pI830->output[i].sdvo_drv != NULL) - { + if (outputs & PIPE_DFP) { output_index = i; } break; diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 9792904d..dc17af0e 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -644,9 +644,6 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { I830SDVOPtr sdvo = output->sdvo_drv; - if (sdvo == NULL) - return; - if (mode != DPMSModeOn) I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); else @@ -659,9 +656,6 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = output->sdvo_drv; - if (sdvo == NULL) - return; - sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo); I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1, &sdvo->save_sdvo_active_2); @@ -699,9 +693,6 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = output->sdvo_drv; - if (sdvo == NULL) - return; - if (sdvo->caps.caps & 0x1) { I830SDVOSetTargetInput(sdvo, FALSE, FALSE); I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, From d649fb0d964a9b40b8e04314b5fc14bbbfd41bc3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Oct 2006 22:46:07 -0700 Subject: [PATCH 175/257] Don't require MonitorLayout when two monitors are plugged in. With randr12 working, we can just leave the second monitor off for now. --- src/i830_driver.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index d46fc1bd..07a9d59b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1771,13 +1771,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) { - if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout " - "defined for use in a DualHead, Clone or MergedFB setup.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 " "cannot be type NONE in DualHead or Clone setup.\n"); From bf3820f1f505649ac0730add23d97d6de3f6d22c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Oct 2006 21:57:26 -0700 Subject: [PATCH 176/257] Compute LVDS resolution from server DPI and native panel size. I was unable to find the native LVDS panel physical size in the BDB information. I would prefer to report accurate information through RandR if possible though. --- src/i830_modes.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index ac7c4c51..9301dda4 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -651,11 +651,27 @@ static MonPtr i830GetLVDSMonitor(ScrnInfoPtr pScrn) { MonPtr mon; + DisplayModePtr mode; mon = xnfcalloc(1, sizeof(*mon)); mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes); mon->Last = i830GetModeListTail(mon->Modes); - + /* + * Find the preferred mode, use the display resolution to compute + * the effective monitor size + */ + for (mode = mon->Modes; mode; mode = mode->next) + if (mode->type & M_T_PREFERRED) + break; + if (!mode) + mode = mon->Modes; + if (mode) + { +#define MMPERINCH 25.4 + mon->widthmm = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH; + mon->heightmm = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH; + } + return mon; } From 53c28b3980d2682de830e8f86553ccad71527ac1 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Sat, 7 Oct 2006 11:18:26 -0400 Subject: [PATCH 177/257] Expand the check for AOpen Mini-PC. Just match on subsystem vendor, don't bother inspecting the subsystem device ID, since apparently they're all busted. --- src/i830_driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 07a9d59b..a69b5c6a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1577,8 +1577,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Blacklist machines with known broken BIOSes */ if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) { - if ((pI830->PciInfo->subsysVendor == 0xa0a0) && - (pI830->PciInfo->subsysCard == 0x0589)) /* aopen mini pc */ + if (pI830->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */ has_lvds = FALSE; if ((pI830->PciInfo->subsysVendor == 0x8086) && From 317cc119c575650c1aa8bf992a0f42bdfffcd7ba Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Oct 2006 11:49:18 -0700 Subject: [PATCH 178/257] Move per-output mode setting code to per-output methods. This is not a very clean interface, as a number of outputs require tweaks to the DPLL registers. When possible, the DPLLs are just adjusted in the per-output post_set_mode, which happens just after the DPLL is enabled. However, this seems better than the previous method of having all outputs programmed in the same function. --- src/i830.h | 25 +- src/i830_crt.c | 37 ++- src/i830_display.c | 561 +++++++++++++++------------------------------ src/i830_display.h | 1 + src/i830_driver.c | 55 ++++- src/i830_dvo.c | 51 ++++- src/i830_lvds.c | 84 +++++++ src/i830_modes.c | 2 +- src/i830_sdvo.c | 92 ++++++-- src/i830_sdvo.h | 3 + 10 files changed, 504 insertions(+), 407 deletions(-) diff --git a/src/i830.h b/src/i830.h index ae84846b..c41cb569 100644 --- a/src/i830.h +++ b/src/i830.h @@ -222,12 +222,15 @@ extern const char *i830_output_type_names[]; struct _I830OutputRec { int type; -/* int pipe; - int flags;*/ + int pipe; + Bool disabled; /** * Turns the output on/off, or sets intermediate power levels if available. - * Unsupported intermediate modes drop to the lower power setting. + * + * Unsupported intermediate modes drop to the lower power setting. If the + * mode is DPMSModeOff, the output must be disabled, as the DPLL may be + * disabled afterwards. */ void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode); @@ -241,6 +244,22 @@ struct _I830OutputRec { */ void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output); + /** + * Callback for setting up a video mode before any pipe/dpll changes. + * + * \param pMode the mode that will be set, or NULL if the mode to be set is + * unknown (such as the restore path of VT switching). + */ + void (*pre_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode); + + /** + * Callback for setting up a video mode after the DPLL update but before + * the plane is enabled. + */ + void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode); + xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; diff --git a/src/i830_crt.c b/src/i830_crt.c index 72df6bc5..1cf1687e 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -40,15 +40,17 @@ i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) temp = INREG(ADPA); temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); + temp &= ~ADPA_DAC_ENABLE; switch(mode) { case DPMSModeOn: + temp |= ADPA_DAC_ENABLE; break; case DPMSModeStandby: - temp |= ADPA_HSYNC_CNTL_DISABLE; + temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; break; case DPMSModeSuspend: - temp |= ADPA_VSYNC_CNTL_DISABLE; + temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; break; case DPMSModeOff: temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; @@ -74,6 +76,35 @@ i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(ADPA, pI830->saveADPA); } +static void +i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ +} + +static void +i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + CARD32 adpa; + + adpa = ADPA_DAC_ENABLE; + + if (pMode->Flags & V_PHSYNC) + adpa |= ADPA_HSYNC_ACTIVE_HIGH; + if (pMode->Flags & V_PVSYNC) + adpa |= ADPA_VSYNC_ACTIVE_HIGH; + + if (output->pipe == 0) + adpa |= ADPA_PIPE_A_SELECT; + else + adpa |= ADPA_PIPE_B_SELECT; + + OUTREG(ADPA, adpa); +} + void i830_crt_init(ScrnInfoPtr pScrn) { @@ -83,6 +114,8 @@ i830_crt_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].dpms = i830_crt_dpms; pI830->output[pI830->num_outputs].save = i830_crt_save; pI830->output[pI830->num_outputs].restore = i830_crt_restore; + pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; + pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; /* Set up the DDC bus. */ I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, diff --git a/src/i830_display.c b/src/i830_display.c index e3c3062f..32ee6e2f 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -226,7 +226,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, return (err != target); } -static void +void i830WaitForVblank(ScrnInfoPtr pScreen) { /* Wait for 20ms, i.e. one cycle at 50hz. */ @@ -259,6 +259,91 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) pI830->pipeY[pipe] = y; } +/** + * In the current world order, there is a list of per-pipe modes, which may or + * may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ +static DisplayModePtr +i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pBest = NULL, pScan; + + /* If the pipe doesn't have any detected modes, just let the system try to + * spam the desired mode in. + */ + if (pI830->pipeMon[pipe] == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No pipe mode list for pipe %d," + "continuing with desired mode\n", pipe); + return pMode; + } + + assert(pScan->VRefresh != 0.0); + for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL; + pScan = pScan->next) { + /* If there's an exact match, we're done. */ + if (I830ModesEqual(pScan, pMode)) { + pBest = pMode; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (pScan->HDisplay > pMode->HDisplay || + pScan->VDisplay > pMode->VDisplay) + { + continue; + } + + if (pBest == NULL) { + pBest = pScan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((pScan->HDisplay > pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) || + (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay > pBest->VDisplay)) + { + pBest = pScan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (pScan->HDisplay == pBest->HDisplay && + pScan->VDisplay == pBest->VDisplay && + (fabs(pScan->VRefresh - pMode->VRefresh) < + fabs(pBest->VRefresh - pMode->VRefresh))) { + pBest = pScan; + } + } + + if (pBest == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No suitable mode found to program for the pipe.\n" + " continuing with desired mode %dx%d@%.1f\n", + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + } else if (!I830ModesEqual(pBest, pMode)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " + "mode %dx%d@%.1f\n", pipe, + pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + pMode = pBest; + } + return pMode; +} + /** * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. @@ -270,119 +355,76 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; - CARD32 pipesrc, dspsize, adpa; - CARD32 sdvob = 0, sdvoc = 0, dvo = 0; - Bool ok, is_sdvo, is_dvo; - int refclk, pixel_clock, sdvo_pixel_multiply; - int outputs; - DisplayModePtr pMasterMode = pMode; + CARD32 pipesrc, dspsize; + Bool ok, is_sdvo = FALSE, is_dvo = FALSE; + Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE; + int refclk, pixel_clock; + int outputs, i; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + int fp_reg = (pipe == 0) ? FPA0 : FPB0; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; + int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - assert(pMode->VRefresh != 0.0); - /* If we've got a list of modes probed for the device, find the best match - * in there to the requested mode. - */ - if (pI830->pipeMon[pipe] != NULL) { - DisplayModePtr pBest = NULL, pScan; - - assert(pScan->VRefresh != 0.0); - for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL; - pScan = pScan->next) - { - /* If there's an exact match, we're done. */ - if (I830ModesEqual(pScan, pMode)) { - pBest = pMode; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (pScan->HDisplay > pMode->HDisplay || - pScan->VDisplay > pMode->VDisplay) - { - continue; - } - - if (pBest == NULL) { - pBest = pScan; - continue; - } - /* Find if it's closer to the right size than the current best - * option. - */ - if ((pScan->HDisplay > pBest->HDisplay && - pScan->VDisplay >= pBest->VDisplay) || - (pScan->HDisplay >= pBest->HDisplay && - pScan->VDisplay > pBest->VDisplay)) - { - pBest = pScan; - continue; - } - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (pScan->HDisplay == pBest->HDisplay && - pScan->VDisplay == pBest->VDisplay && - (fabs(pScan->VRefresh - pMode->VRefresh) < - fabs(pBest->VRefresh - pMode->VRefresh))) - { - pBest = pScan; - } - } - if (pBest != NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " - "mode %dx%d@%.1f\n", pipe, - pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, - pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); - pMode = pBest; - } - } if (pipe == 0) outputs = pI830->operatingDevices & 0xff; else outputs = (pI830->operatingDevices >> 8) & 0xff; - if (outputs & PIPE_LCD_ACTIVE) { - if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMasterMode)) - return TRUE; - } else { - if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) - return TRUE; - } + if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) + return TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", pMode->Clock); - if ((outputs & PIPE_LCD_ACTIVE) && (outputs & ~PIPE_LCD_ACTIVE)) { + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].pipe != pipe || pI830->output[i].disabled) + continue; + + switch (pI830->output[i].type) { + case I830_OUTPUT_LVDS: + is_lvds = TRUE; + break; + case I830_OUTPUT_SDVO: + is_sdvo = TRUE; + break; + case I830_OUTPUT_DVO: + is_dvo = TRUE; + break; + case I830_OUTPUT_TVOUT: + is_tv = TRUE; + break; + case I830_OUTPUT_ANALOG: + is_crt = TRUE; + break; + } + } + + if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable LVDS and non-LVDS on the same pipe\n"); return FALSE; } - if (((outputs & PIPE_TV_ACTIVE) && (outputs & ~PIPE_TV_ACTIVE)) || - ((outputs & PIPE_TV2_ACTIVE) && (outputs & ~PIPE_TV2_ACTIVE))) { + if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable a TV and any other output on the same pipe\n"); + "Can't enable a TV and any other output on the same " + "pipe\n"); return FALSE; } - if (pipe == 0 && (outputs & PIPE_LCD_ACTIVE)) { + if (pipe == 0 && is_lvds) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't support LVDS on pipe A\n"); return FALSE; } - if ((outputs & PIPE_DFP_ACTIVE) || (outputs & PIPE_DFP2_ACTIVE)) { - /* We'll change how we control outputs soon, but to get the SDVO code up - * and running, just check for these two possibilities. - */ - if (IS_I9XX(pI830)) { - is_sdvo = TRUE; - is_dvo = FALSE; - } else { - is_dvo = TRUE; - is_sdvo = FALSE; - } - } else { - is_sdvo = FALSE; - is_dvo = FALSE; - } htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); @@ -393,8 +435,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); pixel_clock = pMode->Clock; - if (outputs & PIPE_LCD_ACTIVE && pI830->panel_fixed_hactive != 0) - { + + if (is_lvds && pI830->panel_fixed_hactive != 0) { /* To enable panel fitting, we need to set the pipe timings to that of * the screen at its full resolution. So, drop the timings from the * BIOS VBT tables here. @@ -420,30 +462,24 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pI830->panel_fixed_vsyncwidth - 1) << 16); pixel_clock = pI830->panel_fixed_clock; - if (pMasterMode->HDisplay <= pI830->panel_fixed_hactive && - pMasterMode->HDisplay <= pI830->panel_fixed_vactive) + if (pMode->HDisplay <= pI830->panel_fixed_hactive && + pMode->HDisplay <= pI830->panel_fixed_vactive) { - pipesrc = ((pMasterMode->HDisplay - 1) << 16) | - (pMasterMode->VDisplay - 1); - dspsize = ((pMasterMode->VDisplay - 1) << 16) | - (pMasterMode->HDisplay - 1); + pipesrc = ((pMode->HDisplay - 1) << 16) | + (pMode->VDisplay - 1); + dspsize = ((pMode->VDisplay - 1) << 16) | + (pMode->HDisplay - 1); } } - if (pMode->Clock >= 100000) - sdvo_pixel_multiply = 1; - else if (pMode->Clock >= 50000) - sdvo_pixel_multiply = 2; - else - sdvo_pixel_multiply = 4; - /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz. * The clock on the bus is 10 times the pixel clock normally. If that * would be too low, we run the DPLL at a multiple of the pixel clock, and - * tell the SDVO device the multiplier so it can throw away the dummy bytes. + * tell the SDVO device the multiplier so it can throw away the dummy + * bytes. */ if (is_sdvo) { - pixel_clock *= sdvo_pixel_multiply; + pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode); } if (IS_I9XX(pI830)) { @@ -461,7 +497,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; if (IS_I9XX(pI830)) { - if (outputs & PIPE_LCD_ACTIVE) + if (is_lvds) dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; @@ -486,55 +522,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= PLL_P2_DIVIDE_BY_4; } - if (outputs & (PIPE_TV_ACTIVE | PIPE_TV2_ACTIVE)) + if (is_tv) dpll |= PLL_REF_INPUT_TVCLKINBC; #if 0 - else if (outputs & (PIPE_LCD_ACTIVE)) + else if (is_lvds) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; #endif else dpll |= PLL_REF_INPUT_DREFCLK; - if (is_dvo) { - dpll |= DPLL_DVO_HIGH_SPEED; - - /* Save the data order, since I don't know what it should be set to. */ - dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); - dvo |= DVO_ENABLE; - dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; - - if (pipe == 1) - dvo |= DVO_PIPE_B_SELECT; - - if (pMode->Flags & V_PHSYNC) - dvo |= DVO_HSYNC_ACTIVE_HIGH; - if (pMode->Flags & V_PVSYNC) - dvo |= DVO_VSYNC_ACTIVE_HIGH; - - OUTREG(DVOC, dvo & ~DVO_ENABLE); - } - - if (is_sdvo) { - dpll |= DPLL_DVO_HIGH_SPEED; - - ErrorF("DVOB: %08x\nDVOC: %08x\n", (int)INREG(SDVOB), (int)INREG(SDVOC)); - - sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK; - sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK; - sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE; - sdvoc |= 9 << 19; - if (pipe == 1) - sdvob |= SDVO_PIPE_B_SELECT; - - if (IS_I945G(pI830) || IS_I945GM(pI830)) - dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else - sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; - - OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); - OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); - } - fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2); #if 1 @@ -576,150 +572,53 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dspcntr |= DISPPLANE_GAMMA_ENABLE; } - if (is_sdvo) - adpa = ADPA_DAC_DISABLE; - else - adpa = ADPA_DAC_ENABLE; - if (pMode->Flags & V_PHSYNC) - adpa |= ADPA_HSYNC_ACTIVE_HIGH; - if (pMode->Flags & V_PVSYNC) - adpa |= ADPA_VSYNC_ACTIVE_HIGH; - - if (pipe == 0) { + if (pipe == 0) dspcntr |= DISPPLANE_SEL_PIPE_A; - adpa |= ADPA_PIPE_A_SELECT; - } else { + else dspcntr |= DISPPLANE_SEL_PIPE_B; - adpa |= ADPA_PIPE_B_SELECT; - } OUTREG(VGACNTRL, VGA_DISP_DISABLE); - /* Set up display timings and PLLs for the pipe. */ - if (pipe == 0) { - /* First, disable display planes */ - temp = INREG(DSPACNTR); - OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); + /* Finally, set the mode. */ + /* First, disable display planes */ + temp = INREG(dspcntr_reg); + OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); - /* Next, disable display pipes */ - temp = INREG(PIPEACONF); - OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); + /* Next, disable display pipes */ + temp = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - OUTREG(FPA0, fp); - OUTREG(DPLL_A, dpll); + OUTREG(fp_reg, fp); + OUTREG(dpll_reg, dpll); - OUTREG(HTOTAL_A, htot); - OUTREG(HBLANK_A, hblank); - OUTREG(HSYNC_A, hsync); - OUTREG(VTOTAL_A, vtot); - OUTREG(VBLANK_A, vblank); - OUTREG(VSYNC_A, vsync); - OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp); - OUTREG(DSPASIZE, dspsize); - OUTREG(DSPAPOS, 0); - i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]); - OUTREG(PIPEASRC, pipesrc); - - /* Then, turn the pipe on first */ - temp = INREG(PIPEACONF); - OUTREG(PIPEACONF, temp | PIPEACONF_ENABLE); - - /* And then turn the plane on */ - OUTREG(DSPACNTR, dspcntr); - } else { - /* Always make sure the LVDS is off before we play with DPLLs and pipe - * configuration. - */ - i830SetLVDSPanelPower(pScrn, FALSE); - - /* First, disable display planes */ - temp = INREG(DSPBCNTR); - OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); - - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - - /* Next, disable display pipes */ - temp = INREG(PIPEBCONF); - OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - - if (outputs & PIPE_LCD_ACTIVE) { - /* Disable the PLL before messing with LVDS enable */ - OUTREG(FPB0, fp & ~DPLL_VCO_ENABLE); - - /* LVDS must be powered on before PLL is enabled and before power - * sequencing the panel. - */ - temp = INREG(LVDS); - OUTREG(LVDS, temp | LVDS_PORT_EN | LVDS_PIPEB_SELECT); - } - - OUTREG(FPB0, fp); - OUTREG(DPLL_B, dpll); - OUTREG(HTOTAL_B, htot); - OUTREG(HBLANK_B, hblank); - OUTREG(HSYNC_B, hsync); - OUTREG(VTOTAL_B, vtot); - OUTREG(VBLANK_B, vblank); - OUTREG(VSYNC_B, vsync); - OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp); - OUTREG(DSPBSIZE, dspsize); - OUTREG(DSPBPOS, 0); - i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]); - OUTREG(PIPEBSRC, pipesrc); - - if (outputs & PIPE_LCD_ACTIVE) { - CARD32 pfit_control; - - /* Enable automatic panel scaling so that non-native modes fill the - * screen. - */ - /* XXX: Allow (auto-?) enabling of 8-to-6 dithering */ - pfit_control = (PFIT_ENABLE | - VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); - if (pI830->panel_wants_dither) - pfit_control |= PANEL_8TO6_DITHER_ENABLE; - OUTREG(PFIT_CONTROL, pfit_control); - } - - /* Then, turn the pipe on first */ - temp = INREG(PIPEBCONF); - OUTREG(PIPEBCONF, temp | PIPEBCONF_ENABLE); - - /* And then turn the plane on */ - OUTREG(DSPBCNTR, dspcntr); - - if (outputs & PIPE_LCD_ACTIVE) { - i830SetLVDSPanelPower(pScrn, TRUE); - } + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].pipe == pipe) + pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode); } - if (outputs & PIPE_CRT_ACTIVE) - OUTREG(ADPA, adpa); + OUTREG(htot_reg, htot); + OUTREG(hblank_reg, hblank); + OUTREG(hsync_reg, hsync); + OUTREG(vtot_reg, vtot); + OUTREG(vblank_reg, vblank); + OUTREG(vsync_reg, vsync); + OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp); + OUTREG(dspsize_reg, dspsize); + OUTREG(dsppos_reg, 0); + i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]); + OUTREG(pipesrc_reg, pipesrc); - if (is_dvo) { - /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | - (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ - OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | - (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); - /*OUTREG(DVOB, dvo);*/ - OUTREG(DVOC, dvo); - } + /* Then, turn the pipe on first */ + temp = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); - if (is_sdvo) { - OUTREG(SDVOB, sdvob); - OUTREG(SDVOC, sdvoc); - } + /* And then turn the plane on */ + OUTREG(dspcntr_reg, dspcntr); - if (outputs & PIPE_LCD_ACTIVE) { - pI830->pipeCurMode[pipe] = *pMasterMode; - } else { - pI830->pipeCurMode[pipe] = *pMode; - } + pI830->pipeCurMode[pipe] = *pMode; return TRUE; } @@ -729,47 +628,15 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int outputsA, outputsB; + int i; outputsA = pI830->operatingDevices & 0xff; outputsB = (pI830->operatingDevices >> 8) & 0xff; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); - /* First, disable the unused outputs */ - if ((outputsA & PIPE_CRT_ACTIVE) == 0 && - (outputsB & PIPE_CRT_ACTIVE) == 0) - { - CARD32 adpa = INREG(ADPA); - - if (adpa & ADPA_DAC_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRT output\n"); - OUTREG(ADPA, adpa & ~ADPA_DAC_ENABLE); - } - } - - if ((outputsB & PIPE_LCD_ACTIVE) == 0) { - CARD32 pp_status = INREG(PP_STATUS); - - if (pp_status & PP_ON) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling LVDS output\n"); - i830SetLVDSPanelPower(pScrn, FALSE); - } - } - - if (IS_I9XX(pI830) && ((outputsA & PIPE_DFP_ACTIVE) == 0 && - (outputsB & PIPE_DFP_ACTIVE) == 0)) - { - CARD32 sdvob = INREG(SDVOB); - CARD32 sdvoc = INREG(SDVOC); - - if (sdvob & SDVO_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOB output\n"); - OUTREG(SDVOB, sdvob & ~SDVO_ENABLE); - } - if (sdvoc & SDVO_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling SDVOC output\n"); - OUTREG(SDVOC, sdvoc & ~SDVO_ENABLE); - } + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); } /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915 @@ -864,30 +731,21 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } for (i = 0; i < pI830->num_outputs; i++) { - I830OutputPtr output = &pI830->output[i]; - - if (pI830->output[i].type == I830_OUTPUT_SDVO) - pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); - - if (pI830->output[i].type == I830_OUTPUT_DVO) - output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, - pMode); + pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); } if (pI830->planeEnabled[0]) { - ok = i830PipeSetMode(pScrn, pMode, 0); + ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode), + 0); if (!ok) goto done; } if (pI830->planeEnabled[1]) { - ok = i830PipeSetMode(pScrn, pMode, 1); + ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode), + 1); if (!ok) goto done; } - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_SDVO) - I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode); - } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", (int)(pMode->HDisplay * pMode->VDisplay * @@ -1092,42 +950,3 @@ i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb) return FALSE; } - -/** - * Sets the power state for the panel. - */ -void -i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 pp_status, pp_control; - CARD32 blc_pwm_ctl; - int backlight_duty_cycle; - - blc_pwm_ctl = INREG (BLC_PWM_CTL); - backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK; - if (backlight_duty_cycle) - pI830->backlight_duty_cycle = backlight_duty_cycle; - - if (on) { - OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); - do { - pp_status = INREG(PP_STATUS); - pp_control = INREG(PP_CONTROL); - } while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON)); - OUTREG(BLC_PWM_CTL, - (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) | - pI830->backlight_duty_cycle); - } else { - OUTREG(BLC_PWM_CTL, - (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK)); - - OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); - OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); - do { - pp_status = INREG(PP_STATUS); - pp_control = INREG(PP_CONTROL); - } while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON)); - } -} diff --git a/src/i830_display.h b/src/i830_display.h index 91450fe0..df8356aa 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -32,6 +32,7 @@ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); +void i830WaitForVblank(ScrnInfoPtr pScrn); /* i830_sdvo.c */ Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 4b558559..3a278fb0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1528,7 +1528,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * that we might find early in the list. This hackery will go away when we * start doing independent per-head mode selection. */ - for (i = MAX_OUTPUTS - 1; i >= 0; i--) { + for (i = pI830->num_outputs - 1; i >= 0; i--) { if (pI830->output[i].MonInfo) { pScrn->monitor->DDC = pI830->output[i].MonInfo; xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); @@ -1668,11 +1668,50 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType1 |= PIPE_CRT; } + /* Perform the pipe assignment of outputs. This code shouldn't exist, + * but for now we're supporting the existing MonitorLayout configuration + * scheme. + */ + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].disabled = FALSE; + + switch (pI830->output[i].type) { + case I830_OUTPUT_LVDS: + if (pI830->MonType1 & PIPE_LFP) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_LFP) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + case I830_OUTPUT_ANALOG: + if (pI830->MonType1 & PIPE_CRT) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_CRT) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + if (pI830->MonType1 & PIPE_DFP) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_DFP) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); + break; + } + } + /* Check for attached SDVO outputs. Assume that they're flat panels for * now. Though really, it's just a name at the moment, since we don't * treat different SDVO outputs differently. */ - for (i = 0; i < MAX_OUTPUTS; i++) { + for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].type == I830_OUTPUT_SDVO) { if (!I830DetectSDVODisplays(pScrn, i)) continue; @@ -2607,11 +2646,6 @@ RestoreHWState(ScrnInfoPtr pScrn) vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); - /* Disable outputs */ - for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); - } - /* First, disable display planes */ temp = INREG(DSPACNTR); OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); @@ -2624,6 +2658,11 @@ RestoreHWState(ScrnInfoPtr pScrn) temp = INREG(PIPEBCONF); OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); + /* Disable outputs if necessary */ + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], NULL); + } + i830WaitForVblank(pScrn); OUTREG(FPA0, pI830->saveFPA0); @@ -4333,7 +4372,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n", found_crt ? "connected" : "disconnected", finish - start); - for (i = 0; i < MAX_OUTPUTS; i++) { + for (i = 0; i < pI830->num_outputs; i++) { Bool found_sdvo = TRUE; if (pI830->output[i].type != I830_OUTPUT_SDVO) diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 27f1755f..ea74337a 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -22,7 +22,8 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************/ +****** +********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -30,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86.h" #include "i830.h" +#include "i810_reg.h" #include "sil164/sil164.h" #include "ch7xxx/ch7xxx.h" @@ -90,6 +92,51 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv); } +static void +i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (output->i2c_drv == NULL) + return; + + output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode); + + OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE); +} + +static void +i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 dvo; + int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; + + /* Save the data order, since I don't know what it should be set to. */ + dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + dvo |= DVO_ENABLE; + dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; + + if (output->pipe == 1) + dvo |= DVO_PIPE_B_SELECT; + + if (pMode->Flags & V_PHSYNC) + dvo |= DVO_HSYNC_ACTIVE_HIGH; + if (pMode->Flags & V_PVSYNC) + dvo |= DVO_VSYNC_ACTIVE_HIGH; + + OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED); + + /*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ + OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | + (pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); + /*OUTREG(DVOB, dvo);*/ + OUTREG(DVOC, dvo); +} + static Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv) @@ -132,6 +179,8 @@ i830_dvo_init(ScrnInfoPtr pScrn) pI830->output[i].dpms = i830_dvo_dpms; pI830->output[i].save = i830_dvo_save; pI830->output[i].restore = i830_dvo_restore; + pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode ; + pI830->output[i].post_set_mode = i830_dvo_post_set_mode ; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 3ce8cb6e..23fc0a77 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -32,6 +32,45 @@ #include "xf86.h" #include "i830.h" +/** + * Sets the power state for the panel. + */ +static void +i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 pp_status, pp_control; + CARD32 blc_pwm_ctl; + int backlight_duty_cycle; + + blc_pwm_ctl = INREG (BLC_PWM_CTL); + backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK; + if (backlight_duty_cycle) + pI830->backlight_duty_cycle = backlight_duty_cycle; + + if (on) { + OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON); + do { + pp_status = INREG(PP_STATUS); + pp_control = INREG(PP_CONTROL); + } while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON)); + OUTREG(BLC_PWM_CTL, + (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) | + pI830->backlight_duty_cycle); + } else { + OUTREG(BLC_PWM_CTL, + (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK)); + + OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON); + OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON); + do { + pp_status = INREG(PP_STATUS); + pp_control = INREG(PP_CONTROL); + } while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON)); + } +} + static void i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { @@ -80,6 +119,49 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(PP_CONTROL, pI830->savePP_CONTROL); } +static void +i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + /* Always make sure the LVDS is off before we play with DPLLs and pipe + * configuration. We can skip this in some cases (for example, going + * between hi-res modes with automatic panel scaling are fine), but be + * conservative for now. + */ + i830SetLVDSPanelPower(pScrn, FALSE); +} + +static void +i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 pfit_control; + + /* Enable automatic panel scaling so that non-native modes fill the + * screen. Should be enabled before the pipe is enabled, according to + * register description. + */ + pfit_control = (PFIT_ENABLE | + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + + if (pI830->panel_wants_dither) + pfit_control |= PANEL_8TO6_DITHER_ENABLE; + + OUTREG(PFIT_CONTROL, pfit_control); + + /* Disable the PLL before messing with LVDS enable */ + OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE); + + /* LVDS must be powered on before PLL is enabled and before power + * sequencing the panel. + */ + OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); + + i830SetLVDSPanelPower(pScrn, TRUE); +} + void i830_lvds_init(ScrnInfoPtr pScrn) { @@ -89,6 +171,8 @@ i830_lvds_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms; pI830->output[pI830->num_outputs].save = i830_lvds_save; pI830->output[pI830->num_outputs].restore = i830_lvds_restore; + pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; + pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index f7d46950..83c6051b 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -750,7 +750,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) else outputs = (pI830->operatingDevices >> 8) & 0xff; - for (i = 0; i < MAX_OUTPUTS; i++) { + for (i = 0; i < pI830->num_outputs; i++) { switch (pI830->output[i].type) { case I830_OUTPUT_ANALOG: if (outputs & PIPE_CRT) { diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index dc17af0e..9a1e1550 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -34,6 +34,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "compiler.h" #include "i830.h" #include "i830_display.h" +#include "i810_reg.h" #include "i830_sdvo_regs.h" CARD16 curr_table[6]; @@ -169,6 +170,17 @@ I830SDVOReadInputRegs(I830SDVOPtr s) ErrorF("\n"); } +int +i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode) +{ + if (pMode->Clock >= 100000) + return 1; + else if (pMode->Clock >= 50000) + return 2; + else + return 4; +} + /* Sets the control bus switch to either point at one of the DDC buses or the * PROM. It resets from the DDC bus back to internal registers at the next I2C * STOP. PROM access is terminated by accessing an internal register. @@ -520,9 +532,11 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) return TRUE; } -Bool -I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) +static void +i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr mode) { + I830Ptr pI830 = I830PTR(pScrn); CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay; CARD16 height = mode->CrtcVDisplay; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; @@ -533,6 +547,7 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) CARD16 out_timings[6]; CARD16 clock_min, clock_max; Bool out1, out2; + I830SDVOPtr s = output->sdvo_drv; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -600,22 +615,34 @@ I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode) out_timings[5]); I830SDVOSetTargetInput (s, FALSE, FALSE); - - if (clock >= 10000) - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X); - else if (clock >= 5000) - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X); - else - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X); - return TRUE; + switch (i830_sdvo_get_pixel_multiplier(mode)) { + case 1: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X); + break; + case 2: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X); + break; + case 4: + I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X); + break; + } + + OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE); + OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); } -Bool -I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) +static void +i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr mode) { + I830Ptr pI830 = I830PTR(pScrn); Bool ret = TRUE; Bool out1, out2; + CARD32 dpll, sdvob, sdvoc; + int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; + int sdvo_pixel_multiply; + I830SDVOPtr s = output->sdvo_drv; /* the BIOS writes out 6 commands post mode set */ /* two 03s, 04 05, 10, 1d */ @@ -636,18 +663,41 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode) I830SDVOSetActiveOutputs(s, TRUE, FALSE); I830SDVOSetTargetInput (s, FALSE, FALSE); - return ret; + /* Set the SDVO control regs. */ + sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK; + sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK; + sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE; + sdvoc |= 9 << 19; + if (output->pipe == 1) + sdvob |= SDVO_PIPE_B_SELECT; + + dpll = INREG(dpll_reg); + + sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); + if (IS_I945G(pI830) || IS_I945GM(pI830)) + dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + else + sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; + + OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED); + + OUTREG(SDVOB, sdvob); + OUTREG(SDVOC, sdvoc); } static void i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { + I830Ptr pI830 = I830PTR(pScrn); I830SDVOPtr sdvo = output->sdvo_drv; - if (mode != DPMSModeOn) + if (mode != DPMSModeOn) { I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); - else + OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); + } else { I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE); + OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE); + } } static void @@ -857,13 +907,11 @@ void I830DumpSDVO (ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr s; int i; - for (i = 0; i < 4; i++) { - s = pI830->output[i].sdvo_drv; - if (s) - I830DumpOneSDVO (s); + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_SDVO) + I830DumpOneSDVO (pI830->output[i].sdvo_drv); } } @@ -906,6 +954,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms; pI830->output[pI830->num_outputs].save = i830_sdvo_save; pI830->output[pI830->num_outputs].restore = i830_sdvo_restore; + pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode; + pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode; /* Find an existing SDVO I2CBus from another output, or allocate it. */ for (i = 0; i < pI830->num_outputs; i++) { @@ -974,7 +1024,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) return; } - pI830->output[pI830->num_outputs].pI2CBus = ddcbus; + pI830->output[pI830->num_outputs].pI2CBus = i2cbus; pI830->output[pI830->num_outputs].pDDCBus = ddcbus; pI830->output[pI830->num_outputs].sdvo_drv = sdvo; diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 9a3586f2..44bbfe47 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -58,6 +58,9 @@ typedef struct _i830_sdvo_dtd { void i830_sdvo_init(ScrnInfoPtr pScrn, int output_device); +int +i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode); + Bool I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); From 09e3d10b0ff69d180467fa9099d12da08e4f681b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Oct 2006 13:09:18 -0700 Subject: [PATCH 179/257] Add a function for describing the output connection configuration. --- src/i830_display.c | 60 ++++++++++++++++++++++++++++++++++++---------- src/i830_display.h | 1 + 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 32ee6e2f..2693ded6 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -706,7 +706,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; - CARD32 planeA, planeB; #ifdef XF86DRI Bool didLock = FALSE; #endif @@ -777,18 +776,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) i830DisableUnusedFunctions(pScrn); - planeA = INREG(DSPACNTR); - planeB = INREG(DSPBCNTR); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Display plane A is now %s and connected to %s.\n", - pI830->planeEnabled[0] ? "enabled" : "disabled", - planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); - if (pI830->availablePipes == 2) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Display plane B is now %s and connected to %s.\n", - pI830->planeEnabled[1] ? "enabled" : "disabled", - planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + i830DescribeOutputConfiguration(pScrn); #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, TRUE); @@ -804,6 +792,52 @@ done: return ok; } +void +i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n"); + + for (i = 0; i < pI830->availablePipes; i++) { + CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " Display plane %c is now %s and connected to pipe %c.\n", + 'A' + i, + pI830->planeEnabled[i] ? "enabled" : "disabled", + dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A'); + } + + for (i = 0; i < pI830->num_outputs; i++) { + const char *name = NULL; + + switch (pI830->output[i].type) { + case I830_OUTPUT_ANALOG: + name = "CRT"; + break; + case I830_OUTPUT_LVDS: + name = "LVDS"; + break; + case I830_OUTPUT_SDVO: + name = "SDVO"; + break; + case I830_OUTPUT_DVO: + name = "DVO"; + break; + case I830_OUTPUT_TVOUT: + name = "TV"; + break; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " Output %s is %sabled and connected to pipe %c\n", + name, pI830->output[i].disabled ? "dis" : "en", + pI830->output[i].pipe == 0 ? 'A' : 'B'); + } +} + /** * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. * diff --git a/src/i830_display.h b/src/i830_display.h index df8356aa..97194062 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -33,6 +33,7 @@ Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); +void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); /* i830_sdvo.c */ Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); From 2591c1fcf15608d96031be4760cf08534461ca34 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Oct 2006 14:20:49 -0700 Subject: [PATCH 180/257] Fix LVDS restore path, and move pipe assignment for outputs to the right place. --- src/i830_driver.c | 89 ++++++++++++++++++++++++----------------------- src/i830_lvds.c | 7 ++++ 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3a278fb0..1f53915a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1668,45 +1668,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType1 |= PIPE_CRT; } - /* Perform the pipe assignment of outputs. This code shouldn't exist, - * but for now we're supporting the existing MonitorLayout configuration - * scheme. - */ - for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].disabled = FALSE; - - switch (pI830->output[i].type) { - case I830_OUTPUT_LVDS: - if (pI830->MonType1 & PIPE_LFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_LFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; - break; - case I830_OUTPUT_ANALOG: - if (pI830->MonType1 & PIPE_CRT) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_CRT) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; - break; - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - if (pI830->MonType1 & PIPE_DFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_DFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); - break; - } - } - /* Check for attached SDVO outputs. Assume that they're flat panels for * now. Though really, it's just a name at the moment, since we don't * treat different SDVO outputs differently. @@ -1766,6 +1727,48 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->Clone = TRUE; } + + /* Perform the pipe assignment of outputs. This code shouldn't exist, + * but for now we're supporting the existing MonitorLayout configuration + * scheme. + */ + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].disabled = FALSE; + + switch (pI830->output[i].type) { + case I830_OUTPUT_LVDS: + if (pI830->MonType1 & PIPE_LFP) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_LFP) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + case I830_OUTPUT_ANALOG: + if (pI830->MonType1 & PIPE_CRT) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_CRT) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + if (pI830->MonType1 & PIPE_DFP) + pI830->output[i].pipe = 0; + else if (pI830->MonType2 & PIPE_DFP) + pI830->output[i].pipe = 1; + else + pI830->output[i].disabled = TRUE; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); + break; + } + } + + + pI830->CloneRefresh = 60; /* default to 60Hz */ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH, &(pI830->CloneRefresh))) { @@ -2703,6 +2706,10 @@ RestoreHWState(ScrnInfoPtr pScrn) } } + for (i = 0; i < pI830->num_outputs; i++) { + pI830->output[i].restore(pScrn, &pI830->output[i]); + } + if (IS_I965G(pI830)) { OUTREG(DSPASURF, pI830->saveDSPABASE); OUTREG(DSPBSURF, pI830->saveDSPBBASE); @@ -2719,10 +2726,6 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPACNTR, pI830->saveDSPACNTR); OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].restore(pScrn, &pI830->output[i]); - } - for(i = 0; i < 7; i++) { OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 23fc0a77..186d33b5 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -117,6 +117,10 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); OUTREG(LVDS, pI830->saveLVDS); OUTREG(PP_CONTROL, pI830->savePP_CONTROL); + if (pI830->savePP_CONTROL & POWER_TARGET_ON) + i830SetLVDSPanelPower(pScrn, TRUE); + else + i830SetLVDSPanelPower(pScrn, FALSE); } static void @@ -159,6 +163,9 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, */ OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); + /* Re-enable the PLL */ + OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE); + i830SetLVDSPanelPower(pScrn, TRUE); } From 1838671476875e9f5b3dde235eacf9fb43afb66c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Oct 2006 12:41:01 -0700 Subject: [PATCH 181/257] Only disable the output when marked disabled. Also, remove a couple of dead variables. --- src/i830_display.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 2693ded6..9b20d65c 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -627,16 +627,13 @@ void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int outputsA, outputsB; int i; - outputsA = pI830->operatingDevices & 0xff; - outputsB = (pI830->operatingDevices >> 8) & 0xff; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); + if (pI830->output[i].disabled) + pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); } /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915 From c5cca4c20ae6b519e3b021a9d90809c1b3d1facb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Oct 2006 15:31:43 -0700 Subject: [PATCH 182/257] Advertise textured video adapter first --- src/i830_video.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 6a18f932..47f4a03f 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -454,19 +454,6 @@ I830InitVideo(ScreenPtr pScreen) xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); - /* Set up overlay video if we can do it at this depth. */ - if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) { - overlayAdaptor = I830SetupImageVideoOverlay(pScreen); - if (overlayAdaptor != NULL) { - adaptors[num_adaptors++] = overlayAdaptor; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to set up overlay video\n"); - } - I830InitOffscreenImages(pScreen); - } - /* Set up textured video if we can do it at this depth and we are on * supported hardware. */ @@ -481,6 +468,19 @@ I830InitVideo(ScreenPtr pScreen) } } + /* Set up overlay video if we can do it at this depth. */ + if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) { + overlayAdaptor = I830SetupImageVideoOverlay(pScreen); + if (overlayAdaptor != NULL) { + adaptors[num_adaptors++] = overlayAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up overlay video\n"); + } + I830InitOffscreenImages(pScreen); + } + if (num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); From 8149681f2eac0af3b70a9457c5204e17da56142b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 16 Oct 2006 16:51:04 -0700 Subject: [PATCH 183/257] Add a per-output mode-valid method. This is currently disconnected, but will be used in more overhaul work. This should be where any output limitations, such as clocks, resolution, scaling limits, or other options, are validated. Other limitations, such as chipset resolution limits, CRTC clock limits, etc. should be elsewhere. --- src/i830.h | 14 ++++++++++++++ src/i830_crt.c | 8 ++++++++ src/i830_dvo.c | 18 +++++++++++++----- src/i830_lvds.c | 8 ++++++++ src/i830_sdvo.c | 22 +++++++++++++++++++--- 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/i830.h b/src/i830.h index c41cb569..90fdcb85 100644 --- a/src/i830.h +++ b/src/i830.h @@ -211,6 +211,9 @@ typedef struct _I830SDVODriver { CARD32 output_device; /* SDVOB or SDVOC */ i830_sdvo_caps caps; + + CARD16 pixel_clock_min, pixel_clock_max; + int save_sdvo_mult; Bool save_sdvo_active_1, save_sdvo_active_2; i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; @@ -244,6 +247,17 @@ struct _I830OutputRec { */ void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output); + /** + * Callback for testing a video mode for a given output. + * + * This function should only check for cases where a mode can't be supported + * on the pipe specifically, and not represent generic CRTC limitations. + * + * \return MODE_OK if the mode is valid, or another MODE_* otherwise. + */ + int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode); + /** * Callback for setting up a video mode before any pipe/dpll changes. * diff --git a/src/i830_crt.c b/src/i830_crt.c index 1cf1687e..7721a0c2 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -76,6 +76,13 @@ i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(ADPA, pI830->saveADPA); } +static int +i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + return MODE_OK; +} + static void i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) @@ -114,6 +121,7 @@ i830_crt_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].dpms = i830_crt_dpms; pI830->output[pI830->num_outputs].save = i830_crt_save; pI830->output[pI830->num_outputs].restore = i830_crt_restore; + pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; diff --git a/src/i830_dvo.c b/src/i830_dvo.c index ea74337a..01858f2c 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -92,15 +92,22 @@ i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv); } +static int +i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode)) + return MODE_OK; + else + return MODE_BAD; +} + static void i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); - if (output->i2c_drv == NULL) - return; - output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode); OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE); @@ -179,8 +186,9 @@ i830_dvo_init(ScrnInfoPtr pScrn) pI830->output[i].dpms = i830_dvo_dpms; pI830->output[i].save = i830_dvo_save; pI830->output[i].restore = i830_dvo_restore; - pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode ; - pI830->output[i].post_set_mode = i830_dvo_post_set_mode ; + pI830->output[i].mode_valid = i830_dvo_mode_valid; + pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode; + pI830->output[i].post_set_mode = i830_dvo_post_set_mode; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 186d33b5..399324f0 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -123,6 +123,13 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) i830SetLVDSPanelPower(pScrn, FALSE); } +static int +i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + return MODE_OK; +} + static void i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) @@ -178,6 +185,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms; pI830->output[pI830->num_outputs].save = i830_lvds_save; pI830->output[pI830->num_outputs].restore = i830_lvds_restore; + pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 9a1e1550..76080dfa 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -545,7 +545,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, CARD8 c16a[8]; CARD8 c17a[8]; CARD16 out_timings[6]; - CARD16 clock_min, clock_max; Bool out1, out2; I830SDVOPtr s = output->sdvo_drv; @@ -588,8 +587,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, out_timings[5] = c17a[3] | ((short)c17a[2] << 8); I830SDVOSetTargetInput(s, FALSE, FALSE); - I830SDVOGetInputPixelClockRange(s, &clock_min, &clock_max); - ErrorF("clock min/max: %d %d\n", clock_min, clock_max); I830SDVOGetActiveOutputs(s, &out1, &out2); @@ -775,6 +772,21 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) sdvo->save_sdvo_active_2); } +static int +i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830SDVOPtr sdvo = output->sdvo_drv; + + if (sdvo->pixel_clock_min > pMode->Clock) + return MODE_CLOCK_HIGH; + + if (sdvo->pixel_clock_max < pMode->Clock) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + static void I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps) { @@ -954,6 +966,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms; pI830->output[pI830->num_outputs].save = i830_sdvo_save; pI830->output[pI830->num_outputs].restore = i830_sdvo_restore; + pI830->output[pI830->num_outputs].mode_valid = i830_sdvo_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode; @@ -1042,6 +1055,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) I830SDVOGetCapabilities(sdvo, &sdvo->caps); + I830SDVOGetInputPixelClockRange(sdvo, &sdvo->pixel_clock_min, + &sdvo->pixel_clock_max); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SDVO device VID/DID: %02X:%02X.%02X, %02X," "output 1: %c, output 2: %c\n", From a91c0cbab5de51885bfce7c7dce76f82c1b19553 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Oct 2006 14:30:38 -0700 Subject: [PATCH 184/257] Add work-in-progress integrated TV-out support. This is the TV connector on board for the 915GM and 945GM. It is currently not hooked up to output initialization as it's entirely untested. However, I think this is a reasonable starting point for getting TV-out actually working. --- src/Makefile.am | 1 + src/i810_reg.h | 563 ++++++++++++++++++++++++++++++++++++++++++++++++ src/i830.h | 5 + src/i830_tv.c | 430 ++++++++++++++++++++++++++++++++++++ 4 files changed, 999 insertions(+) create mode 100644 src/i830_tv.c diff --git a/src/Makefile.am b/src/Makefile.am index cab6fe92..0fce5e4f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ i810_drv_la_SOURCES = \ i830_sdvo.c \ i830_sdvo.h \ i830_sdvo_regs.h \ + i830_tv.c \ i830_xf86Modes.h \ i830_xf86Modes.c \ i915_3d.c \ diff --git a/src/i810_reg.h b/src/i810_reg.h index 4fec65ff..a80b66ee 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -26,9 +26,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +/** @file + * Register names and fields for Intel graphics. + */ + /* * Authors: * Keith Whitwell + * Eric Anholt * * based on the i740 driver by * Kevin E. Martin @@ -928,6 +933,564 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define LVDS_CLKA_POWER_DOWN (0 << 8) # define LVDS_CLKA_POWER_UP (3 << 8) +/** @defgroup TV_CTL + * @{ + */ +#define TV_CTL 0x68000 +/** Enables the TV encoder */ +# define TV_ENC_ENABLE (1 << 31) +/** Sources the TV encoder input from pipe B instead of A. */ +# define TV_ENC_PIPEB_SELECT (1 << 30) +/** Outputs composite video (DAC A only) */ +# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) +/** Outputs SVideo video (DAC B/C) */ +# define TV_ENC_OUTPUT_SVIDEO (1 << 28) +/** Outputs Component video (DAC A/B/C) */ +# define TV_ENC_OUTPUT_COMPONENT (2 << 28) +# define TV_TRILEVEL_SYNC (1 << 21) +/** Enables slow sync generation (945GM only) */ +# define TV_SLOW_SYNC (1 << 20) +/** Selects 4x oversampling for 480i and 576p */ +# define TV_OVERSAMPLE_4X (0 << 18) +/** Selects 2x oversampling for 720p and 1080i */ +# define TV_OVERSAMPLE_2X (1 << 18) +/** Selects no oversampling for 1080p */ +# define TV_OVERSAMPLE_NONE (2 << 18) +/** Selects 8x oversampling */ +# define TV_OVERSAMPLE_8X (3 << 18) +/** Selects progressive mode rather than interlaced */ +# define TV_PROGRESSIVE (1 << 17) +/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */ +# define TV_PAL_BURST (1 << 16) +/** Field for setting delay of Y compared to C */ +# define TV_YC_SKEW_MASK (7 << 12) +/** Enables a fix for 480p/576p standard definition modes on the 915GM only */ +# define TV_ENC_SDP_FIX (1 << 11) +/** + * Enables a fix for the 915GM only. + * + * Not sure what it does. + */ +# define TV_ENC_C0_FIX (1 << 10) +/** Bits that must be preserved by software */ +# define TV_CTL_SAVE ((3 << 8) | (3 << 6)) +# define TV_FUSE_STATE_MASK (3 << 4) +/** Read-only state that reports all features enabled */ +# define TV_FUSE_STATE_ENABLED (0 << 4) +/** Read-only state that reports that Macrovision is disabled in hardware*/ +# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) +/** Read-only state that reports that TV-out is disabled in hardware. */ +# define TV_FUSE_STATE_DISABLED (2 << 4) +/** + * This test mode forces the DACs to 50% of full output. + * + * This is used for load detection in combination with TVDAC_SENSE_MASK + */ +# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) +/** @} */ + +/** @defgroup TV_DAC + * @{ + */ +#define TV_DAC 0x68004 +/** + * Reports that DAC state change logic has reported change (RO). + * + * This gets cleared when TV_DAC_STATE_EN is cleared +*/ +# define TVDAC_STATE_CHG (1 << 31) +# define TVDAC_SENSE_MASK (7 << 28) +/** Reports that DAC A voltage is above the detect threshold */ +# define TVDAC_A_SENSE (1 << 30) +/** Reports that DAC B voltage is above the detect threshold */ +# define TVDAC_B_SENSE (1 << 29) +/** Reports that DAC C voltage is above the detect threshold */ +# define TVDAC_C_SENSE (1 << 28) +/** + * Enables DAC state detection logic, for load-based TV detection. + * + * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set + * to off, for load detection to work. + */ +# define TVDAC_STATE_CHG_EN (1 << 27) +/** Sets the DAC A sense value to high */ +# define TVDAC_A_SENSE_CTL (1 << 26) +/** Sets the DAC B sense value to high */ +# define TVDAC_B_SENSE_CTL (1 << 25) +/** Sets the DAC C sense value to high */ +# define TVDAC_C_SENSE_CTL (1 << 24) +/** Overrides the ENC_ENABLE and DAC voltage levels */ +# define DAC_CTL_OVERRIDE (1 << 7) +/** Sets the slew rate. Must be preserved in software */ +# define ENC_TVDAC_SLEW_FAST (1 << 6) +# define DAC_A_1_3_V (0 << 4) +# define DAC_A_1_1_V (1 << 4) +# define DAC_A_0_7_V (2 << 4) +# define DAC_A_OFF (3 << 4) +# define DAC_B_1_3_V (0 << 2) +# define DAC_B_1_1_V (1 << 2) +# define DAC_B_0_7_V (2 << 2) +# define DAC_B_OFF (3 << 2) +# define DAC_C_1_3_V (0 << 0) +# define DAC_C_1_1_V (1 << 0) +# define DAC_C_0_7_V (2 << 0) +# define DAC_C_OFF (3 << 0) +/** @} */ + +/** + * CSC coefficients are stored in a floating point format with 9 bits of + * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, + * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with + * -1 (0x3) being the only legal negative value. + */ +#define TV_CSC_Y 0x68010 +# define TV_RY_MASK 0x07ff0000 +# define TV_RY_SHIFT 16 +# define TV_GY_MASK 0x00000fff +# define TV_GY_SHIFT 0 + +#define TV_CSC_Y2 0x68014 +# define TV_BY_MASK 0x07ff0000 +# define TV_BY_SHIFT 16 +/** + * Y attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AY_MASK 0x000003ff +# define TV_AY_SHIFT 0 + +#define TV_CSC_U 0x68018 +# define TV_RU_MASK 0x07ff0000 +# define TV_RU_SHIFT 16 +# define TV_GU_MASK 0x000007ff +# define TV_GU_SHIFT 0 + +#define TV_CSC_U2 0x6801c +# define TV_BU_MASK 0x07ff0000 +# define TV_BU_SHIFT 16 +/** + * U attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AU_MASK 0x000003ff +# define TV_AU_SHIFT 0 + +#define TV_CSC_V 0x68020 +# define TV_RV_MASK 0x0fff0000 +# define TV_RV_SHIFT 16 +# define TV_GV_MASK 0x000007ff +# define TV_GV_SHIFT 0 + +#define TV_CSC_V2 0x68024 +# define TV_BV_MASK 0x07ff0000 +# define TV_BV_SHIFT 16 +/** + * V attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AV_MASK 0x000007ff +# define TV_AV_SHIFT 0 + +/** @defgroup TV_CSC_KNOBS + * @{ + */ +#define TV_CLR_KNOBS 0x68028 +/** 2s-complement brightness adjustment */ +# define TV_BRIGHTNESS_MASK 0xff000000 +# define TV_BRIGHTNESS_SHIFT 24 +/** Contrast adjustment, as a 2.6 unsigned floating point number */ +# define TV_CONTRAST_MASK 0x00ff0000 +# define TV_CONTRAST_SHIFT 16 +/** Saturation adjustment, as a 2.6 unsigned floating point number */ +# define TV_SATURATION_MASK 0x0000ff00 +# define TV_SATURATION_SHIFT 8 +/** Hue adjustment, as an integer phase angle in degrees */ +# define TV_HUE_MASK 0x000000ff +# define TV_HUE_SHIFT 0 +/** @} */ + +/** @defgroup TV_CLR_LEVEL + * @{ + */ +#define TV_CLR_LEVEL 0x6802c +/** Controls the DAC level for black */ +# define TV_BLACK_LEVEL_MASK 0x01ff0000 +# define TV_BLACK_LEVEL_SHIFT 16 +/** Controls the DAC level for blanking */ +# define TV_BLANK_LEVEL_MASK 0x000001ff +# define TV_BLANK_LEVEL_SHIFT 0 +/* @} */ + +/** @defgroup TV_H_CTL_1 + * @{ + */ +#define TV_H_CTL_1 0x68030 +/** Number of pixels in the hsync. */ +# define TV_HSYNC_END_MASK 0x1fff0000 +# define TV_HSYNC_END_SHIFT 16 +/** Total number of pixels minus one in the line (display and blanking). */ +# define TV_HTOTAL_MASK 0x00001fff +# define TV_HTOTAL_SHIFT 0 +/** @} */ + +/** @defgroup TV_H_CTL_2 + * @{ + */ +#define TV_H_CTL_2 0x68034 +/** Enables the colorburst (needed for non-component color) */ +# define TV_BURST_ENA (1 << 31) +/** Offset of the colorburst from the start of hsync, in pixels minus one. */ +# define TV_HBURST_START_SHIFT 16 +# define TV_HBURST_START_MASK 0x1fff0000 +/** Length of the colorburst */ +# define TV_HBURST_LEN_SHIFT 0 +# define TV_HBURST_LEN_MASK 0x0001fff +/** @} */ + +/** @defgroup TV_H_CTL_3 + * @{ + */ +#define TV_H_CTL_3 0x68038 +/** End of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_END_SHIFT 16 +# define TV_HBLANK_END_MASK 0x1fff0000 +/** Start of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_START_SHIFT 0 +# define TV_HBLANK_START_MASK 0x0001fff +/** @} */ + +/** @defgroup TV_V_CTL_1 + * @{ + */ +#define TV_V_CTL_1 0x6803c +/** XXX */ +# define TV_NBR_END_SHIFT 16 +# define TV_NBR_END_MASK 0x07ff0000 +/** XXX */ +# define TV_VI_END_F1_SHIFT 8 +# define TV_VI_END_F1_MASK 0x00003f00 +/** XXX */ +# define TV_VI_END_F2_SHIFT 0 +# define TV_VI_END_F2_MASK 0x0000003f +/** @} */ + +/** @defgroup TV_V_CTL_2 + * @{ + */ +#define TV_V_CTL_2 0x68040 +/** Length of vsync, in half lines */ +# define TV_VSYNC_LEN_MASK 0x07ff0000 +# define TV_VSYNC_LEN_SHIFT 16 +/** Offset of the start of vsync in field 1, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F1_MASK 0x00007f00 +# define TV_VSYNC_START_F1_SHIFT 8 +/** + * Offset of the start of vsync in field 2, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F2_MASK 0x0000007f +# define TV_VSYNC_START_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_3 + * @{ + */ +#define TV_V_CTL_3 0x68044 +/** Enables generation of the equalization signal */ +# define TV_EQUAL_ENA (1 << 31) +/** Length of vsync, in half lines */ +# define TV_VEQ_LEN_MASK 0x007f0000 +# define TV_VEQ_LEN_SHIFT 16 +/** Offset of the start of equalization in field 1, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F1_MASK 0x0007f00 +# define TV_VEQ_START_F1_SHIFT 8 +/** + * Offset of the start of equalization in field 2, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F2_MASK 0x000007f +# define TV_VEQ_START_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_4 + * @{ + */ +#define TV_V_CTL_4 0x68048 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F1_MASK 0x003f0000 +# define TV_VBURST_START_F1_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F1_MASK 0x000000ff +# define TV_VBURST_END_F1_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_5 + * @{ + */ +#define TV_V_CTL_5 0x6804c +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F2_MASK 0x003f0000 +# define TV_VBURST_START_F2_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F2_MASK 0x000000ff +# define TV_VBURST_END_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_6 + * @{ + */ +#define TV_V_CTL_6 0x68050 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F3_MASK 0x003f0000 +# define TV_VBURST_START_F3_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F3_MASK 0x000000ff +# define TV_VBURST_END_F3_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_7 + * @{ + */ +#define TV_V_CTL_7 0x68054 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F4_MASK 0x003f0000 +# define TV_VBURST_START_F4_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F4_MASK 0x000000ff +# define TV_VBURST_END_F4_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_1 + * @{ + */ +#define TV_SC_CTL_1 0x68060 +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA1_EN (1 << 31) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA2_EN (2 << 31) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA3_EN (3 << 31) +/** Sets the subcarrier DDA to reset frequency every other field */ +# define TV_SC_RESET_EVERY_2 (0 << 24) +/** Sets the subcarrier DDA to reset frequency every fourth field */ +# define TV_SC_RESET_EVERY_4 (1 << 24) +/** Sets the subcarrier DDA to reset frequency every eighth field */ +# define TV_SC_RESET_EVERY_8 (2 << 24) +/** Sets the subcarrier DDA to never reset the frequency */ +# define TV_SC_RESET_NEVER (3 << 24) +/** Sets the peak amplitude of the colorburst.*/ +# define TV_BURST_LEVEL_MASK 0x00ff0000 +# define TV_BURST_LEVEL_SHIFT 16 +/** Sets the increment of the first subcarrier phase generation DDA */ +# define TV_SCDDA1_INC_MASK 0x00000fff +# define TV_SCDDA1_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_2 + * @{ + */ +#define TV_SC_CTL_2 0x68068 +/** Sets the rollover for the second subcarrier phase generation DDA */ +# define TV_SCDDA2_SIZE_MASK 0x7fff0000 +# define TV_SCDDA2_SIZE_SHIFT 16 +/** Sets the increent of the second subcarrier phase generation DDA */ +# define TV_SCDDA2_INC_MASK 0x00007fff +# define TV_SCDDA2_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_3 + * @{ + */ +#define TV_SC_CTL_3 0x68068 +/** Sets the rollover for the third subcarrier phase generation DDA */ +# define TV_SCDDA3_SIZE_MASK 0x7fff0000 +# define TV_SCDDA3_SIZE_SHIFT 16 +/** Sets the increent of the third subcarrier phase generation DDA */ +# define TV_SCDDA3_INC_MASK 0x00007fff +# define TV_SCDDA3_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_WIN_POS + * @{ + */ +#define TV_WIN_POS 0x68070 +/** X coordinate of the display from the start of horizontal active */ +# define TV_XPOS_MASK 0x1fff0000 +# define TV_XPOS_SHIFT 16 +/** Y coordinate of the display from the start of vertical active (NBR) */ +# define TV_YPOS_MASK 0x00000fff +# define TV_YPOS_SHIFT 0 +/** @} */ + +/** @defgroup TV_WIN_SIZE + * @{ + */ +#define TV_WIN_SIZE 0x68074 +/** Horizontal size of the display window, measured in pixels*/ +# define TV_XSIZE_MASK 0x1fff0000 +# define TV_XSIZE_SHIFT 16 +/** + * Vertical size of the display window, measured in pixels. + * + * Must be even for interlaced modes. + */ +# define TV_YSIZE_MASK 0x00000fff +# define TV_YSIZE_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_1 + * @{ + */ +#define TV_FILTER_CTL_1 0x68080 +/** + * Enables automatic scaling calculation. + * + * If set, the rest of the registers are ignored, and the calculated values can + * be read back from the register. + */ +# define TV_AUTO_SCALE (1 << 31) +/** + * Disables the vertical filter. + * + * This is required on modes more than 1024 pixels wide */ +# define TV_V_FILTER_BYPASS (1 << 29) +/** Enables adaptive vertical filtering */ +# define TV_VADAPT (1 << 28) +# define TV_VADAPT_MODE_MASK (3 << 26) +/** Selects the least adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_LEAST (0 << 26) +/** Selects the moderately adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MODERATE (1 << 26) +/** Selects the most adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MOST (3 << 26) +/** + * Sets the horizontal scaling factor. + * + * This should be the fractional part of the horizontal scaling factor divided + * by the oversampling rate. TV_HSCALE should be less than 1, and set to: + * + * (src width - 1) / ((oversample * dest width) - 1) + */ +# define TV_HSCALE_FRAC_MASK 0x00003fff +# define TV_HSCALE_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_2 + * @{ + */ +#define TV_FILTER_CTL_2 0x68084 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) + */ +# define TV_VSCALE_INT_MASK 0x00038000 +# define TV_VSCALE_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * \sa TV_VSCALE_INT_MASK + */ +# define TV_VSCALE_FRAC_MASK 0x00007fff +# define TV_VSCALE_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_3 + * @{ + */ +#define TV_FILTER_CTL_3 0x68088 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + */ +# define TV_VSCALE_IP_INT_MASK 0x00038000 +# define TV_VSCALE_IP_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + * + * \sa TV_VSCALE_IP_INT_MASK + */ +# define TV_VSCALE_IP_FRAC_MASK 0x00007fff +# define TV_VSCALE_IP_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_CC_CONTROL + * @{ + */ +#define TV_CC_CONTROL 0x68090 +# define TV_CC_ENABLE (1 << 31) +/** + * Specifies which field to send the CC data in. + * + * CC data is usually sent in field 0. + */ +# define TV_CC_FID_MASK (1 << 27) +# define TV_CC_FID_SHIFT 27 +/** Sets the horizontal position of the CC data. Usually 135. */ +# define TV_CC_HOFF_MASK 0x03ff0000 +# define TV_CC_HOFF_SHIFT 16 +/** Sets the vertical position of the CC data. Usually 21 */ +# define TV_CC_LINE_MASK 0x0000003f +# define TV_CC_LINE_SHIFT 0 +/** @} */ + +/** @defgroup TV_CC_DATA + * @{ + */ +#define TV_CC_DATA 0x68094 +# define TV_CC_RDY (1 << 31) +/** Second word of CC data to be transmitted. */ +# define TV_CC_DATA_2_MASK 0x007f0000 +# define TV_CC_DATA_2_SHIFT 16 +/** First word of CC data to be transmitted. */ +# define TV_CC_DATA_1_MASK 0x0000007f +# define TV_CC_DATA_1_SHIFT 0 +/** @} + */ + +/** @{ */ +#define TV_H_LUMA_0 0x68100 +#define TV_H_LUMA_59 0x681ec +#define TV_H_CHROMA_0 0x68200 +#define TV_H_CHROMA_59 0x682ec +/** @} */ + #define PIPEACONF 0x70008 #define PIPEACONF_ENABLE (1<<31) #define PIPEACONF_DISABLE 0 diff --git a/src/i830.h b/src/i830.h index 90fdcb85..832061c5 100644 --- a/src/i830.h +++ b/src/i830.h @@ -279,6 +279,8 @@ struct _I830OutputRec { I2CBusPtr pDDCBus; struct _I830DVODriver *i2c_drv; I830SDVOPtr sdvo_drv; + /** Output-private structure. Should replace i2c_drv and sdvo_drv */ + void *dev_priv; }; typedef struct _I830Rec { @@ -693,6 +695,9 @@ Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, Rotation I830GetRotation(ScreenPtr pScreen); void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); +/* i830_tv.c */ +void i830_tv_init(ScrnInfoPtr pScrn); + /* * 12288 is set as the maximum, chosen because it is enough for * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. diff --git a/src/i830_tv.c b/src/i830_tv.c new file mode 100644 index 00000000..2adbe91b --- /dev/null +++ b/src/i830_tv.c @@ -0,0 +1,430 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/** @file + * Integrated TV-out support for the 915GM and 945GM. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" +#include "i830_display.h" + +enum tv_type { + TV_TYPE_UNKNOWN, + TV_TYPE_COMPOSITE, + TV_TYPE_SVIDEO, + TV_TYPE_COMPONENT +}; + +/** Private structure for the integrated TV support */ +struct i830_tv_priv { + CARD32 save_TV_H_CTL_1; + CARD32 save_TV_H_CTL_2; + CARD32 save_TV_H_CTL_3; + CARD32 save_TV_V_CTL_1; + CARD32 save_TV_V_CTL_2; + CARD32 save_TV_V_CTL_3; + CARD32 save_TV_V_CTL_4; + CARD32 save_TV_V_CTL_5; + CARD32 save_TV_V_CTL_6; + CARD32 save_TV_V_CTL_7; + CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3; + CARD32 save_TV_DAC; + CARD32 save_TV_CTL; +}; + +enum burst_modes { + TV_SC_NTSC_MJ, + TV_SC_PAL, + TV_SC_PAL_NC, + TV_SC_PAL_M, + TV_SC_NTSC_443 +}; + +const struct tv_sc_mode { + char *name; + int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc; + CARD32 sc_reset; + Bool pal_burst; +} tv_sc_modes[] = { + [TV_SC_NTSC_MJ] = { + "NTSC M/J", + 27456, 0, 135, 20800, 0, + TV_SC_RESET_EVERY_4, + FALSE + }, + [TV_SC_PAL] = { + "PAL", + 27648, 625, 168, 4122, 67, + TV_SC_RESET_EVERY_8, + TRUE + }, + [TV_SC_PAL_NC] = { + "PAL Nc", + 27648, 625, 135, 23578, 134, + TV_SC_RESET_EVERY_8, + TRUE + }, + [TV_SC_PAL_M] = { + "PAL M", + 27456, 0, 135, 16704, 0, + TV_SC_RESET_EVERY_8, + TRUE + }, + [TV_SC_NTSC_443] = { + "NTSC-4.43", + 27456, 525, 168, 4093, 310, + TV_SC_RESET_NEVER, + FALSE + }, +}; + +/** + * Register programming values for TV modes. + * + * These values account for -1s required. + */ +const struct tv_mode { + char *name; + CARD32 oversample; + int hsync_end, hblank_end, hblank_start, htotal; + Bool progressive; + int vsync_start_f1, vsync_start_f2, vsync_len; + Bool veq_ena; + int veq_start_f1, veq_start_f2, veq_len; + int vi_end_f1, vi_end_f2, nbr_end; + Bool burst_ena; + int hburst_start, hburst_len; + int vburst_start_f1, vburst_end_f1; + int vburst_start_f2, vburst_end_f2; + int vburst_start_f3, vburst_end_f3; + int vburst_start_f4, vburst_end_f4; +} tv_modes[] = { + { + "480i", + TV_OVERSAMPLE_8X, + 64, 124, 836, 857, + FALSE, + 6, 7, 6, + TRUE, 0, 1, 18, + 20, 21, 240, + TRUE, + 72, 34, 9, 240, 10, 240, 9, 240, 10, 240 + } +}; + + +static int +i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + CARD32 save_tv_ctl, save_tv_dac; + CARD32 tv_ctl, tv_dac; + I830Ptr pI830 = I830PTR(pScrn); + + save_tv_ctl = INREG(TV_CTL); + save_tv_dac = INREG(TV_DAC); + + /* First, we have to disable the encoder but source from the right pipe, + * which is already enabled. + */ + tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT); + if (output->pipe == 1) + tv_ctl |= TV_ENC_PIPEB_SELECT; + OUTREG(TV_CTL, tv_ctl); + + /* Then set the voltage overrides. */ + tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V; + OUTREG(TV_DAC, tv_dac); + + /* Enable sensing of the load. */ + tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; + OUTREG(TV_CTL, tv_ctl); + + tv_dac |= TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | + TVDAC_C_SENSE_CTL; + OUTREG(TV_DAC, tv_dac); + + /* Wait for things to take effect. */ + i830WaitForVblank(pScrn); + + tv_dac = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac); + OUTREG(TV_CTL, save_tv_ctl); + + if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Composite TV connection\n"); + return TV_TYPE_COMPOSITE; + } else if ((tv_dac & TVDAC_SENSE_MASK) == TVDAC_A_SENSE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected S-Video TV connection\n"); + return TV_TYPE_SVIDEO; + } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Component TV connection\n"); + return TV_TYPE_COMPONENT; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Couldn't detect TV connection\n"); + return TV_TYPE_UNKNOWN; + } +} + +static void +i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + switch(mode) { + case DPMSModeOn: + OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE); + break; + case DPMSModeStandby: + case DPMSModeSuspend: + case DPMSModeOff: + OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE); + break; + } +} + +static void +i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct i830_tv_priv *dev_priv = output->dev_priv; + + dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1); + dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2); + dev_priv->save_TV_H_CTL_3 = INREG(TV_H_CTL_3); + dev_priv->save_TV_V_CTL_1 = INREG(TV_V_CTL_1); + dev_priv->save_TV_V_CTL_2 = INREG(TV_V_CTL_2); + dev_priv->save_TV_V_CTL_3 = INREG(TV_V_CTL_3); + dev_priv->save_TV_V_CTL_4 = INREG(TV_V_CTL_4); + dev_priv->save_TV_V_CTL_5 = INREG(TV_V_CTL_5); + dev_priv->save_TV_V_CTL_6 = INREG(TV_V_CTL_6); + dev_priv->save_TV_V_CTL_7 = INREG(TV_V_CTL_7); + dev_priv->save_TV_SC_CTL_1 = INREG(TV_SC_CTL_1); + dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2); + dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3); + + dev_priv->save_TV_DAC = INREG(TV_DAC); + dev_priv->save_TV_CTL = INREG(TV_CTL); +} + +static void +i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct i830_tv_priv *dev_priv = output->dev_priv; + + OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1); + OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2); + OUTREG(TV_H_CTL_3, dev_priv->save_TV_H_CTL_3); + OUTREG(TV_V_CTL_1, dev_priv->save_TV_V_CTL_1); + OUTREG(TV_V_CTL_2, dev_priv->save_TV_V_CTL_2); + OUTREG(TV_V_CTL_3, dev_priv->save_TV_V_CTL_3); + OUTREG(TV_V_CTL_4, dev_priv->save_TV_V_CTL_4); + OUTREG(TV_V_CTL_5, dev_priv->save_TV_V_CTL_5); + OUTREG(TV_V_CTL_6, dev_priv->save_TV_V_CTL_6); + OUTREG(TV_V_CTL_7, dev_priv->save_TV_V_CTL_7); + OUTREG(TV_SC_CTL_1, dev_priv->save_TV_SC_CTL_1); + OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2); + OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3); + + OUTREG(TV_DAC, dev_priv->save_TV_DAC); + OUTREG(TV_CTL, dev_priv->save_TV_CTL); +} + +static int +i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + return MODE_OK; +} + +static void +i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + + /* Disable the encoder while we set up the pipe. */ + OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE); +} + +static void +i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, + DisplayModePtr pMode) +{ + I830Ptr pI830 = I830PTR(pScrn); + enum tv_type type; + const struct tv_mode *tv_mode; + const struct tv_sc_mode *sc_mode; + CARD32 tv_ctl, tv_filter_ctl; + CARD32 hctl1, hctl2, hctl3; + CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7; + CARD32 scctl1, scctl2, scctl3; + + /* Need to actually choose or construct the appropriate + * mode. For now, just set the first one in the list, with + * NTSC format. + */ + tv_mode = &tv_modes[0]; + sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ]; + + type = i830_tv_detect_type(pScrn, output); + if (type == TV_TYPE_UNKNOWN) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Defaulting TV to SVIDEO\n"); + type = TV_TYPE_SVIDEO; + } + + hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | + (tv_mode->htotal << TV_HTOTAL_SHIFT); + + hctl2 = (tv_mode->hburst_start << 16) | + (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT); + if (tv_mode->burst_ena) + hctl2 |= TV_BURST_ENA; + + hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) | + (tv_mode->hblank_end << TV_HBLANK_END_SHIFT); + + vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) | + (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) | + (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT); + + vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) | + (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) | + (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT); + + vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) | + (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) | + (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT); + if (tv_mode->veq_ena) + vctl3 |= TV_EQUAL_ENA; + + vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) | + (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT); + + vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) | + (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT); + + vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) | + (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT); + + vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) | + (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT); + + tv_ctl = TV_ENC_ENABLE; + if (output->pipe == 1) + tv_ctl |= TV_ENC_PIPEB_SELECT; + + switch (type) { + case TV_TYPE_COMPOSITE: + tv_ctl |= TV_ENC_OUTPUT_COMPOSITE; + break; + case TV_TYPE_COMPONENT: + tv_ctl |= TV_ENC_OUTPUT_COMPONENT; + break; + default: + case TV_TYPE_SVIDEO: + tv_ctl |= TV_ENC_OUTPUT_SVIDEO; + break; + } + tv_ctl |= tv_mode->oversample; + if (tv_mode->progressive) + tv_ctl |= TV_PROGRESSIVE; + if (sc_mode->pal_burst) + tv_ctl |= TV_PAL_BURST; + + scctl1 = TV_SC_DDA1_EN | TV_SC_DDA1_EN; + if (sc_mode->dda3_size != 0) + scctl1 |= TV_SC_DDA3_EN; + scctl1 |= sc_mode->sc_reset; + /* XXX: set the burst level */ + scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; + + scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | + sc_mode->dda2_inc << TV_SCDDA2_INC_SHIFT; + + scctl3 = sc_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT | + sc_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; + + /* Enable two fixes for the chips that need them. */ + if (pI830->PciInfo->chipType < PCI_CHIP_I945_G) + tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; + + tv_filter_ctl = TV_AUTO_SCALE; + if (pMode->HDisplay > 1024) + tv_ctl |= TV_V_FILTER_BYPASS; + + OUTREG(TV_H_CTL_1, hctl1); + OUTREG(TV_H_CTL_2, hctl2); + OUTREG(TV_H_CTL_3, hctl3); + OUTREG(TV_V_CTL_1, vctl1); + OUTREG(TV_V_CTL_2, vctl2); + OUTREG(TV_V_CTL_3, vctl3); + OUTREG(TV_V_CTL_4, vctl4); + OUTREG(TV_V_CTL_5, vctl5); + OUTREG(TV_V_CTL_6, vctl6); + OUTREG(TV_V_CTL_7, vctl7); + OUTREG(TV_SC_CTL_1, scctl1); + OUTREG(TV_SC_CTL_2, scctl2); + OUTREG(TV_SC_CTL_3, scctl3); + + OUTREG(TV_DAC, 0); + OUTREG(TV_CTL, tv_ctl); +} + +void +i830_tv_init(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) + return; + + pI830->output[pI830->num_outputs].dev_priv = + malloc(sizeof(struct i830_tv_priv)); + if (pI830->output[pI830->num_outputs].dev_priv == NULL) + return; + + pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG; + pI830->output[pI830->num_outputs].dpms = i830_tv_dpms; + pI830->output[pI830->num_outputs].save = i830_tv_save; + pI830->output[pI830->num_outputs].restore = i830_tv_restore; + pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid; + pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode; + pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode; + + pI830->num_outputs++; +} From cd2f0d948a6cae61b0d77d2c7184ed8d695be8c3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Oct 2006 17:47:47 -0700 Subject: [PATCH 185/257] Clean up SDVO code, moving the private structure internal and cleaning up caps. All the SDVO code should now be in lower case rather than StudlyCaps. This also adjusts the I2C setup to create a bus per SDVO output we set up. The previous setup with shared buses was failing in some circumstances, which is probably due to the lack of refcounting in xf86i2c.c. --- src/i830.h | 20 +- src/i830_display.c | 2 +- src/i830_display.h | 4 - src/i830_driver.c | 4 +- src/i830_modes.c | 2 +- src/i830_sdvo.c | 957 +++++++++++++++++++++++++-------------------- src/i830_sdvo.h | 4 +- 7 files changed, 547 insertions(+), 446 deletions(-) diff --git a/src/i830.h b/src/i830.h index 832061c5..b4408c26 100644 --- a/src/i830.h +++ b/src/i830.h @@ -205,22 +205,6 @@ struct _I830DVODriver { pointer modhandle; }; -typedef struct _I830SDVODriver { - I2CDevRec d; - unsigned char sdvo_regs[20]; - CARD32 output_device; /* SDVOB or SDVOC */ - - i830_sdvo_caps caps; - - CARD16 pixel_clock_min, pixel_clock_max; - - int save_sdvo_mult; - Bool save_sdvo_active_1, save_sdvo_active_2; - i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; - i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; - CARD32 save_SDVOX; -} I830SDVORec, *I830SDVOPtr; - extern const char *i830_output_type_names[]; struct _I830OutputRec { @@ -278,8 +262,7 @@ struct _I830OutputRec { I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; struct _I830DVODriver *i2c_drv; - I830SDVOPtr sdvo_drv; - /** Output-private structure. Should replace i2c_drv and sdvo_drv */ + /** Output-private structure. Should replace i2c_drv */ void *dev_priv; }; @@ -499,7 +482,6 @@ typedef struct _I830Rec { int ddc2; int num_outputs; struct _I830OutputRec output[MAX_OUTPUTS]; - I830SDVOPtr sdvo; /* Panel size pulled from the BIOS */ int PanelXRes, PanelYRes; diff --git a/src/i830_display.c b/src/i830_display.c index 9b20d65c..a94e21da 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -785,7 +785,7 @@ done: #endif i830DumpRegs (pScrn); - I830DumpSDVO (pScrn); + i830_sdvo_dump(pScrn); return ok; } diff --git a/src/i830_display.h b/src/i830_display.h index 97194062..229e576b 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -34,7 +34,3 @@ void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); - -/* i830_sdvo.c */ -Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode); -Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 972df137..4ee5fc27 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1673,7 +1673,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) */ for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].type == I830_OUTPUT_SDVO) { - if (!I830DetectSDVODisplays(pScrn, i)) + if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i])) continue; if (pI830->MonType1 == PIPE_NONE) @@ -4373,7 +4373,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) if (pI830->output[i].type != I830_OUTPUT_SDVO) continue; start = GetTimeInMillis(); - found_sdvo = I830DetectSDVODisplays(pScrn, i); + found_sdvo = i830_sdvo_detect_displays(pScrn, &pI830->output[i]); finish = GetTimeInMillis(); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n", found_sdvo ? "connected" : "disconnected", finish - start); diff --git a/src/i830_modes.c b/src/i830_modes.c index bc4536d5..f4306934 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -807,7 +807,7 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) if (pI830->pipeMon[pipe] == NULL) { switch (pI830->output[output_index].type) { case I830_OUTPUT_SDVO: - if (I830DetectSDVODisplays(pScrn, output_index)) + if (i830_sdvo_detect_displays(pScrn, &pI830->output[output_index])) pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); break; case I830_OUTPUT_ANALOG: diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 76080dfa..e028a9bb 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -23,6 +23,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +/** @file + * SDVO support for i915 and newer chipsets. + * + * The SDVO outputs send digital display data out over the PCIE bus to display + * cards implementing a defined interface. These cards may have DVI, TV, CRT, + * or other outputs on them. + * + * The system has two SDVO channels, which may be used for SDVO chips on the + * motherboard, or in the external cards. The two channels may also be used + * in a ganged mode to provide higher bandwidth to a single output. Currently, + * this code doesn't deal with either ganged mode or more than one SDVO output. + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -37,26 +50,58 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i810_reg.h" #include "i830_sdvo_regs.h" +/** SDVO driver private structure. */ +struct i830_sdvo_priv { + /** SDVO device on SDVO I2C bus. */ + I2CDevRec d; + /** Temporary storage for reg read/writes */ + unsigned char sdvo_regs[20]; + /** Register for the SDVO device: SDVOB or SDVOC */ + int output_device; + /** + * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities() + */ + i830_sdvo_caps caps; + /** Pixel clock limitations reported by the SDVO device */ + CARD16 pixel_clock_min, pixel_clock_max; + + /** State for save/restore */ + /** @{ */ + int save_sdvo_mult; + Bool save_sdvo_active_1, save_sdvo_active_2; + i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; + i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; + CARD32 save_SDVOX; + /** @} */ +}; + CARD16 curr_table[6]; -/* SDVO support for i9xx chipsets */ -static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch) +/** Read a single byte from the given address on the SDVO device. */ +static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr, + unsigned char *ch) { - if (!xf86I2CReadByte(&s->d, addr, ch)) { - xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, - "Unable to read from %s Slave %d.\n", s->d.pI2CBus->BusName, - s->d.SlaveAddr); + struct i830_sdvo_priv *dev_priv = output->dev_priv; + + if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) { + xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s slave %d.\n", + output->pI2CBus->BusName, dev_priv->d.SlaveAddr); return FALSE; } return TRUE; } -static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) +/** Write a single byte to the given address on the SDVO device. */ +static Bool i830_sdvo_write_byte(I830OutputPtr output, + int addr, unsigned char ch) { - if (!xf86I2CWriteByte(&s->d, addr, ch)) { - xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, - "Unable to write to %s Slave %d.\n", s->d.pI2CBus->BusName, - s->d.SlaveAddr); + struct i830_sdvo_priv *dev_priv = output->dev_priv; + + if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) { + xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + output->pI2CBus->BusName, dev_priv->d.SlaveAddr); return FALSE; } return TRUE; @@ -64,6 +109,7 @@ static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch) #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} +/** Mapping of command numbers to names, for debug output */ const struct _sdvo_cmd_name { CARD8 cmd; char *name; @@ -106,19 +152,21 @@ const struct _sdvo_cmd_name { SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), }; + /* following on from tracing the intel BIOS i2c routines */ static void -I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) +i830_sdvo_write_outputs(I830OutputPtr output, int num_out) { + struct i830_sdvo_priv *dev_priv = output->dev_priv; int i; - ErrorF("SDVO: W: %02X ", s->sdvo_regs[SDVO_I2C_OPCODE]); + ErrorF("SDVO: W: %02X ", dev_priv->sdvo_regs[SDVO_I2C_OPCODE]); for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) - ErrorF("%02X ", s->sdvo_regs[i]); + ErrorF("%02X ", dev_priv->sdvo_regs[i]); for (; i > SDVO_I2C_ARG_7; i--) ErrorF(" "); for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { - if (s->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) { + if (dev_priv->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) { ErrorF("(%s)", sdvo_cmd_names[i].name); break; } @@ -127,10 +175,11 @@ I830SDVOWriteOutputs(I830SDVOPtr s, int num_out) /* blast the output regs */ for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) { - sWriteByte(s, i, s->sdvo_regs[i]); + i830_sdvo_write_byte(output, i, dev_priv->sdvo_regs[i]); } /* blast the command reg */ - sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]); + i830_sdvo_write_byte(output, SDVO_I2C_OPCODE, + dev_priv->sdvo_regs[SDVO_I2C_OPCODE]); } static const char *cmd_status_names[] = { @@ -144,29 +193,43 @@ static const char *cmd_status_names[] = { }; static void -I830SDVOReadInputRegs(I830SDVOPtr s) +i830_sdvo_read_input_regs(I830OutputPtr output) { + struct i830_sdvo_priv *dev_priv = output->dev_priv; int i; /* follow BIOS ordering */ - sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]); - - sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]); - sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]); - sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]); - sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]); - sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]); - sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]); - sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]); - sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]); + i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, + &dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]); + + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_3, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_2, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_1, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_7, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_6, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_5, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]); + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_4, + &dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]); ErrorF("SDVO: R: "); for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++) - ErrorF("%02X ", s->sdvo_regs[i]); - if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - ErrorF("(%s)", cmd_status_names[s->sdvo_regs[SDVO_I2C_CMD_STATUS]]); - else - ErrorF("(??? %d)", s->sdvo_regs[SDVO_I2C_CMD_STATUS]); + ErrorF("%02X ", dev_priv->sdvo_regs[i]); + if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] <= + SDVO_CMD_STATUS_SCALING_NOT_SUPP) + { + ErrorF("(%s)", + cmd_status_names[dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]]); + } else { + ErrorF("(??? %d)", dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]); + } ErrorF("\n"); } @@ -186,355 +249,395 @@ i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode) * STOP. PROM access is terminated by accessing an internal register. */ static Bool -I830SDVOSetControlBusSwitch(I830SDVOPtr s, CARD8 target) +i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; - s->sdvo_regs[SDVO_I2C_ARG_0] = target; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 1); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target; + + i830_sdvo_write_outputs(output, 1); return TRUE; } static Bool -I830SDVOSetTargetInput(I830SDVOPtr s, Bool target_1, Bool target_2) +i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; - s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; - s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 2); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2; - I830SDVOReadInputRegs(s); + i830_sdvo_write_outputs(output, 2); + + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOGetTrainedInputs(I830SDVOPtr s) +i830_sdvo_get_trained_inputs(I830OutputPtr output) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS; + + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOGetActiveOutputs(I830SDVOPtr s, Bool *on_1, Bool *on_2) +i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS; - *on_1 = s->sdvo_regs[SDVO_I2C_RETURN_0]; - *on_2 = s->sdvo_regs[SDVO_I2C_RETURN_1]; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + *on_1 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; + *on_2 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; return TRUE; } static Bool -I830SDVOSetActiveOutputs(I830SDVOPtr s, Bool on_1, Bool on_2) +i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS; - s->sdvo_regs[SDVO_I2C_ARG_0] = on_1; - s->sdvo_regs[SDVO_I2C_ARG_1] = on_2; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 2); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = on_1; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = on_2; + + i830_sdvo_write_outputs(output, 2); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 *clock_min, - CARD16 *clock_max) +i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, + CARD16 *clock_max) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = + SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE; - *clock_min = s->sdvo_regs[SDVO_I2C_RETURN_0] | - (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - *clock_max = s->sdvo_regs[SDVO_I2C_RETURN_2] | - (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + *clock_min = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + *clock_max = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); return TRUE; } static Bool -I830SDVOSetTargetOutput(I830SDVOPtr s, Bool target_1, Bool target_2) +i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT; - s->sdvo_regs[SDVO_I2C_ARG_0] = target_1; - s->sdvo_regs[SDVO_I2C_ARG_1] = target_2; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 2); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2; + + i830_sdvo_write_outputs(output, 2); + i830_sdvo_read_input_regs(output); return TRUE; } /* Fetches either input or output timings to *dtd, depending on cmd. */ static Bool -I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) +i830_sdvo_get_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd) { - memset(s->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] | - (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2]; - dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3]; - dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4]; - dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5]; - dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6]; - dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7]; + memset(dev_priv->sdvo_regs, 0, 9); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); - memset(s->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dtd->clock = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + dtd->h_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; + dtd->h_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; + dtd->h_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; + dtd->v_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; + dtd->v_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; + dtd->v_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; - dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0]; - dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1]; - dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2]; - dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3]; - dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4]; - dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5]; - dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6]; - dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7]; + memset(dev_priv->sdvo_regs, 0, 9); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + dtd->h_sync_off = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; + dtd->h_sync_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; + dtd->v_sync_off_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; + dtd->sync_off_width_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; + dtd->dtd_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; + dtd->sdvo_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; + dtd->v_sync_off_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; + dtd->reserved = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; return TRUE; } /* Sets either input or output timings to *dtd, depending on cmd. */ static Bool -I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd) +i830_sdvo_set_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd) { - memset(s->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8; - s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active; - s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank; - s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high; - s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active; - s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank; - s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high; - I830SDVOWriteOutputs(s, 8); - I830SDVOReadInputRegs(s); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - memset(s->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; - s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off; - s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width; - s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width; - s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high; - s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags; - s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags; - s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high; - s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved; - I830SDVOWriteOutputs(s, 7); - I830SDVOReadInputRegs(s); + memset(dev_priv->sdvo_regs, 0, 9); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8; + dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active; + dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank; + dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high; + dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active; + dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank; + dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high; + i830_sdvo_write_outputs(output, 8); + i830_sdvo_read_input_regs(output); + + memset(dev_priv->sdvo_regs, 0, 9); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width; + dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width; + dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high; + dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags; + dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags; + dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high; + dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved; + i830_sdvo_write_outputs(output, 7); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1, - CARD16 magic2, CARD16 magic3) +i830_sdvo_set_timings_part1(I830OutputPtr output, char cmd, CARD16 clock, + CARD16 magic1, CARD16 magic2, CARD16 magic3) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + memset(dev_priv->sdvo_regs, 0, 9); + + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; /* set clock regs */ - s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff; - I830SDVOWriteOutputs(s, 8); - I830SDVOReadInputRegs(s); + i830_sdvo_write_outputs(output, 8); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock, - CARD16 magic1, CARD16 magic2, CARD16 magic3) +i830_sdvo_set_input_timings_part1(I830OutputPtr output, CARD16 clock, + CARD16 magic1, CARD16 magic2, CARD16 magic3) { - return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1, - clock, magic1, magic2, magic3); + return i830_sdvo_set_timings_part1(output, + SDVO_CMD_SET_INPUT_TIMINGS_PART1, + clock, magic1, magic2, magic3); } static Bool -I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1, - CARD16 magic2, CARD16 magic3) +i830_sdvo_set_output_timings_part1(I830OutputPtr output, CARD16 clock, + CARD16 magic1, CARD16 magic2, CARD16 magic3) { - return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, - clock, magic1, magic2, magic3); + return i830_sdvo_set_timings_part1(output, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, + clock, magic1, magic2, magic3); } static Bool -I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5, - CARD16 magic6) +i830_sdvo_set_timings_part2(I830OutputPtr output, CARD8 cmd, + CARD16 magic4, CARD16 magic5, CARD16 magic6) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; + + memset(dev_priv->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = cmd; + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; /* set clock regs */ - s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff; - I830SDVOWriteOutputs(s, 8); - I830SDVOReadInputRegs(s); + i830_sdvo_write_outputs(output, 8); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5, - CARD16 magic6) +i830_sdvo_set_input_timings_part2(I830OutputPtr output, + CARD16 magic4, CARD16 magic5, CARD16 magic6) { - return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4, - magic5, magic6); + return i830_sdvo_set_timings_part2(output, + SDVO_CMD_SET_INPUT_TIMINGS_PART2, + magic4, magic5, magic6); } static Bool -I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5, - CARD16 magic6) +i830_sdvo_set_output_timings_part2(I830OutputPtr output, + CARD16 magic4, CARD16 magic5, CARD16 magic6) { - return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4, - magic5, magic6); + return i830_sdvo_set_timings_part2(output, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, + magic4, magic5, magic6); } static Bool -I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width, - CARD16 height) +i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock, + CARD16 width, CARD16 height) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING; + memset(dev_priv->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff; - s->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = + SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING; - I830SDVOWriteOutputs(s, 7); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff; + dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff; + + i830_sdvo_write_outputs(output, 7); + i830_sdvo_read_input_regs(output); return TRUE; } static Bool -I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s) +i830_sdvo_get_preferred_input_timing_part1(I830OutputPtr output) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = + SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1; - curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] | - (s->sdvo_regs[SDVO_I2C_RETURN_7] << 8); - curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] | - (s->sdvo_regs[SDVO_I2C_RETURN_5] << 8); - curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] | - (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + curr_table[0] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_7] << 8); + curr_table[1] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_5] << 8); + curr_table[2] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); return TRUE; } static Bool -I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s) +i830_sdvo_get_preferred_input_timing_part2(I830OutputPtr output) { - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2; + struct i830_sdvo_priv *dev_priv = output->dev_priv; - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = + SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2; - curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] | - (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] | - (s->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + curr_table[3] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); + curr_table[4] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | + (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); curr_table[5] = 0x1e; return TRUE; } static int -I830SDVOGetClockRateMult(I830SDVOPtr s) +i830_sdvo_get_clock_rate_mult(I830OutputPtr output) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT; + memset(dev_priv->sdvo_regs, 0, 9); - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT; - if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) { - xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR, + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) { + xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR, "Couldn't get SDVO clock rate multiplier\n"); return SDVO_CLOCK_RATE_MULT_1X; } else { - xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO, + xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO, "Current clock rate multiplier: %d\n", - s->sdvo_regs[SDVO_I2C_RETURN_0]); + dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]); } - return s->sdvo_regs[SDVO_I2C_RETURN_0]; + return dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; } static Bool -I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val) +i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val) { - memset(s->sdvo_regs, 0, 9); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT; + memset(dev_priv->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_ARG_0] = val; - I830SDVOWriteOutputs(s, 1); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT; + + dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = val; + i830_sdvo_write_outputs(output, 1); + i830_sdvo_read_input_regs(output); return TRUE; } static void i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr mode) + DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay; @@ -546,7 +649,6 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, CARD8 c17a[8]; CARD16 out_timings[6]; Bool out1, out2; - I830SDVOPtr s = output->sdvo_drv; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -586,42 +688,44 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, out_timings[4] = c17a[5] | ((short)c17a[4] << 8); out_timings[5] = c17a[3] | ((short)c17a[2] << 8); - I830SDVOSetTargetInput(s, FALSE, FALSE); + i830_sdvo_set_target_input(output, FALSE, FALSE); - I830SDVOGetActiveOutputs(s, &out1, &out2); + i830_sdvo_get_active_outputs(output, &out1, &out2); - I830SDVOSetActiveOutputs(s, FALSE, FALSE); + i830_sdvo_set_active_outputs(output, FALSE, FALSE); - I830SDVOSetTargetOutput(s, TRUE, FALSE); - I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1], - out_timings[2]); - I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4], - out_timings[5]); + i830_sdvo_set_target_output(output, TRUE, FALSE); + i830_sdvo_set_output_timings_part1(output, clock, + out_timings[0], out_timings[1], + out_timings[2]); + i830_sdvo_set_output_timings_part2(output, out_timings[3], out_timings[4], + out_timings[5]); - I830SDVOSetTargetInput (s, FALSE, FALSE); + i830_sdvo_set_target_input(output, FALSE, FALSE); - I830SDVOCreatePreferredInputTiming(s, clock, width, height); - I830SDVOGetPreferredInputTimingPart1(s); - I830SDVOGetPreferredInputTimingPart2(s); + i830_sdvo_create_preferred_input_timing(output, clock, width, height); + i830_sdvo_get_preferred_input_timing_part1(output); + i830_sdvo_get_preferred_input_timing_part2(output); - I830SDVOSetTargetInput (s, FALSE, FALSE); + i830_sdvo_set_target_input(output, FALSE, FALSE); - I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1], - curr_table[2]); - I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4], - out_timings[5]); + i830_sdvo_set_input_timings_part1(output, clock, + curr_table[0], curr_table[1], + curr_table[2]); + i830_sdvo_set_input_timings_part2(output, curr_table[3], curr_table[4], + out_timings[5]); - I830SDVOSetTargetInput (s, FALSE, FALSE); + i830_sdvo_set_target_input(output, FALSE, FALSE); switch (i830_sdvo_get_pixel_multiplier(mode)) { case 1: - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_1X); + i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_1X); break; case 2: - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_2X); + i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_2X); break; case 4: - I830SDVOSetClockRateMult(s, SDVO_CLOCK_RATE_MULT_4X); + i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_4X); break; } @@ -634,31 +738,31 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); + struct i830_sdvo_priv *dev_priv = output->dev_priv; Bool ret = TRUE; Bool out1, out2; CARD32 dpll, sdvob, sdvoc; int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; int sdvo_pixel_multiply; - I830SDVOPtr s = output->sdvo_drv; /* the BIOS writes out 6 commands post mode set */ /* two 03s, 04 05, 10, 1d */ /* these contain the height and mode clock / 10 by the looks of it */ - I830SDVOGetTrainedInputs(s); + i830_sdvo_get_trained_inputs(output); /* THIS IS A DIRTY HACK - sometimes for some reason on startup * the BIOS doesn't find my DVI monitor - * without this hack the driver doesn't work.. this causes the modesetting * to be re-run */ - if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) { + if (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) { ret = FALSE; } - I830SDVOGetActiveOutputs (s, &out1, &out2); - I830SDVOSetActiveOutputs(s, TRUE, FALSE); - I830SDVOSetTargetInput (s, FALSE, FALSE); + i830_sdvo_get_active_outputs(output, &out1, &out2); + i830_sdvo_set_active_outputs(output, TRUE, FALSE); + i830_sdvo_set_target_input(output, FALSE, FALSE); /* Set the SDVO control regs. */ sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK; @@ -686,13 +790,12 @@ static void i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = output->sdvo_drv; if (mode != DPMSModeOn) { - I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE); + i830_sdvo_set_active_outputs(output, FALSE, FALSE); OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); } else { - I830SDVOSetActiveOutputs(sdvo, TRUE, FALSE); + i830_sdvo_set_active_outputs(output, TRUE, FALSE); OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE); } } @@ -701,115 +804,118 @@ static void i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = output->sdvo_drv; + struct i830_sdvo_priv *dev_priv = output->dev_priv; - sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo); - I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1, - &sdvo->save_sdvo_active_2); + dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output); + i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1, + &dev_priv->save_sdvo_active_2); - if (sdvo->caps.caps & 0x1) { - I830SDVOSetTargetInput(sdvo, FALSE, FALSE); - I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); + if (dev_priv->caps.caps & 0x1) { + i830_sdvo_set_target_input(output, FALSE, FALSE); + i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_1, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); } - if (sdvo->caps.caps & 0x2) { - I830SDVOSetTargetInput(sdvo, FALSE, TRUE); - I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); + if (dev_priv->caps.caps & 0x2) { + i830_sdvo_set_target_input(output, FALSE, TRUE); + i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2, + SDVO_CMD_GET_INPUT_TIMINGS_PART1); } - if (sdvo->caps.output_0_supported) { - I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); - I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + if (dev_priv->caps.output_0_supported) { + i830_sdvo_set_target_output(output, TRUE, FALSE); + i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); } - if (sdvo->caps.output_1_supported) { - I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); - I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + if (dev_priv->caps.output_1_supported) { + i830_sdvo_set_target_output(output, FALSE, TRUE); + i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_2, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); } - sdvo->save_SDVOX = INREG(sdvo->output_device); + dev_priv->save_SDVOX = INREG(dev_priv->output_device); } static void i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo = output->sdvo_drv; + struct i830_sdvo_priv *dev_priv = output->dev_priv; - if (sdvo->caps.caps & 0x1) { - I830SDVOSetTargetInput(sdvo, FALSE, FALSE); - I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); + if (dev_priv->caps.caps & 0x1) { + i830_sdvo_set_target_input(output, FALSE, FALSE); + i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_1, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); } - if (sdvo->caps.caps & 0x2) { - I830SDVOSetTargetInput(sdvo, FALSE, TRUE); - I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); + if (dev_priv->caps.caps & 0x2) { + i830_sdvo_set_target_input(output, FALSE, TRUE); + i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_2, + SDVO_CMD_SET_INPUT_TIMINGS_PART1); } - if (sdvo->caps.output_0_supported) { - I830SDVOSetTargetOutput(sdvo, TRUE, FALSE); - I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + if (dev_priv->caps.output_0_supported) { + i830_sdvo_set_target_output(output, TRUE, FALSE); + i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_1, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); } - if (sdvo->caps.output_1_supported) { - I830SDVOSetTargetOutput(sdvo, FALSE, TRUE); - I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + if (dev_priv->caps.output_1_supported) { + i830_sdvo_set_target_output(output, FALSE, TRUE); + i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_2, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); } - I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult); + i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult); - OUTREG(sdvo->output_device, sdvo->save_SDVOX); + OUTREG(dev_priv->output_device, dev_priv->save_SDVOX); - I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1, - sdvo->save_sdvo_active_2); + i830_sdvo_set_active_outputs(output, dev_priv->save_sdvo_active_1, + dev_priv->save_sdvo_active_2); } static int i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) { - I830SDVOPtr sdvo = output->sdvo_drv; + struct i830_sdvo_priv *dev_priv = output->dev_priv; - if (sdvo->pixel_clock_min > pMode->Clock) + if (dev_priv->pixel_clock_min > pMode->Clock) return MODE_CLOCK_HIGH; - if (sdvo->pixel_clock_max < pMode->Clock) + if (dev_priv->pixel_clock_max < pMode->Clock) return MODE_CLOCK_LOW; return MODE_OK; } static void -I830SDVOGetCapabilities(I830SDVOPtr s, i830_sdvo_caps *caps) +i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps) { - memset(s->sdvo_regs, 0, 9); - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS; - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + struct i830_sdvo_priv *dev_priv = output->dev_priv; - caps->vendor_id = s->sdvo_regs[SDVO_I2C_RETURN_0]; - caps->device_id = s->sdvo_regs[SDVO_I2C_RETURN_1]; - caps->device_rev_id = s->sdvo_regs[SDVO_I2C_RETURN_2]; - caps->sdvo_version_major = s->sdvo_regs[SDVO_I2C_RETURN_3]; - caps->sdvo_version_minor = s->sdvo_regs[SDVO_I2C_RETURN_4]; - caps->caps = s->sdvo_regs[SDVO_I2C_RETURN_5]; - caps->output_0_supported = s->sdvo_regs[SDVO_I2C_RETURN_6]; - caps->output_1_supported = s->sdvo_regs[SDVO_I2C_RETURN_7]; + memset(dev_priv->sdvo_regs, 0, 9); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); + + caps->vendor_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; + caps->device_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; + caps->device_rev_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; + caps->sdvo_version_major = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; + caps->sdvo_version_minor = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; + caps->caps = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; + caps->output_0_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; + caps->output_1_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; } +/** Forces the device over to the real I2C bus and uses its GetByte */ static Bool -I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last) { - I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; - I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = output->pI2CBus, savebus; Bool ret; savebus = d->pI2CBus; @@ -820,11 +926,12 @@ I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) return ret; } +/** Forces the device over to the real I2C bus and uses its PutByte */ static Bool -I830SDVODDCI2CPutByte(I2CDevPtr d, I2CByte c) +i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c) { - I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; - I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = output->pI2CBus, savebus; Bool ret; savebus = d->pI2CBus; @@ -835,21 +942,29 @@ I830SDVODDCI2CPutByte(I2CDevPtr d, I2CByte c) return ret; } +/** + * Sets the control bus over to DDC before sending the start on the real I2C + * bus. + * + * The control bus will flip back at the stop following the start executed + * here. + */ static Bool -I830SDVODDCI2CStart(I2CBusPtr b, int timeout) +i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout) { - I830SDVOPtr sdvo = b->DriverPrivate.ptr; - I2CBusPtr i2cbus = sdvo->d.pI2CBus; + I830OutputPtr output = b->DriverPrivate.ptr; + I2CBusPtr i2cbus = output->pI2CBus; - I830SDVOSetControlBusSwitch(sdvo, SDVO_CONTROL_BUS_DDC2); + i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2); return i2cbus->I2CStart(i2cbus, timeout); } +/** Forces the device over to the real SDVO bus and sends a stop to it. */ static void -I830SDVODDCI2CStop(I2CDevPtr d) +i830_sdvo_ddc_i2c_stop(I2CDevPtr d) { - I830SDVOPtr sdvo = d->pI2CBus->DriverPrivate.ptr; - I2CBusPtr i2cbus = sdvo->d.pI2CBus, savebus; + I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr; + I2CBusPtr i2cbus = output->pI2CBus, savebus; savebus = d->pI2CBus; d->pI2CBus = i2cbus; @@ -857,11 +972,15 @@ I830SDVODDCI2CStop(I2CDevPtr d) d->pI2CBus = savebus; } -/* It's a shame that xf86i2c.c's I2CAddress() doesn't use the bus's pointers, - * so it's useless to us here. +/** + * Mirrors xf86i2c I2CAddress, using the bus's (wrapped) methods rather than + * the default methods. + * + * This ensures that our start commands always get wrapped with control bus + * switches. xf86i2c should probably be fixed to do this. */ static Bool -I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr) { if (d->pI2CBus->I2CStart(d->pI2CBus, d->StartTimeout)) { if (d->pI2CBus->I2CPutByte(d, addr & 0xFF)) { @@ -880,50 +999,54 @@ I830SDVODDCI2CAddress(I2CDevPtr d, I2CSlaveAddr addr) } static void -I830DumpSDVOCmd (I830SDVOPtr s, int opcode) +i830_sdvo_dump_cmd(I830OutputPtr output, int opcode) { - memset (s->sdvo_regs, 0, sizeof (s->sdvo_regs)); - s->sdvo_regs[SDVO_I2C_OPCODE] = opcode; - I830SDVOWriteOutputs (s, 0); - I830SDVOReadInputRegs (s); + struct i830_sdvo_priv *dev_priv = output->dev_priv; + + memset(dev_priv->sdvo_regs, 0, sizeof(dev_priv->sdvo_regs)); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = opcode; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); } static void -I830DumpOneSDVO (I830SDVOPtr s) +i830_sdvo_dump_device(I830OutputPtr output) { - ErrorF ("Dump %s\n", s->d.DevName); - I830DumpSDVOCmd (s, SDVO_CMD_GET_DEVICE_CAPS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_FIRMWARE_REV); - I830DumpSDVOCmd (s, SDVO_CMD_GET_TRAINED_INPUTS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_OUTPUTS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_IN_OUT_MAP); - I830DumpSDVOCmd (s, SDVO_CMD_GET_ATTACHED_DISPLAYS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_HOT_PLUG_SUPPORT); - I830DumpSDVOCmd (s, SDVO_CMD_GET_ACTIVE_HOT_PLUG); - I830DumpSDVOCmd (s, SDVO_CMD_GET_INTR_EVENT_SOURCE); - I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART1); - I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_TIMINGS_PART2); - I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); - I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2); - I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1); - I830DumpSDVOCmd (s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2); - I830DumpSDVOCmd (s, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE); - I830DumpSDVOCmd (s, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE); - I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_CLOCK_RATE_MULT); - I830DumpSDVOCmd (s, SDVO_CMD_GET_SUPPORTED_TV_FORMATS); - I830DumpSDVOCmd (s, SDVO_CMD_GET_TV_FORMAT); + struct i830_sdvo_priv *dev_priv = output->dev_priv; + + ErrorF("Dump %s\n", dev_priv->d.DevName); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_FIRMWARE_REV); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_IN_OUT_MAP); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTR_EVENT_SOURCE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART2); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_TV_FORMATS); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TV_FORMAT); } - + void -I830DumpSDVO (ScrnInfoPtr pScrn) +i830_sdvo_dump(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int i; for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].type == I830_OUTPUT_SDVO) - I830DumpOneSDVO (pI830->output[i].sdvo_drv); + i830_sdvo_dump_device(&pI830->output[i]); } } @@ -937,73 +1060,74 @@ I830DumpSDVO (ScrnInfoPtr pScrn) * Takes 14ms on average on my i945G. */ Bool -I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index) +i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr s = pI830->output[output_index].sdvo_drv; + struct i830_sdvo_priv *dev_priv = output->dev_priv; - s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS; - I830SDVOWriteOutputs(s, 0); - I830SDVOReadInputRegs(s); + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS; + i830_sdvo_write_outputs(output, 0); + i830_sdvo_read_input_regs(output); - if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) + if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) return FALSE; - return (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0 || - s->sdvo_regs[SDVO_I2C_RETURN_1] != 0); + return (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0 || + dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] != 0); } void i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) { I830Ptr pI830 = I830PTR(pScrn); - I830SDVOPtr sdvo; + I830OutputPtr output = &pI830->output[pI830->num_outputs]; + struct i830_sdvo_priv *dev_priv; int i; unsigned char ch[0x40]; I2CBusPtr i2cbus = NULL, ddcbus; - pI830->output[pI830->num_outputs].type = I830_OUTPUT_SDVO; - pI830->output[pI830->num_outputs].dpms = i830_sdvo_dpms; - pI830->output[pI830->num_outputs].save = i830_sdvo_save; - pI830->output[pI830->num_outputs].restore = i830_sdvo_restore; - pI830->output[pI830->num_outputs].mode_valid = i830_sdvo_mode_valid; - pI830->output[pI830->num_outputs].pre_set_mode = i830_sdvo_pre_set_mode; - pI830->output[pI830->num_outputs].post_set_mode = i830_sdvo_post_set_mode; + output->type = I830_OUTPUT_SDVO; + output->dpms = i830_sdvo_dpms; + output->save = i830_sdvo_save; + output->restore = i830_sdvo_restore; + output->mode_valid = i830_sdvo_mode_valid; + output->pre_set_mode = i830_sdvo_pre_set_mode; + output->post_set_mode = i830_sdvo_post_set_mode; + + /* While it's the same bus, we just initialize a new copy to avoid trouble + * with tracking refcounting ourselves, since the XFree86 DDX bits don't. + */ + if (output_device == SDVOB) + I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOB"); + else + I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC"); - /* Find an existing SDVO I2CBus from another output, or allocate it. */ - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_SDVO) - i2cbus = pI830->output[i].pI2CBus; - } - if (i2cbus == NULL) - I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E"); if (i2cbus == NULL) return; /* Allocate the SDVO output private data */ - sdvo = xcalloc(1, sizeof(I830SDVORec)); - if (sdvo == NULL) { + dev_priv = xcalloc(1, sizeof(struct i830_sdvo_priv)); + if (dev_priv == NULL) { xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); return; } if (output_device == SDVOB) { - sdvo->d.DevName = "SDVO Controller B"; - sdvo->d.SlaveAddr = 0x70; + dev_priv->d.DevName = "SDVO Controller B"; + dev_priv->d.SlaveAddr = 0x70; } else { - sdvo->d.DevName = "SDVO Controller C"; - sdvo->d.SlaveAddr = 0x72; + dev_priv->d.DevName = "SDVO Controller C"; + dev_priv->d.SlaveAddr = 0x72; } - sdvo->d.pI2CBus = i2cbus; - sdvo->d.DriverPrivate.ptr = sdvo; - sdvo->output_device = output_device; + dev_priv->d.pI2CBus = i2cbus; + dev_priv->d.DriverPrivate.ptr = output; + dev_priv->output_device = output_device; - if (!xf86I2CDevInit(&sdvo->d)) { + if (!xf86I2CDevInit(&dev_priv->d)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize SDVO I2C device %s\n", output_device == SDVOB ? "SDVOB" : "SDVOC"); xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(sdvo); + xfree(dev_priv); return; } @@ -1014,9 +1138,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) */ ddcbus = xf86CreateI2CBusRec(); if (ddcbus == NULL) { - xf86DestroyI2CDevRec(&sdvo->d, FALSE); + xf86DestroyI2CDevRec(&dev_priv->d, FALSE); xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(sdvo); + xfree(dev_priv); return; } if (output_device == SDVOB) @@ -1024,47 +1148,46 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) else ddcbus->BusName = "SDVOC DDC Bus"; ddcbus->scrnIndex = i2cbus->scrnIndex; - ddcbus->I2CGetByte = I830SDVODDCI2CGetByte; - ddcbus->I2CPutByte = I830SDVODDCI2CPutByte; - ddcbus->I2CStart = I830SDVODDCI2CStart; - ddcbus->I2CStop = I830SDVODDCI2CStop; - ddcbus->I2CAddress = I830SDVODDCI2CAddress; - ddcbus->DriverPrivate.ptr = sdvo; + ddcbus->I2CGetByte = i830_sdvo_ddc_i2c_get_byte; + ddcbus->I2CPutByte = i830_sdvo_ddc_i2c_put_byte; + ddcbus->I2CStart = i830_sdvo_ddc_i2c_start; + ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop; + ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address; + ddcbus->DriverPrivate.ptr = &pI830->output[pI830->num_outputs]; if (!xf86I2CBusInit(ddcbus)) { - xf86DestroyI2CDevRec(&sdvo->d, FALSE); + xf86DestroyI2CDevRec(&dev_priv->d, FALSE); xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(sdvo); + xfree(dev_priv); return; } - pI830->output[pI830->num_outputs].pI2CBus = i2cbus; - pI830->output[pI830->num_outputs].pDDCBus = ddcbus; - pI830->output[pI830->num_outputs].sdvo_drv = sdvo; + output->pI2CBus = i2cbus; + output->pDDCBus = ddcbus; + output->dev_priv = dev_priv; /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { - if (!sReadByte(sdvo, i, &ch[i])) { - xf86DestroyI2CBusRec(pI830->output[pI830->num_outputs].pDDCBus, - FALSE, FALSE); - xf86DestroyI2CDevRec(&sdvo->d, FALSE); + if (!i830_sdvo_read_byte(output, i, &ch[i])) { + xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE); + xf86DestroyI2CDevRec(&dev_priv->d, FALSE); xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(sdvo); + xfree(dev_priv); return; } } - I830SDVOGetCapabilities(sdvo, &sdvo->caps); + i830_sdvo_get_capabilities(output, &dev_priv->caps); - I830SDVOGetInputPixelClockRange(sdvo, &sdvo->pixel_clock_min, - &sdvo->pixel_clock_max); + i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min, + &dev_priv->pixel_clock_max); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SDVO device VID/DID: %02X:%02X.%02X, %02X," "output 1: %c, output 2: %c\n", - sdvo->caps.vendor_id, sdvo->caps.device_id, - sdvo->caps.device_rev_id, sdvo->caps.caps, - sdvo->caps.output_0_supported ? 'Y' : 'N', - sdvo->caps.output_1_supported ? 'Y' : 'N'); + dev_priv->caps.vendor_id, dev_priv->caps.device_id, + dev_priv->caps.device_rev_id, dev_priv->caps.caps, + dev_priv->caps.output_0_supported ? 'Y' : 'N', + dev_priv->caps.output_1_supported ? 'Y' : 'N'); pI830->num_outputs++; } diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 44bbfe47..db7eb97f 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -62,7 +62,7 @@ int i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode); Bool -I830DetectSDVODisplays(ScrnInfoPtr pScrn, int output_index); +i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output); void -I830DumpSDVO(ScrnInfoPtr pScrn); +i830_sdvo_dump(ScrnInfoPtr pScrn); From ddb986e54f5320359abac06f512f2d3f446872db Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Oct 2006 17:47:58 -0700 Subject: [PATCH 186/257] Nuke trailing whitespace in SDVO code not already cleaned up. --- src/i830_sdvo.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index e028a9bb..523eed27 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1,7 +1,7 @@ /************************************************************************** Copyright 2006 Dave Airlie - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation @@ -463,7 +463,7 @@ i830_sdvo_set_timings_part1(I830OutputPtr output, char cmd, CARD16 clock, i830_sdvo_write_outputs(output, 8); i830_sdvo_read_input_regs(output); - + return TRUE; } @@ -492,9 +492,9 @@ i830_sdvo_set_timings_part2(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_priv *dev_priv = output->dev_priv; memset(dev_priv->sdvo_regs, 0, 9); - + dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - + /* set clock regs */ dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff; dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff; @@ -505,7 +505,7 @@ i830_sdvo_set_timings_part2(I830OutputPtr output, CARD8 cmd, i830_sdvo_write_outputs(output, 8); i830_sdvo_read_input_regs(output); - + return TRUE; } @@ -691,7 +691,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, i830_sdvo_set_target_input(output, FALSE, FALSE); i830_sdvo_get_active_outputs(output, &out1, &out2); - + i830_sdvo_set_active_outputs(output, FALSE, FALSE); i830_sdvo_set_target_output(output, TRUE, FALSE); @@ -702,13 +702,13 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, out_timings[5]); i830_sdvo_set_target_input(output, FALSE, FALSE); - + i830_sdvo_create_preferred_input_timing(output, clock, width, height); i830_sdvo_get_preferred_input_timing_part1(output); i830_sdvo_get_preferred_input_timing_part2(output); - + i830_sdvo_set_target_input(output, FALSE, FALSE); - + i830_sdvo_set_input_timings_part1(output, clock, curr_table[0], curr_table[1], curr_table[2]); @@ -821,7 +821,7 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2, SDVO_CMD_GET_INPUT_TIMINGS_PART1); } - + if (dev_priv->caps.output_0_supported) { i830_sdvo_set_target_output(output, TRUE, FALSE); i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1, From 2631014e9d5b2e64908ea413729eb5fd819b17fc Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 25 Oct 2006 12:21:44 -0700 Subject: [PATCH 187/257] Clean up the SDVO code. The main change is to send SDVO commands using data passed into the send command function, and receive responses into memory passed into the read response function, rather than stuff things in/out through dev_priv->sdvo_regs. This lets us use structures to represent some arguments, which results in a nice cleanup (and 100% fewer arguments named magicN as a side effect). Also, the mode set path is changed to not do any preferred input timing work. We weren't doing anything legitimate with the results, since we didn't modify the CRTC timing appropriately, so now we just stuff the CRTC timing into both and hope for the best. This should probably be revisited later. --- src/i830_sdvo.c | 692 +++++++++++++++++-------------------------- src/i830_sdvo.h | 30 -- src/i830_sdvo_regs.h | 70 ++++- 3 files changed, 322 insertions(+), 470 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 523eed27..ac5ae48e 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -54,8 +54,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. struct i830_sdvo_priv { /** SDVO device on SDVO I2C bus. */ I2CDevRec d; - /** Temporary storage for reg read/writes */ - unsigned char sdvo_regs[20]; /** Register for the SDVO device: SDVOB or SDVOC */ int output_device; /** @@ -69,14 +67,12 @@ struct i830_sdvo_priv { /** @{ */ int save_sdvo_mult; Bool save_sdvo_active_1, save_sdvo_active_2; - i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; - i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; + struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; + struct i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; CARD32 save_SDVOX; /** @} */ }; -CARD16 curr_table[6]; - /** Read a single byte from the given address on the SDVO device. */ static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr, unsigned char *ch) @@ -153,33 +149,36 @@ const struct _sdvo_cmd_name { SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), }; -/* following on from tracing the intel BIOS i2c routines */ +/** + * Writes out the data given in args (up to 8 bytes), followed by the opcode. + */ static void -i830_sdvo_write_outputs(I830OutputPtr output, int num_out) +i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; int i; - ErrorF("SDVO: W: %02X ", dev_priv->sdvo_regs[SDVO_I2C_OPCODE]); - for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) - ErrorF("%02X ", dev_priv->sdvo_regs[i]); - for (; i > SDVO_I2C_ARG_7; i--) - ErrorF(" "); + /* Write the SDVO command logging */ + xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "SDVO: W: %02X ", cmd); + for (i = 0; i < args_len; i++) + LogWrite(1, "%02X ", ((CARD8 *)args)[i]); + for (; i < 8; i++) + LogWrite(1, " "); for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { - if (dev_priv->sdvo_regs[SDVO_I2C_OPCODE] == sdvo_cmd_names[i].cmd) { - ErrorF("(%s)", sdvo_cmd_names[i].name); + if (cmd == sdvo_cmd_names[i].cmd) { + LogWrite(1, "(%s)", sdvo_cmd_names[i].name); break; } } - ErrorF("\n"); + if (i == sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0])) + LogWrite(1, "(%02X)", cmd); + LogWrite(1, "\n"); - /* blast the output regs */ - for (i = SDVO_I2C_ARG_0; i > SDVO_I2C_ARG_0 - num_out; i--) { - i830_sdvo_write_byte(output, i, dev_priv->sdvo_regs[i]); + /* send the output regs */ + for (i = 0; i < args_len; i++) { + i830_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((CARD8 *)args)[i]); } /* blast the command reg */ - i830_sdvo_write_byte(output, SDVO_I2C_OPCODE, - dev_priv->sdvo_regs[SDVO_I2C_OPCODE]); + i830_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd); } static const char *cmd_status_names[] = { @@ -192,45 +191,40 @@ static const char *cmd_status_names[] = { "Scaling not supported" }; -static void -i830_sdvo_read_input_regs(I830OutputPtr output) +/** + * Reads back response_len bytes from the SDVO device, and returns the status. + */ +static CARD8 +i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; int i; + CARD8 status; - /* follow BIOS ordering */ - i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, - &dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]); - - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_3, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_2, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_1, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_7, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_6, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_5, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]); - i830_sdvo_read_byte(output, SDVO_I2C_RETURN_4, - &dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]); - - ErrorF("SDVO: R: "); - for (i = SDVO_I2C_RETURN_0; i <= SDVO_I2C_RETURN_7; i++) - ErrorF("%02X ", dev_priv->sdvo_regs[i]); - if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] <= - SDVO_CMD_STATUS_SCALING_NOT_SUPP) - { - ErrorF("(%s)", - cmd_status_names[dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]]); - } else { - ErrorF("(??? %d)", dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS]); + /* Read the command response */ + for (i = 0; i < response_len; i++) { + i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i, + &((CARD8 *)response)[i]); } - ErrorF("\n"); + + /* Read the return status */ + i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); + + /* Write the SDVO command logging */ + xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, + "SDVO: R: "); + for (i = 0; i < response_len; i++) + LogWrite(1, "%02X ", ((CARD8 *)response)[i]); + for (; i < 8; i++) + LogWrite(1, " "); + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) + { + LogWrite(1, "(%s)", cmd_status_names[status]); + } else { + LogWrite(1, "(??? %d)", status); + } + LogWrite(1, "\n"); + + return status; } int @@ -248,49 +242,47 @@ i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode) * PROM. It resets from the DDC bus back to internal registers at the next I2C * STOP. PROM access is terminated by accessing an internal register. */ -static Bool +static void i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; - - memset(dev_priv->sdvo_regs, 0, 9); - - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target; - - i830_sdvo_write_outputs(output, 1); - return TRUE; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); } static Bool i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 targets[2]; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + targets[0] = target_1; + targets[1] = target_2; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, 2); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2; + status = i830_sdvo_read_response(output, NULL, 0); - i830_sdvo_write_outputs(output, 2); - - i830_sdvo_read_input_regs(output); - - return TRUE; + return (status == SDVO_CMD_STATUS_SUCCESS); } +/** + * Return whether each input is trained. + * + * This function is making an assumption about the layout of the response, + * which should be checked against the docs. + */ static Bool -i830_sdvo_get_trained_inputs(I830OutputPtr output) +i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 response[2]; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS; + i830_sdvo_read_response(output, response, 2); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + *input_1 = response[0]; + *input_2 = response[1]; return TRUE; } @@ -298,56 +290,50 @@ i830_sdvo_get_trained_inputs(I830OutputPtr output) static Bool i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 response[2]; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS; + status = i830_sdvo_read_response(output, &response, 2); - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + *on_1 = response[0]; + *on_2 = response[1]; - *on_1 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; - *on_2 = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; - - return TRUE; + return (status == SDVO_CMD_STATUS_SUCCESS); } static Bool i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 outputs[2]; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + outputs[0] = on_1; + outputs[1] = on_2; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, 2); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = on_1; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = on_2; + status = i830_sdvo_read_response(output, NULL, 0); - i830_sdvo_write_outputs(output, 2); - i830_sdvo_read_input_regs(output); - - return TRUE; + return (status == SDVO_CMD_STATUS_SUCCESS); } static Bool i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, CARD16 *clock_max) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + struct i830_sdvo_pixel_clock_range clocks; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, 0); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = - SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE; + status = i830_sdvo_read_response(output, &clocks, sizeof(clocks)); - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - *clock_min = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - *clock_max = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); + *clock_min = clocks.min; + *clock_max = clocks.max; return TRUE; } @@ -355,282 +341,164 @@ i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, static Bool i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 targets[2]; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + targets[0] = target_1; + targets[1] = target_2; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &targets, 2); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = target_1; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = target_2; + status = i830_sdvo_read_response(output, NULL, 0); - i830_sdvo_write_outputs(output, 2); - i830_sdvo_read_input_regs(output); - - return TRUE; + return (status == SDVO_CMD_STATUS_SUCCESS); } -/* Fetches either input or output timings to *dtd, depending on cmd. */ +/** Fetches either input or output timings to *dtd, depending on cmd. */ static Bool -i830_sdvo_get_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd) +i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, cmd, NULL, 0); - dtd->clock = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - dtd->h_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; - dtd->h_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; - dtd->h_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; - dtd->v_active = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; - dtd->v_blank = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; - dtd->v_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; + status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - memset(dev_priv->sdvo_regs, 0, 9); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, cmd + 1, NULL, 0); - dtd->h_sync_off = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; - dtd->h_sync_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; - dtd->v_sync_off_width = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; - dtd->sync_off_width_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; - dtd->dtd_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; - dtd->sdvo_flags = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; - dtd->v_sync_off_high = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; - dtd->reserved = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; - - return TRUE; -} - -/* Sets either input or output timings to *dtd, depending on cmd. */ -static Bool -i830_sdvo_set_timings(I830OutputPtr output, i830_sdvo_dtd *dtd, CARD8 cmd) -{ - struct i830_sdvo_priv *dev_priv = output->dev_priv; - - memset(dev_priv->sdvo_regs, 0, 9); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8; - dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active; - dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank; - dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high; - dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active; - dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank; - dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high; - i830_sdvo_write_outputs(output, 8); - i830_sdvo_read_input_regs(output); - - memset(dev_priv->sdvo_regs, 0, 9); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1; - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width; - dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width; - dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high; - dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags; - dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags; - dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high; - dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved; - i830_sdvo_write_outputs(output, 7); - i830_sdvo_read_input_regs(output); + status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; return TRUE; } static Bool -i830_sdvo_set_timings_part1(I830OutputPtr output, char cmd, CARD16 clock, - CARD16 magic1, CARD16 magic2, CARD16 magic3) +i830_sdvo_get_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd); +} - memset(dev_priv->sdvo_regs, 0, 9); +static Bool +i830_sdvo_get_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) +{ + return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd); +} - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; +/** Sets either input or output timings from *dtd, depending on cmd. */ +static Bool +i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) +{ + CARD8 status; - /* set clock regs */ - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff; + i830_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1)); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - i830_sdvo_write_outputs(output, 8); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2)); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; return TRUE; } static Bool -i830_sdvo_set_input_timings_part1(I830OutputPtr output, CARD16 clock, - CARD16 magic1, CARD16 magic2, CARD16 magic3) +i830_sdvo_set_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) { - return i830_sdvo_set_timings_part1(output, - SDVO_CMD_SET_INPUT_TIMINGS_PART1, - clock, magic1, magic2, magic3); + return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); } static Bool -i830_sdvo_set_output_timings_part1(I830OutputPtr output, CARD16 clock, - CARD16 magic1, CARD16 magic2, CARD16 magic3) +i830_sdvo_set_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) { - return i830_sdvo_set_timings_part1(output, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, - clock, magic1, magic2, magic3); -} - -static Bool -i830_sdvo_set_timings_part2(I830OutputPtr output, CARD8 cmd, - CARD16 magic4, CARD16 magic5, CARD16 magic6) -{ - struct i830_sdvo_priv *dev_priv = output->dev_priv; - - memset(dev_priv->sdvo_regs, 0, 9); - - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = cmd; - - /* set clock regs */ - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff; - - i830_sdvo_write_outputs(output, 8); - i830_sdvo_read_input_regs(output); - - return TRUE; -} - -static Bool -i830_sdvo_set_input_timings_part2(I830OutputPtr output, - CARD16 magic4, CARD16 magic5, CARD16 magic6) -{ - return i830_sdvo_set_timings_part2(output, - SDVO_CMD_SET_INPUT_TIMINGS_PART2, - magic4, magic5, magic6); -} - -static Bool -i830_sdvo_set_output_timings_part2(I830OutputPtr output, - CARD16 magic4, CARD16 magic5, CARD16 magic6) -{ - return i830_sdvo_set_timings_part2(output, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, - magic4, magic5, magic6); + return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); } +#if 0 static Bool i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock, CARD16 width, CARD16 height) { struct i830_sdvo_priv *dev_priv = output->dev_priv; + struct i830_sdvo_preferred_input_timing_args args; - memset(dev_priv->sdvo_regs, 0, 9); - - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = - SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING; - - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_4] = height & 0xff; - dev_priv->sdvo_regs[SDVO_I2C_ARG_5] = (height >> 8) & 0xff; - - i830_sdvo_write_outputs(output, 7); - i830_sdvo_read_input_regs(output); + args.clock = clock; + args.width = width; + args.height = height; + i830_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, + &args, sizeof(args)); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; return TRUE; } static Bool -i830_sdvo_get_preferred_input_timing_part1(I830OutputPtr output) +i830_sdvo_get_preferred_input_timing(I830OutputPtr output, + struct i830_sdvo_dtd *dtd) { struct i830_sdvo_priv *dev_priv = output->dev_priv; - memset(dev_priv->sdvo_regs, 0, 9); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, + NULL, 0); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = - SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1; + status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, + NULL, 0); - curr_table[0] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_7] << 8); - curr_table[1] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_5] << 8); - curr_table[2] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); - - return TRUE; -} - -static Bool -i830_sdvo_get_preferred_input_timing_part2(I830OutputPtr output) -{ - struct i830_sdvo_priv *dev_priv = output->dev_priv; - - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = - SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2; - - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); - - curr_table[3] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] << 8); - curr_table[4] = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2] | - (dev_priv->sdvo_regs[SDVO_I2C_RETURN_3] << 8); - curr_table[5] = 0x1e; + status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; return TRUE; } +#endif +/** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */ static int i830_sdvo_get_clock_rate_mult(I830OutputPtr output) { struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 response; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0); + status = i830_sdvo_read_response(output, &response, 1); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT; - - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); - - if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) { + if (status != SDVO_CMD_STATUS_SUCCESS) { xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR, "Couldn't get SDVO clock rate multiplier\n"); return SDVO_CLOCK_RATE_MULT_1X; } else { xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO, - "Current clock rate multiplier: %d\n", - dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]); + "Current clock rate multiplier: %d\n", response); } - return dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; + return response; } +/** + * Sets the current clock multiplier. + * + * This has to match with the settings in the DPLL/SDVO reg when the output + * is actually turned on. + */ static Bool i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); - - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT; - - dev_priv->sdvo_regs[SDVO_I2C_ARG_0] = val; - i830_sdvo_write_outputs(output, 1); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; return TRUE; } @@ -640,15 +508,11 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); - CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay; + CARD16 width = mode->CrtcHDisplay; CARD16 height = mode->CrtcVDisplay; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; - CARD16 sync_flags; - CARD8 c16a[8]; - CARD8 c17a[8]; - CARD16 out_timings[6]; - Bool out1, out2; + struct i830_sdvo_dtd output_dtd; /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -660,62 +524,57 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart; v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart; - sync_flags = 0x18; + output_dtd.part1.clock = mode->Clock / 10; + output_dtd.part1.h_active = width & 0xff; + output_dtd.part1.h_blank = h_blank_len & 0xff; + output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | + ((h_blank_len >> 8) & 0xf); + output_dtd.part1.v_active = height & 0xff; + output_dtd.part1.v_blank = v_blank_len & 0xff; + output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | + ((v_blank_len >> 8) & 0xf); + + output_dtd.part2.h_sync_off = h_sync_offset; + output_dtd.part2.h_sync_width = h_sync_len & 0xff; + output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | + (v_sync_len & 0xf); + output_dtd.part2.sync_off_width_high = 0; + output_dtd.part2.dtd_flags = 0x18; + output_dtd.part2.sdvo_flags = 0; + output_dtd.part2.v_sync_off_width = 0; + output_dtd.part2.reserved = 0; if (mode->Flags & V_PHSYNC) - sync_flags |= 0x2; + output_dtd.part2.dtd_flags |= 0x2; if (mode->Flags & V_PVSYNC) - sync_flags |= 0x4; - /* high bits of 0 */ - c16a[7] = clock & 0xff; - c16a[6] = (clock >> 8) & 0xff; - c16a[5] = (width & 0xff); - c16a[4] = (h_blank_len & 0xff); - c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf); - c16a[2] = (height & 0xff); - c16a[1] = (v_blank_len & 0xff); - c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf); - - c17a[7] = h_sync_offset; - c17a[6] = h_sync_len & 0xff; - c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf); - c17a[4] = 0; - c17a[3] = sync_flags; - c17a[2] = 0; - out_timings[0] = c16a[1] | ((short)c16a[0] << 8); - out_timings[1] = c16a[3] | ((short)c16a[2] << 8); - out_timings[2] = c16a[5] | ((short)c16a[4] << 8); - out_timings[3] = c17a[7] | ((short)c17a[6] << 8); - out_timings[4] = c17a[5] | ((short)c17a[4] << 8); - out_timings[5] = c17a[3] | ((short)c17a[2] << 8); - - i830_sdvo_set_target_input(output, FALSE, FALSE); - - i830_sdvo_get_active_outputs(output, &out1, &out2); + output_dtd.part2.dtd_flags |= 0x4; + /* Turn off the screens before adjusting timings */ i830_sdvo_set_active_outputs(output, FALSE, FALSE); + /* Set the output timing to the screen */ i830_sdvo_set_target_output(output, TRUE, FALSE); - i830_sdvo_set_output_timings_part1(output, clock, - out_timings[0], out_timings[1], - out_timings[2]); - i830_sdvo_set_output_timings_part2(output, out_timings[3], out_timings[4], - out_timings[5]); + i830_sdvo_set_output_timing(output, &output_dtd); - i830_sdvo_set_target_input(output, FALSE, FALSE); + /* Set the input timing to the screen */ + i830_sdvo_set_target_input(output, TRUE, FALSE); - i830_sdvo_create_preferred_input_timing(output, clock, width, height); - i830_sdvo_get_preferred_input_timing_part1(output); - i830_sdvo_get_preferred_input_timing_part2(output); + /* We would like to use i830_sdvo_create_preferred_input_timing() to + * provide the device with a timing it can support, if it supports that + * feature. However, presumably we would need to adjust the CRTC to output + * the preferred timing, and we don't support that currently. + */ +#if 0 + success = i830_sdvo_create_preferred_input_timing(output, clock, + width, height); + if (success) { + struct i830_sdvo_dtd *input_dtd; - i830_sdvo_set_target_input(output, FALSE, FALSE); - - i830_sdvo_set_input_timings_part1(output, clock, - curr_table[0], curr_table[1], - curr_table[2]); - i830_sdvo_set_input_timings_part2(output, curr_table[3], curr_table[4], - out_timings[5]); - - i830_sdvo_set_target_input(output, FALSE, FALSE); + i830_sdvo_get_preferred_input_timing(output, &input_dtd); + i830_sdvo_set_input_timing(output, &input_dtd); + } +#else + i830_sdvo_set_input_timing(output, &output_dtd); +#endif switch (i830_sdvo_get_pixel_multiplier(mode)) { case 1: @@ -738,26 +597,22 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; - Bool ret = TRUE; - Bool out1, out2; + Bool out1, out2, input1, input2; CARD32 dpll, sdvob, sdvoc; int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; int sdvo_pixel_multiply; + CARD8 status; /* the BIOS writes out 6 commands post mode set */ /* two 03s, 04 05, 10, 1d */ /* these contain the height and mode clock / 10 by the looks of it */ - i830_sdvo_get_trained_inputs(output); + i830_sdvo_get_trained_inputs(output, &input1, &input2); - /* THIS IS A DIRTY HACK - sometimes for some reason on startup - * the BIOS doesn't find my DVI monitor - - * without this hack the driver doesn't work.. this causes the modesetting - * to be re-run - */ - if (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) { - ret = FALSE; + /* Warn if the device reported failure to sync. */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First SDVO output reported failure to sync\n"); } i830_sdvo_get_active_outputs(output, &out1, &out2); @@ -810,28 +665,24 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1, &dev_priv->save_sdvo_active_2); - if (dev_priv->caps.caps & 0x1) { + if (dev_priv->caps.sdvo_inputs_mask & 0x1) { i830_sdvo_set_target_input(output, FALSE, FALSE); - i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_1, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); + i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1); } - if (dev_priv->caps.caps & 0x2) { + if (dev_priv->caps.sdvo_inputs_mask & 0x2) { i830_sdvo_set_target_input(output, FALSE, TRUE); - i830_sdvo_get_timings(output, &dev_priv->save_input_dtd_2, - SDVO_CMD_GET_INPUT_TIMINGS_PART1); + i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2); } if (dev_priv->caps.output_0_supported) { i830_sdvo_set_target_output(output, TRUE, FALSE); - i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_1, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_1); } if (dev_priv->caps.output_1_supported) { i830_sdvo_set_target_output(output, FALSE, TRUE); - i830_sdvo_get_timings(output, &dev_priv->save_output_dtd_2, - SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); + i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_2); } dev_priv->save_SDVOX = INREG(dev_priv->output_device); @@ -843,28 +694,24 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); struct i830_sdvo_priv *dev_priv = output->dev_priv; - if (dev_priv->caps.caps & 0x1) { + if (dev_priv->caps.sdvo_inputs_mask & 0x1) { i830_sdvo_set_target_input(output, FALSE, FALSE); - i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_1, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); + i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1); } - if (dev_priv->caps.caps & 0x2) { + if (dev_priv->caps.sdvo_inputs_mask & 0x2) { i830_sdvo_set_target_input(output, FALSE, TRUE); - i830_sdvo_set_timings(output, &dev_priv->save_input_dtd_2, - SDVO_CMD_SET_INPUT_TIMINGS_PART1); + i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2); } if (dev_priv->caps.output_0_supported) { i830_sdvo_set_target_output(output, TRUE, FALSE); - i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_1, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_1); } if (dev_priv->caps.output_1_supported) { i830_sdvo_set_target_output(output, FALSE, TRUE); - i830_sdvo_set_timings(output, &dev_priv->save_output_dtd_2, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1); + i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_2); } i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult); @@ -890,24 +737,17 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, return MODE_OK; } -static void +static Bool i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 status; - memset(dev_priv->sdvo_regs, 0, 9); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_DEVICE_CAPS; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0); + status = i830_sdvo_read_response(output, caps, sizeof(*caps)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; - caps->vendor_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_0]; - caps->device_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_1]; - caps->device_rev_id = dev_priv->sdvo_regs[SDVO_I2C_RETURN_2]; - caps->sdvo_version_major = dev_priv->sdvo_regs[SDVO_I2C_RETURN_3]; - caps->sdvo_version_minor = dev_priv->sdvo_regs[SDVO_I2C_RETURN_4]; - caps->caps = dev_priv->sdvo_regs[SDVO_I2C_RETURN_5]; - caps->output_0_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_6]; - caps->output_1_supported = dev_priv->sdvo_regs[SDVO_I2C_RETURN_7]; + return TRUE; } /** Forces the device over to the real I2C bus and uses its GetByte */ @@ -1001,12 +841,10 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr) static void i830_sdvo_dump_cmd(I830OutputPtr output, int opcode) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 response[8]; - memset(dev_priv->sdvo_regs, 0, sizeof(dev_priv->sdvo_regs)); - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = opcode; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, opcode, NULL, 0); + i830_sdvo_read_response(output, response, 8); } static void @@ -1062,17 +900,16 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) Bool i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + CARD8 response[2]; + CARD8 status; - dev_priv->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ATTACHED_DISPLAYS; - i830_sdvo_write_outputs(output, 0); - i830_sdvo_read_input_regs(output); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); + status = i830_sdvo_read_response(output, &response, 2); - if (dev_priv->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) + if (status != SDVO_CMD_STATUS_SUCCESS) return FALSE; - return (dev_priv->sdvo_regs[SDVO_I2C_RETURN_0] != 0 || - dev_priv->sdvo_regs[SDVO_I2C_RETURN_1] != 0); + return (response[0] != 0 || response[1] != 0); } void @@ -1182,10 +1019,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) &dev_priv->pixel_clock_max); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "SDVO device VID/DID: %02X:%02X.%02X, %02X," + "SDVO device VID/DID: %02X:%02X.%02X, " + "input 1: %c, input 2: %c, " "output 1: %c, output 2: %c\n", dev_priv->caps.vendor_id, dev_priv->caps.device_id, - dev_priv->caps.device_rev_id, dev_priv->caps.caps, + dev_priv->caps.device_rev_id, + (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', + (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', dev_priv->caps.output_0_supported ? 'Y' : 'N', dev_priv->caps.output_1_supported ? 'Y' : 'N'); diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index db7eb97f..b1d86b41 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -25,36 +25,6 @@ * */ -typedef struct _i830_sdvo_caps { - CARD8 vendor_id; - CARD8 device_id; - CARD8 device_rev_id; - CARD8 sdvo_version_major; - CARD8 sdvo_version_minor; - CARD8 caps; - CARD8 output_0_supported; - CARD8 output_1_supported; -} __attribute__((packed)) i830_sdvo_caps; - -typedef struct _i830_sdvo_dtd { - CARD16 clock; - CARD8 h_active; - CARD8 h_blank; - CARD8 h_high; - CARD8 v_active; - CARD8 v_blank; - CARD8 v_high; - - CARD8 h_sync_off; - CARD8 h_sync_width; - CARD8 v_sync_off_width; - CARD8 sync_off_width_high; - CARD8 dtd_flags; - CARD8 sdvo_flags; - CARD8 v_sync_off_high; - CARD8 reserved; -} __attribute__((packed)) i830_sdvo_dtd; - void i830_sdvo_init(ScrnInfoPtr pScrn, int output_device); diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index a35d5a4e..be3294b4 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -25,6 +25,57 @@ * */ +typedef struct _i830_sdvo_caps { + CARD8 vendor_id; + CARD8 device_id; + CARD8 device_rev_id; + CARD8 sdvo_version_major; + CARD8 sdvo_version_minor; + unsigned int sdvo_inputs_mask:2; + unsigned int smooth_scaling:1; + unsigned int sharp_scaling:1; + unsigned int up_scaling:1; + unsigned int down_scaling:1; + unsigned int stall_support:1; + unsigned int pad:1; + CARD8 output_0_supported; + CARD8 output_1_supported; +} __attribute__((packed)) i830_sdvo_caps; + +struct i830_sdvo_dtd { + struct { + CARD16 clock; + CARD8 h_active; + CARD8 h_blank; + CARD8 h_high; + CARD8 v_active; + CARD8 v_blank; + CARD8 v_high; + } part1; + + struct { + CARD8 h_sync_off; + CARD8 h_sync_width; + CARD8 v_sync_off_width; + CARD8 sync_off_width_high; + CARD8 dtd_flags; + CARD8 sdvo_flags; + CARD8 v_sync_off_high; + CARD8 reserved; + } part2; +} __attribute__((packed)); + +struct i830_sdvo_pixel_clock_range { + CARD16 min; + CARD16 max; +} __attribute__((packed)); + +struct i830_sdvo_preferred_input_timing_args { + CARD16 clock; + CARD16 width; + CARD16 height; +} __attribute__((packed)); + /* I2C registers for SDVO */ #define SDVO_I2C_ARG_0 0x07 #define SDVO_I2C_ARG_1 0x06 @@ -56,22 +107,11 @@ #define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 /* SDVO commands, argument/result registers */ + #define SDVO_CMD_RESET 0x01 + +/** Returns a struct i830_sdvo_caps */ #define SDVO_CMD_GET_DEVICE_CAPS 0x02 -# define SDVO_DEVICE_CAPS_VENDOR_ID SDVO_I2C_RETURN_0 -# define SDVO_DEVICE_CAPS_DEVICE_ID SDVO_I2C_RETURN_1 -# define SDVO_DEVICE_CAPS_DEVICE_REV_ID SDVO_I2C_RETURN_2 -# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR SDVO_I2C_RETURN_3 -# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR SDVO_I2C_RETURN_4 -# define SDVO_DEVICE_CAPS_CAPS SDVO_I2C_RETURN_5 -# define SDVO_DEVICE_CAPS_INPUTS_MASK (3 << 0) -# define SDVO_DEVICE_CAPS_SMOOTH_SCALING (1 << 2) -# define SDVO_DEVICE_CAPS_SHARP_SCALING (1 << 3) -# define SDVO_DEVICE_CAPS_UP_SCALING (1 << 4) -# define SDVO_DEVICE_CAPS_DOWN_SCALING (1 << 5) -# define SDVO_DEVICE_CAPS_STALL_SUPPORT (1 << 6) -# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED SDVO_I2C_RETURN_6 -# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED SDVO_I2C_RETURN_7 #define SDVO_CMD_GET_FIRMWARE_REV 0x86 # define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 @@ -148,7 +188,9 @@ #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c +/** Returns a struct i830_sdvo_pixel_clock_range */ #define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d +/** Returns a struct i830_sdvo_pixel_clock_range */ #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f From 88c12f577f80fa132ec45cdf456d8060f2ece4fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Oct 2006 18:57:57 -0700 Subject: [PATCH 188/257] Move LVDS initialization and blacklisting damage to the LVDS support file. --- src/i830_driver.c | 47 ++++++----------------------------------------- src/i830_lvds.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 4ee5fc27..9f986ec8 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1092,7 +1092,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) int i, n; char *s; pointer pVBEModule = NULL; - Bool enable, has_lvds, is_apple_945gm = FALSE; + Bool enable; const char *chipname; unsigned int ver; char v[5]; @@ -1235,7 +1235,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pVbe = pI8301->pVbe; } - has_lvds = TRUE; switch (pI830->PciInfo->chipType) { case PCI_CHIP_I830_M: chipname = "830M"; @@ -1269,11 +1268,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) break; case PCI_CHIP_I865_G: chipname = "865G"; - has_lvds = FALSE; break; case PCI_CHIP_I915_G: chipname = "915G"; - has_lvds = FALSE; break; case PCI_CHIP_E7221_G: chipname = "E7221 (i915)"; @@ -1283,7 +1280,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) break; case PCI_CHIP_I945_G: chipname = "945G"; - has_lvds = FALSE; break; case PCI_CHIP_I945_GM: chipname = "945GM"; @@ -1540,23 +1536,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType2 = PIPE_NONE; pI830->specifiedMonitor = FALSE; - /* Always check for LVDS info once at startup. We hook in the BIOS data - * dumping here (this should be cleaner) and we get to rely on having the - * LVDS info later on. - */ - if (!i830GetLVDSInfoFromBIOS(pScrn)) - has_lvds = FALSE; - - /* Blacklist machines with known broken BIOSes */ - if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) { - if (pI830->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */ - has_lvds = FALSE; - - if ((pI830->PciInfo->subsysVendor == 0x8086) && - (pI830->PciInfo->subsysCard == 0x7270)) /* mini, macbook pro... */ - is_apple_945gm = TRUE; - } - if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { char *Mon1; @@ -1645,33 +1624,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. */ - - /* - * Apple hardware is out to get us. The macbook pro has a real LVDS - * panel, but the mac mini does not, and they have the same device IDs. - * We'll distinguish by panel size, on the assumption that Apple isn't - * about to make any machines with an 800x600 display. - */ - if (is_apple_945gm && pI830->PanelXRes == 800 && pI830->PanelYRes == 600) - { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Suspected Mac Mini, ignoring the LFP\n"); - has_lvds = FALSE; - } - - if (has_lvds) { - pI830->MonType2 |= PIPE_LFP; - } - if (i830DetectCRT(pScrn, TRUE)) { pI830->MonType1 |= PIPE_CRT; } /* Check for attached SDVO outputs. Assume that they're flat panels for * now. Though really, it's just a name at the moment, since we don't - * treat different SDVO outputs differently. + * treat different SDVO outputs differently. Also, check for LVDS and + * set it to the right pipe if available. */ for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].type == I830_OUTPUT_LVDS) + pI830->MonType2 |= PIPE_LFP; + if (pI830->output[i].type == I830_OUTPUT_SDVO) { if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i])) continue; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 399324f0..5b039b8e 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -181,6 +181,39 @@ i830_lvds_init(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with + * the BIOS being unavailable or broken, but lack the configuration options + * for now. + */ + if (!i830GetLVDSInfoFromBIOS(pScrn)) + return; + + /* Blacklist machines with BIOSes that list an LVDS panel without actually + * having one. + */ + if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) { + if (pI830->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */ + return; + + if ((pI830->PciInfo->subsysVendor == 0x8086) && + (pI830->PciInfo->subsysCard == 0x7270)) { + /* It's a Mac Mini or Macbook Pro. + * + * Apple hardware is out to get us. The macbook pro has a real + * LVDS panel, but the mac mini does not, and they have the same + * device IDs. We'll distinguish by panel size, on the assumption + * that Apple isn't about to make any machines with an 800x600 + * display. + */ + + if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Suspected Mac Mini, ignoring the LVDS\n"); + return; + } + } + } + pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS; pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms; pI830->output[pI830->num_outputs].save = i830_lvds_save; From 3a6104ab89b159241845314ccf88fa62da14cf7d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Oct 2006 19:15:30 -0700 Subject: [PATCH 189/257] Remove disabled I830DetectMonitorChange(). This used to be called when switching back in to X. It might make some sense to detect monitors at this time (it happens to occur at resume time, when monitors are likely to have changed), but it should probably live in either userland policy with RandR 1.2 or RandR 1.2 XFree86-DDX generic code. --- src/i830_driver.c | 208 ---------------------------------------------- 1 file changed, 208 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 9f986ec8..be834311 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3681,210 +3681,6 @@ I830LeaveVT(int scrnIndex, int flags) pI830->AccelInfoRec->NeedToSync = FALSE; } -static Bool -I830DetectMonitorChange(ScrnInfoPtr pScrn) -{ - return FALSE; -#if 0 /* Disabled until we rewrite this natively */ - I830Ptr pI830 = I830PTR(pScrn); - pointer pDDCModule = NULL; - DisplayModePtr p, pMon; - int memsize; - int DDCclock = 0, DDCclock2 = 0; - int displayWidth = pScrn->displayWidth; - int curHDisplay = pScrn->currentMode->HDisplay; - int curVDisplay = pScrn->currentMode->VDisplay; - xf86MonPtr monitor = NULL; - - DPRINTF(PFX, "Detect Monitor Change\n"); - - SetPipeAccess(pScrn); - - /* Re-read EDID */ - pDDCModule = xf86LoadSubModule(pScrn, "ddc"); - - pI830->pVbe->ddc = DDC_UNCHECKED; - monitor = vbeDoEDID(pI830->pVbe, pDDCModule); - xf86UnloadSubModule(pDDCModule); - if ((pScrn->monitor->DDC = monitor) != NULL) { - xf86PrintEDID(monitor); - xf86SetDDCproperties(pScrn, monitor); - } - - DDCclock = I830UseDDC(pScrn); - - /* Revalidate the modes */ - - /* - * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS - * functions. - */ - SetPipeAccess(pScrn); - - pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo); - - if (!pScrn->modePool) { - /* This is bad, which would cause the Xserver to exit, maybe - * we should default to a 640x480 @ 60Hz mode here ??? */ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No Video BIOS modes for chosen depth.\n"); - return FALSE; - } - - VBESetModeNames(pScrn->modePool); - - if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64)) - memsize = pI830->vbeInfo->TotalMemory * 64; - else - memsize = pScrn->videoRam; - - VBEValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, NULL, - NULL, 0, MAX_DISPLAY_PITCH, 1, - 0, MAX_DISPLAY_HEIGHT, - pScrn->display->virtualX, - pScrn->display->virtualY, - memsize, LOOKUP_BEST_REFRESH); - - if (pI830->MergedFB) { - VBEValidateModes(pI830->pScrn_2, pI830->pScrn_2->monitor->Modes, - pI830->pScrn_2->display->modes, NULL, - NULL, 0, MAX_DISPLAY_PITCH, 1, - 0, MAX_DISPLAY_HEIGHT, - pScrn->display->virtualX, - pScrn->display->virtualY, - memsize, LOOKUP_BEST_REFRESH); - } - - if (DDCclock > 0) { - p = pScrn->modes; - if (p == NULL) - return FALSE; - do { - int Clock = 100000000; /* incredible value */ - - if (p->status == MODE_OK) { - for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) { - if ((pMon->HDisplay != p->HDisplay) || - (pMon->VDisplay != p->VDisplay) || - (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - - /* Find lowest supported Clock for this resolution */ - if (Clock > pMon->Clock) - Clock = pMon->Clock; - } - - if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) { - ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", - p->name, pScrn->monitor->id, - Clock/1000.0, DDCclock); - p->status = MODE_BAD; - } - } - p = p->next; - } while (p != NULL && p != pScrn->modes); - } - - /* Only use this if we've got DDC available */ - if (pI830->MergedFB && DDCclock2 > 0) { - p = pI830->pScrn_2->modes; - if (p == NULL) - return FALSE; - do { - int Clock = 100000000; /* incredible value */ - - if (p->status == MODE_OK) { - for (pMon = pI830->pScrn_2->monitor->Modes; pMon != NULL; pMon = pMon->next) { - if ((pMon->HDisplay != p->HDisplay) || - (pMon->VDisplay != p->VDisplay) || - (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - - /* Find lowest supported Clock for this resolution */ - if (Clock > pMon->Clock) - Clock = pMon->Clock; - } - - if (Clock != 100000000 && DDCclock2 < 2550 && Clock / 1000.0 > DDCclock2) { - ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", - p->name, pI830->pScrn_2->monitor->id, - Clock/1000.0, DDCclock2); - p->status = MODE_BAD; - } - } - p = p->next; - } while (p != NULL && p != pI830->pScrn_2->modes); - } - - xf86PruneDriverModes(pScrn); - I830PrintModes(pScrn); - - /* Now check if the previously used mode is o.k. for the current monitor. - * This allows VT switching to continue happily when not disconnecting - * and reconnecting monitors */ - - pScrn->currentMode = pScrn->modes; - - if (pI830->MergedFB) { - /* If no virtual dimension was given by the user, - * calculate a sane one now. Adapts pScrn->virtualX, - * pScrn->virtualY and pScrn->displayWidth. - */ - I830RecalcDefaultVirtualSize(pScrn); - - pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ - pScrn->currentMode = pScrn->modes; - pI830->currentMode = pScrn->currentMode; - } - - pScrn->displayWidth = displayWidth; /* restore old displayWidth */ - - p = pScrn->modes; - if (p == NULL) - return FALSE; - do { - if ((p->HDisplay == curHDisplay) && - (p->VDisplay == curVDisplay) && - (!(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))) { - pScrn->currentMode = p; /* previous mode is o.k. */ - } - p = p->next; - } while (p != NULL && p != pScrn->modes); - - I830PrintModes(pScrn); - - /* Now readjust for panning if necessary */ - { - pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2; - - if (pScrn->frameX0 < 0) - pScrn->frameX0 = 0; - - pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; - if (pScrn->frameX1 >= pScrn->virtualX) { - pScrn->frameX0 = pScrn->virtualX - pScrn->currentMode->HDisplay; - pScrn->frameX1 = pScrn->virtualX - 1; - } - - pScrn->frameY0 = (pScrn->frameY0 + pScrn->frameY1 + 1 - pScrn->currentMode->VDisplay) / 2; - - if (pScrn->frameY0 < 0) - pScrn->frameY0 = 0; - - pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; - if (pScrn->frameY1 >= pScrn->virtualY) { - pScrn->frameY0 = pScrn->virtualY - pScrn->currentMode->VDisplay; - pScrn->frameY1 = pScrn->virtualY - 1; - } - } - - if (pI830->MergedFB) - I830AdjustFrameMerged(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - - return TRUE; -#endif /* 0 */ -} - /* * This gets called when gaining control of the VT, and from ScreenInit(). */ @@ -3925,10 +3721,6 @@ I830EnterVT(int scrnIndex, int flags) /* Mark that we'll need to re-set the mode for sure */ memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode)); - /* Detect monitor change and switch to suitable mode */ - if (!pI830->starting) - I830DetectMonitorChange(pScrn); - if (!i830SetMode(pScrn, pScrn->currentMode)) return FALSE; From df14838eb5d0a056f663d9f12bd8b5c25cf97330 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Oct 2006 00:18:33 -0700 Subject: [PATCH 190/257] Remove dead memsize reporting. The calculation no longer made sense, as we don't use the BIOS for mode selection. --- src/i830_driver.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index be834311..0c0aa952 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1087,7 +1087,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; I830EntPtr pI830Ent = NULL; - int mem, memsize; + int mem; int flags24; int i, n; char *s; @@ -2038,17 +2038,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - /* - * Limit videoram available for mode selection to what the video - * BIOS can see. - */ - if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64)) - memsize = pI830->vbeInfo->TotalMemory * 64; - else - memsize = pScrn->videoRam; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Maximum space available for video modes: %d kByte\n", memsize); - n = I830ValidateXF86ModeList(pScrn, TRUE); if (n <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); From 3ab9f5a4a8cd62c8a8c2a09d3d105adbe815a83d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Oct 2006 00:26:09 -0700 Subject: [PATCH 191/257] Move vbeInfo out of the driver struct to the one place it's used. --- src/i830.h | 1 - src/i830_driver.c | 42 ++++++++++++++---------------------------- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/i830.h b/src/i830.h index b4408c26..3f4eacc1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -447,7 +447,6 @@ typedef struct _I830Rec { /* Video BIOS support. */ vbeInfoPtr pVbe; - VbeInfoBlock *vbeInfo; VESAPtr vesa; Bool swfSaved; diff --git a/src/i830_driver.c b/src/i830_driver.c index 0c0aa952..10c6f09e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -375,8 +375,6 @@ I830FreeRec(ScrnInfoPtr pScrn) pI830 = I830PTR(pScrn); if (I830IsPrimary(pScrn)) { - if (pI830->vbeInfo) - VBEFreeVBEInfo(pI830->vbeInfo); if (pI830->pVbe) vbeFree(pI830->pVbe); } @@ -597,6 +595,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) CARD16 gmch_ctrl; int memsize = 0; int range; + VbeInfoBlock *vbeInfo; bridge = pciTag(0, 0, 0); /* This is always the host bridge */ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); @@ -661,6 +660,19 @@ I830DetectMemory(ScrnInfoPtr pScrn) } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n"); } + + /* Sanity check: compare with what the BIOS thinks. */ + vbeInfo = VBEGetVBEInfo(pI830->pVbe); + if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Detected stolen memory (%ld kB) doesn't match what the BIOS" + " reports (%d kB)\n", + ROUND_DOWN_TO(memsize / 1024, 64), + vbeInfo->TotalMemory * 64); + } + if (vbeInfo != NULL) + VBEFreeVBEInfo(vbeInfo); + return memsize; } @@ -1301,13 +1313,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Integrated Graphics Chipset: Intel(R) %s\n", chipname); - if (I830IsPrimary(pScrn)) { - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->vbeInfo = pI8301->vbeInfo; - } - /* Set the Chipset and ChipRev, allowing config file entries to override. */ if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) { pScrn->chipset = pI830->pEnt->device->chipset; @@ -1434,15 +1439,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->StolenMemory.Start = 0; pI830->StolenMemory.End = pI830->StolenMemory.Size; - /* Sanity check: compare with what the BIOS thinks. */ - if (pI830->vbeInfo->TotalMemory != pI830->StolenMemory.Size / 1024 / 64) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Detected stolen memory (%ld kB) doesn't match what the BIOS" - " reports (%d kB)\n", - ROUND_DOWN_TO(pI830->StolenMemory.Size / 1024, 64), - pI830->vbeInfo->TotalMemory * 64); - } - /* Find the maximum amount of agpgart memory available. */ if (I830IsPrimary(pScrn)) { mem = I830CheckAvailableMemory(pScrn); @@ -2243,10 +2239,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #if 0 if (I830IsPrimary(pScrn)) { - VBEFreeVBEInfo(pI830->vbeInfo); vbeFree(pI830->pVbe); } - pI830->vbeInfo = NULL; pI830->pVbe = NULL; #endif @@ -3233,14 +3227,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!pI830->pVbe) return FALSE; - if (I830IsPrimary(pScrn)) { - if (pI830->vbeInfo) - VBEFreeVBEInfo(pI830->vbeInfo); - pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); - } else { - pI830->vbeInfo = pI8301->vbeInfo; - } - SetPipeAccess(pScrn); miClearVisualTypes(); From c357eca10ca1c535d305e1f3028471a912ae4102 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 09:44:55 -0800 Subject: [PATCH 192/257] Clean up whitespace in i830_randr.c. --- src/i830_randr.c | 84 +++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index e4075f26..f64f3dab 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -58,7 +58,7 @@ typedef struct _i830RandRInfo { DisplayModePtr modes[MAX_DISPLAY_PIPES]; #endif } XF86RandRInfoRec, *XF86RandRInfoPtr; - + #ifdef RANDR_12_INTERFACE static Bool I830RandRInit12 (ScreenPtr pScreen); static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen); @@ -67,7 +67,8 @@ static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen); static int i830RandRIndex; static int i830RandRGeneration; -#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[i830RandRIndex].ptr) +#define XF86RANDRINFO(p) \ + ((XF86RandRInfoPtr)(p)->devPrivates[i830RandRIndex].ptr) static int I830RandRModeRefresh (DisplayModePtr mode) @@ -87,10 +88,10 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) DisplayModePtr mode; int refresh0 = 60; int maxX = 0, maxY = 0; - + *rotations = randrp->supported_rotations; - if (randrp->virtualX == -1 || randrp->virtualY == -1) + if (randrp->virtualX == -1 || randrp->virtualY == -1) { randrp->virtualX = scrp->virtualX; randrp->virtualY = scrp->virtualY; @@ -133,7 +134,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) randrp->maxX = maxX; randrp->maxY = maxY; } - + if (scrp->currentMode->HDisplay != randrp->virtualX || scrp->currentMode->VDisplay != randrp->virtualY) { @@ -144,7 +145,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) if (!pSize) return FALSE; RRRegisterRate (pScreen, pSize, refresh0); - if (scrp->virtualX == randrp->virtualX && + if (scrp->virtualX == randrp->virtualX && scrp->virtualY == randrp->virtualY) { RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); @@ -171,7 +172,7 @@ I830RandRSetMode (ScreenPtr pScreen, DisplayModePtr currentMode = NULL; Bool ret = TRUE; PixmapPtr pspix = NULL; - + if (pRoot) (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); if (useVirtual) @@ -227,7 +228,7 @@ I830RandRSetMode (ScreenPtr pScreen, pspix = (*pScreen->GetScreenPixmap) (pScreen); if (pspix->devPrivate.ptr) scrp->pixmapPrivate = pspix->devPrivate; - + /* * Make sure the layout is correct */ @@ -259,7 +260,7 @@ I830RandRSetConfig (ScreenPtr pScreen, randrp->rotation = rotation; - if (randrp->virtualX == -1 || randrp->virtualY == -1) + if (randrp->virtualX == -1 || randrp->virtualY == -1) { randrp->virtualX = scrp->virtualX; randrp->virtualY = scrp->virtualY; @@ -275,7 +276,7 @@ I830RandRSetConfig (ScreenPtr pScreen, if (maxY < mode->VDisplay) maxY = mode->VDisplay; } - if (mode->HDisplay == pSize->width && + if (mode->HDisplay == pSize->width && mode->VDisplay == pSize->height && (rate == 0 || I830RandRModeRefresh (mode) == rate)) break; @@ -303,7 +304,8 @@ I830RandRSetConfig (ScreenPtr pScreen, randrp->maxY = maxY; } - if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { + if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, + pSize->mmHeight)) { randrp->rotation = oldRotation; return FALSE; } @@ -361,17 +363,17 @@ I830RandRCreateScreenResources (ScreenPtr pScreen) pI830->starting = TRUE; /* abuse this for dual head & rotation */ I830RandRSetConfig (pScreen, requestedRotation, 0, &p); pI830->starting = FALSE; - } + } return TRUE; } - - + + Bool I830RandRInit (ScreenPtr pScreen, int rotation) { rrScrPrivPtr rp; XF86RandRInfoPtr randrp; - + #ifdef PANORAMIX /* XXX disable RandR when using Xinerama */ if (!noPanoramiXExtension) @@ -382,11 +384,11 @@ I830RandRInit (ScreenPtr pScreen, int rotation) i830RandRIndex = AllocateScreenPrivateIndex(); i830RandRGeneration = serverGeneration; } - + randrp = xalloc (sizeof (XF86RandRInfoRec)); if (!randrp) return FALSE; - + if (!RRScreenInit(pScreen)) { xfree (randrp); @@ -400,7 +402,7 @@ I830RandRInit (ScreenPtr pScreen, int rotation) randrp->virtualY = -1; randrp->mmWidth = pScreen->mmWidth; randrp->mmHeight = pScreen->mmHeight; - + randrp->rotation = RR_Rotate_0; /* initial rotated mode */ randrp->supported_rotations = rotation; @@ -446,8 +448,8 @@ I830RandRScreenSetSize (ScreenPtr pScreen, ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); WindowPtr pRoot = WindowTable[pScreen->myNum]; Bool ret = TRUE; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) + + if (randrp->virtualX == -1 || randrp->virtualY == -1) { randrp->virtualX = pScrn->virtualX; randrp->virtualY = pScrn->virtualY; @@ -461,7 +463,7 @@ I830RandRScreenSetSize (ScreenPtr pScreen, pScreen->height = pScrn->virtualY; pScreen->mmWidth = mmWidth; pScreen->mmHeight = mmHeight; - + xf86SetViewport (pScreen, pScreen->width, pScreen->height); xf86SetViewport (pScreen, 0, 0); if (pRoot) @@ -490,7 +492,7 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) int i, j; DisplayModePtr pipeMode = &pI830->pipeCurMode[pipe]; int pipe_type; - + x = pI830->pipeX[pipe]; y = pI830->pipeY[pipe]; rotation = RR_Rotate_0; @@ -533,7 +535,7 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) } return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs); } - + static Bool I830RandRCrtcSet (ScreenPtr pScreen, RRCrtcPtr crtc, @@ -549,7 +551,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, I830Ptr pI830 = I830PTR(pScrn); int pipe = (int) (crtc->devPrivate); DisplayModePtr display_mode = mode ? mode->devPrivate : NULL; - + /* Sync the engine before adjust mode */ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { (*pI830->AccelInfoRec->Sync)(pScrn); @@ -619,13 +621,13 @@ I830RandRSetInfo12 (ScreenPtr pScreen) RRModePtr rrmode, *rrmodes; CARD32 possibleOptions = 0; CARD32 currentOptions = 0; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) + + if (randrp->virtualX == -1 || randrp->virtualY == -1) { randrp->virtualX = pScrn->virtualX; randrp->virtualY = pScrn->virtualY; } - RRScreenSetSizeRange (pScreen, 320, 240, + RRScreenSetSizeRange (pScreen, 320, 240, randrp->virtualX, randrp->virtualY); for (i = 0; i < pI830->num_outputs; i++) { @@ -697,17 +699,17 @@ I830RandRSetInfo12 (ScreenPtr pScreen) return FALSE; RROutputSetCrtc (randrp->outputs[i], crtc); - + RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); nmode = 0; npreferred = 0; rrmodes = NULL; - if (pipe >= 0) + if (pipe >= 0) { MonPtr mon = pI830->pipeMon[pipe]; modes = mon->Modes; - + for (mode = modes; mode; mode = mode->next) nmode++; @@ -726,20 +728,20 @@ I830RandRSetInfo12 (ScreenPtr pScreen) modeInfo.nameLength = strlen (mode->name); modeInfo.mmWidth = mon->widthmm; modeInfo.mmHeight = mon->heightmm; - + modeInfo.width = mode->HDisplay; modeInfo.dotClock = mode->Clock * 1000; modeInfo.hSyncStart = mode->HSyncStart; modeInfo.hSyncEnd = mode->HSyncEnd; modeInfo.hTotal = mode->HTotal; modeInfo.hSkew = mode->HSkew; - + modeInfo.height = mode->VDisplay; modeInfo.vSyncStart = mode->VSyncStart; modeInfo.vSyncEnd = mode->VSyncEnd; modeInfo.vTotal = mode->VTotal; modeInfo.modeFlags = mode->Flags; - + rrmode = RRModeGet (pScreen, &modeInfo, mode->name); rrmode->devPrivate = mode; if (rrmode) @@ -752,21 +754,21 @@ I830RandRSetInfo12 (ScreenPtr pScreen) } } } - + if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred)) { xfree (rrmodes); return FALSE; } - + xfree (rrmodes); - + connection = RR_Disconnected; if (pipe >= 0) connection = RR_Connected; RROutputSetConnection (randrp->outputs[i], connection); - + RROutputSetSubpixelOrder (randrp->outputs[i], subpixel); /* @@ -786,7 +788,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) return TRUE; } - + /* * Query the hardware for the current state, then mirror * that to RandR @@ -828,7 +830,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) name, strlen (name), (void *) i); } - + mode = pScrn->currentMode; if (mode) { @@ -852,10 +854,10 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmWidth, mmHeight); } - + for (i = 0; i < MAX_DISPLAY_PIPES; i++) i830PipeSetBase(pScrn, i, 0, 0); - + return I830RandRSetInfo12 (pScreen); } From 71545db4614cfc4650acc4325912474e777c3b36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 09:46:10 -0800 Subject: [PATCH 193/257] Return and use valid status bits for i830_sdvo_get_trained_inputs(). --- src/i830_sdvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index ac5ae48e..87453b9b 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -277,7 +277,7 @@ i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2) i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0); - i830_sdvo_read_response(output, response, 2); + status = i830_sdvo_read_response(output, response, 2); if (status != SDVO_CMD_STATUS_SUCCESS) return FALSE; @@ -607,7 +607,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, /* two 03s, 04 05, 10, 1d */ /* these contain the height and mode clock / 10 by the looks of it */ - i830_sdvo_get_trained_inputs(output, &input1, &input2); + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); /* Warn if the device reported failure to sync. */ if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { From 819a47b27cd4728feb269a08be32403304993ffa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 09:50:33 -0800 Subject: [PATCH 194/257] Use the new fields for SDVO pixel multiply on the G965. This should fix display at resolutions/refresh rates in a different multiplier class than the console display (generally, high resolution modes). --- src/i810_reg.h | 54 +++++++++++++++++++++++++++++++++++++++++++++- src/i830.h | 2 ++ src/i830_display.c | 7 ++---- src/i830_driver.c | 8 +++++++ src/i830_sdvo.c | 9 ++++++-- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index a80b66ee..bc6c0f8b 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -799,10 +799,56 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PLL_REF_INPUT_TVCLKINBC (2 << 13) # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +/** + * SDVO multiplier for 945G/GM. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ # define SDVO_MULTIPLIER_MASK 0x000000ff # define SDVO_MULTIPLIER_SHIFT_HIRES 4 # define SDVO_MULTIPLIER_SHIFT_VGA 0 +/** @defgroup DPLL_MD + * @{ + */ +/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_A_MD 0x0601c +/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_B_MD 0x06020 +/** + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +# define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/** + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. */ +# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +/** @} */ + #define BLC_PWM_CTL 0x61254 #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) @@ -842,7 +888,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVO_PIPE_B_SELECT (1 << 30) #define SDVO_STALL_SELECT (1 << 29) #define SDVO_INTERRUPT_ENABLE (1 << 26) -/* Programmed value is multiplier - 1, up to 5x. alv, gdg only */ +/** + * 915G/GM SDVO pixel multiplier. + * + * Programmed value is multiplier - 1, up to 5x. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ #define SDVO_PORT_MULTIPLY_MASK (7 << 23) #define SDVO_PORT_MULTIPLY_SHIFT 23 #define SDVO_PHASE_SELECT_MASK (15 << 19) diff --git a/src/i830.h b/src/i830.h index 3f4eacc1..40c8cce6 100644 --- a/src/i830.h +++ b/src/i830.h @@ -509,6 +509,7 @@ typedef struct _I830Rec { CARD32 saveFPA0; CARD32 saveFPA1; CARD32 saveDPLL_A; + CARD32 saveDPLL_A_MD; CARD32 saveHTOTAL_A; CARD32 saveHBLANK_A; CARD32 saveHSYNC_A; @@ -523,6 +524,7 @@ typedef struct _I830Rec { CARD32 saveFPB0; CARD32 saveFPB1; CARD32 saveDPLL_B; + CARD32 saveDPLL_B_MD; CARD32 saveHTOTAL_B; CARD32 saveHBLANK_B; CARD32 saveHSYNC_B; diff --git a/src/i830_display.c b/src/i830_display.c index a94e21da..41f8c213 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -472,11 +472,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) } } - /* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz. - * The clock on the bus is 10 times the pixel clock normally. If that - * would be too low, we run the DPLL at a multiple of the pixel clock, and - * tell the SDVO device the multiplier so it can throw away the dummy - * bytes. + /* Adjust the clock for pixel multiplication. + * See DPLL_MD_UDI_MULTIPLIER_MASK. */ if (is_sdvo) { pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 10c6f09e..5494abb6 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2506,6 +2506,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveFPA0 = INREG(FPA0); pI830->saveFPA1 = INREG(FPA1); pI830->saveDPLL_A = INREG(DPLL_A); + if (IS_I965G(pI830)) + pI830->saveDPLL_A_MD = INREG(DPLL_A_MD); pI830->saveHTOTAL_A = INREG(HTOTAL_A); pI830->saveHBLANK_A = INREG(HBLANK_A); pI830->saveHSYNC_A = INREG(HSYNC_A); @@ -2528,6 +2530,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveFPB0 = INREG(FPB0); pI830->saveFPB1 = INREG(FPB1); pI830->saveDPLL_B = INREG(DPLL_B); + if (IS_I965G(pI830)) + pI830->saveDPLL_B_MD = INREG(DPLL_B_MD); pI830->saveHTOTAL_B = INREG(HTOTAL_B); pI830->saveHBLANK_B = INREG(HBLANK_B); pI830->saveHSYNC_B = INREG(HSYNC_B); @@ -2611,6 +2615,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); OUTREG(DPLL_A, pI830->saveDPLL_A); + if (IS_I965G(pI830)) + OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); OUTREG(HBLANK_A, pI830->saveHBLANK_A); OUTREG(HSYNC_A, pI830->saveHSYNC_A); @@ -2630,6 +2636,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(FPB0, pI830->saveFPB0); OUTREG(FPB1, pI830->saveFPB1); OUTREG(DPLL_B, pI830->saveDPLL_B); + if (IS_I965G(pI830)) + OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 87453b9b..bbc1c725 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -600,6 +600,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, Bool out1, out2, input1, input2; CARD32 dpll, sdvob, sdvoc; int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; + int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; CARD8 status; @@ -630,10 +631,14 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, dpll = INREG(dpll_reg); sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); - if (IS_I945G(pI830) || IS_I945GM(pI830)) + if (IS_I965G(pI830)) { + OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + } else if (IS_I945G(pI830) || IS_I945GM(pI830)) { dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else + } else { sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; + } OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED); From bca9e6ccbd14eb8f2f103e8e64b28a623113d494 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 11:17:27 -0800 Subject: [PATCH 195/257] Remove SetPipeAccess and now-unnecessary VBE reinit. --- src/i830_driver.c | 62 ----------------------------------------------- 1 file changed, 62 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 5494abb6..688d970d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -305,7 +305,6 @@ static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock *block); #endif static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); -static Bool SetPipeAccess(ScrnInfoPtr pScrn); extern int I830EntityIndex; @@ -442,49 +441,6 @@ struct panelid { char reserved[14]; }; -static Bool -SetBIOSPipe(ScrnInfoPtr pScrn, int pipe) -{ - I830Ptr pI830 = I830PTR(pScrn); - vbeInfoPtr pVbe = pI830->pVbe; - - DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe); - - /* single pipe machines should always return TRUE */ - if (pI830->availablePipes == 1) return TRUE; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f1c; - if (pI830->newPipeSwitch) { - pVbe->pInt10->bx = pipe; - pVbe->pInt10->cx = 0; - } else { - pVbe->pInt10->bx = 0x0; - pVbe->pInt10->cx = pipe << 8; - } - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) { - return TRUE; - } - - return FALSE; -} - -static Bool -SetPipeAccess(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - /* Don't try messing with the pipe, unless we're dual head */ - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) { - if (!SetBIOSPipe(pScrn, pI830->pipe)) - return FALSE; - } - - return TRUE; -} - static Bool GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) { @@ -3219,24 +3175,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->used3D = pI8301->used3D; } - /* - * If we're changing the BIOS's view of the video memory size, do that - * first, then re-initialise the VBE information. - */ - if (I830IsPrimary(pScrn)) { - SetPipeAccess(pScrn); - if (pI830->pVbe) - vbeFree(pI830->pVbe); - pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - } else { - pI830->pVbe = pI8301->pVbe; - } - - if (!pI830->pVbe) - return FALSE; - - SetPipeAccess(pScrn); - miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), From 837b2f632062bc29268f109895a577bd90cabd6d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 11:17:55 -0800 Subject: [PATCH 196/257] Warning fix. --- src/i830_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 688d970d..29c3ba3b 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -621,7 +621,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) vbeInfo = VBEGetVBEInfo(pI830->pVbe); if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Detected stolen memory (%ld kB) doesn't match what the BIOS" + "Detected stolen memory (%d kB) doesn't match what the BIOS" " reports (%d kB)\n", ROUND_DOWN_TO(memsize / 1024, 64), vbeInfo->TotalMemory * 64); From 2ca57040b0cd24ad3dbe693789091e28be4e69f8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 11:19:19 -0800 Subject: [PATCH 197/257] Remove GetBIOSVersion(). This info hardly useful now that we don't use the BIOS for mode setting. --- src/i830_driver.c | 55 ----------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 29c3ba3b..609e1b55 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -407,27 +407,6 @@ const int i830refreshes[] = { }; static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]); -static Bool -Check5fStatus(ScrnInfoPtr pScrn, int func, int ax) -{ - if (ax == 0x005f) - return TRUE; - else if (ax == 0x015f) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Extended BIOS function 0x%04x failed.\n", func); - return FALSE; - } else if ((ax & 0xff) != 0x5f) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Extended BIOS function 0x%04x not supported.\n", func); - return FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Extended BIOS function 0x%04x returns 0x%04x.\n", - func, ax & 0xffff); - return FALSE; - } -} - struct panelid { short hsize; short vsize; @@ -441,26 +420,6 @@ struct panelid { char reserved[14]; }; -static Bool -GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) -{ - vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; - - DPRINTF(PFX, "GetBIOSVersion\n"); - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x5f01; - - xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) { - *version = pVbe->pInt10->bx; - return TRUE; - } - - *version = 0; - return FALSE; -} - /* * Returns a string matching the device corresponding to the first bit set * in "device". savedDevice is then set to device with that bit cleared. @@ -1062,8 +1021,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pointer pVBEModule = NULL; Bool enable; const char *chipname; - unsigned int ver; - char v[5]; if (pScrn->numEntities != 1) return FALSE; @@ -1882,18 +1839,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - GetBIOSVersion(pScrn, &ver); - - v[0] = (ver & 0xff000000) >> 24; - v[1] = (ver & 0x00ff0000) >> 16; - v[2] = (ver & 0x0000ff00) >> 8; - v[3] = (ver & 0x000000ff) >> 0; - v[4] = 0; - - pI830->bios_version = atoi(v); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version); - if (IS_I9XX(pI830)) pI830->newPipeSwitch = TRUE; else From e7d546cac06767ec58325396a3bb5780b2257c53 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 30 Oct 2006 11:24:43 -0800 Subject: [PATCH 198/257] Remove some dead code from BIOS modesetting. --- src/i830_driver.c | 93 ----------------------------------------------- src/i830_gtf.c | 2 - src/i830_modes.c | 2 - 3 files changed, 97 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 609e1b55..f142c4b2 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -300,10 +300,6 @@ static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830SaveScreen(ScreenPtr pScreen, int unblack); static Bool I830EnterVT(int scrnIndex, int flags); -#if 0 -static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, - VbeCRTCInfoBlock *block); -#endif static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg); extern int I830EntityIndex; @@ -398,28 +394,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int index) ConfiguredMonitor = vbeDoEDID(pVbe, NULL); } -/* Various extended video BIOS functions. - * 100 and 120Hz aren't really supported, they work but only get close - * to the requested refresh, and really not close enough. - * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */ -const int i830refreshes[] = { - 43, 56, 60, 70, 72, 75, 85 /* 100, 120 */ -}; -static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[0]); - -struct panelid { - short hsize; - short vsize; - short fptype; - char redbpp; - char greenbpp; - char bluebpp; - char reservedbpp; - int rsvdoffscrnmemsize; - int rsvdoffscrnmemptr; - char reserved[14]; -}; - /* * Returns a string matching the device corresponding to the first bit set * in "device". savedDevice is then set to device with that bit cleared. @@ -760,73 +734,6 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, pI830->CursorInfoRec->ShowCursor(pScrn); } -#if 0 -static int -I830UseDDC(ScrnInfoPtr pScrn) -{ - xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC); - struct detailed_monitor_section* detMon; - struct monitor_ranges *mon_range = NULL; - int i; - - if (!DDC) return 0; - - /* Now change the hsync/vrefresh values of the current monitor to - * match those of DDC */ - for (i = 0; i < 4; i++) { - detMon = &DDC->det_mon[i]; - if(detMon->type == DS_RANGES) - mon_range = &detMon->section.ranges; - } - - if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 || - mon_range->min_v == 0 || mon_range->max_v == 0) - return 0; /* bad ddc */ - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n", - mon_range->min_h, mon_range->max_h); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tVertRefresh %d-%d\n", - mon_range->min_v, mon_range->max_v); -#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE - if (pScrn->monitor->nHsync > 0) { - for (i = 0; i < pScrn->monitor->nHsync; i++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h > - pScrn->monitor->hsync[i].lo || - (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h < - pScrn->monitor->hsync[i].hi) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "config file hsync range %g-%gkHz not within DDC " - "hsync range %d-%dkHz\n", - pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi, - mon_range->min_h, mon_range->max_h); - } - pScrn->monitor->hsync[i].lo = mon_range->min_h; - pScrn->monitor->hsync[i].hi = mon_range->max_h; - } - } - - if (pScrn->monitor->nVrefresh > 0) { - for (i=0; imonitor->nVrefresh; i++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v > - pScrn->monitor->vrefresh[i].lo || - (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v < - pScrn->monitor->vrefresh[i].hi) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "config file vrefresh range %g-%gHz not within DDC " - "vrefresh range %d-%dHz\n", - pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi, - mon_range->min_v, mon_range->max_v); - } - pScrn->monitor->vrefresh[i].lo = mon_range->min_v; - pScrn->monitor->vrefresh[i].hi = mon_range->max_v; - } - } - - return mon_range->max_clock; -} -#endif - /** * Set up the outputs according to what type of chip we are. * diff --git a/src/i830_gtf.c b/src/i830_gtf.c index 663a2f45..523e167a 100644 --- a/src/i830_gtf.c +++ b/src/i830_gtf.c @@ -67,8 +67,6 @@ #define C_PRIME (((C - J) * K/256.0) + J) #define M_PRIME (K/256.0 * M) -extern const int i830refreshes[]; - DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins) { diff --git a/src/i830_modes.c b/src/i830_modes.c index f4306934..633ac832 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -99,8 +99,6 @@ static struct #define DEBUG_REPROBE 1 -extern const int i830refreshes[]; - void I830PrintModes(ScrnInfoPtr scrp) { From 49bbdf16c02107c08169f8d2b6e9c6dbd7d8cd95 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 10:44:45 -0800 Subject: [PATCH 199/257] Fix many inconsistencies in the SDVO code compared to the spec. Also, fix some struct padding so that the right bits are sent out. --- src/i830_sdvo.c | 169 ++++++++++++++++++++++--------------------- src/i830_sdvo_regs.h | 109 +++++++++++++++++++++++++--- 2 files changed, 185 insertions(+), 93 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index bbc1c725..d3f509e5 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -54,21 +54,27 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. struct i830_sdvo_priv { /** SDVO device on SDVO I2C bus. */ I2CDevRec d; + /** Register for the SDVO device: SDVOB or SDVOC */ int output_device; + + /** Active outputs controlled by this SDVO output */ + struct i830_sdvo_output_flags active_outputs; + /** * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities() */ - i830_sdvo_caps caps; + struct i830_sdvo_caps caps; + /** Pixel clock limitations reported by the SDVO device */ CARD16 pixel_clock_min, pixel_clock_max; /** State for save/restore */ /** @{ */ int save_sdvo_mult; - Bool save_sdvo_active_1, save_sdvo_active_2; + struct i830_sdvo_output_flags save_active_outputs; struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2; - struct i830_sdvo_dtd save_output_dtd_1, save_output_dtd_2; + struct i830_sdvo_dtd save_output_dtd; CARD32 save_SDVOX; /** @} */ }; @@ -122,7 +128,7 @@ const struct _sdvo_cmd_name { SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTR_EVENT_SOURCE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), @@ -187,7 +193,7 @@ static const char *cmd_status_names[] = { "Not supported", "Invalid arg", "Pending", - "Target not supported", + "Target not specified", "Scaling not supported" }; @@ -249,14 +255,19 @@ i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target) } static Bool -i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2) +i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1) { - CARD8 targets[2]; + struct i830_sdvo_set_target_input_args targets = {0}; CARD8 status; - targets[0] = target_1; - targets[1] = target_2; - i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, 2); + if (target_0 && target_1) + return SDVO_CMD_STATUS_NOTSUPP; + + if (target_1) + targets.target_1 = 1; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, + sizeof(targets)); status = i830_sdvo_read_response(output, NULL, 0); @@ -272,47 +283,41 @@ i830_sdvo_set_target_input(I830OutputPtr output, Bool target_1, Bool target_2) static Bool i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2) { - CARD8 response[2]; + struct i830_sdvo_get_trained_inputs_response response; CARD8 status; i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0); - status = i830_sdvo_read_response(output, response, 2); + status = i830_sdvo_read_response(output, &response, sizeof(response)); if (status != SDVO_CMD_STATUS_SUCCESS) return FALSE; - *input_1 = response[0]; - *input_2 = response[1]; + *input_1 = response.input0_trained; + *input_2 = response.input1_trained; return TRUE; } static Bool -i830_sdvo_get_active_outputs(I830OutputPtr output, Bool *on_1, Bool *on_2) +i830_sdvo_get_active_outputs(I830OutputPtr output, + struct i830_sdvo_output_flags *outputs) { - CARD8 response[2]; CARD8 status; i830_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0); - - status = i830_sdvo_read_response(output, &response, 2); - - *on_1 = response[0]; - *on_2 = response[1]; + status = i830_sdvo_read_response(output, outputs, sizeof(*outputs)); return (status == SDVO_CMD_STATUS_SUCCESS); } static Bool -i830_sdvo_set_active_outputs(I830OutputPtr output, Bool on_1, Bool on_2) +i830_sdvo_set_active_outputs(I830OutputPtr output, + struct i830_sdvo_output_flags *outputs) { - CARD8 outputs[2]; CARD8 status; - outputs[0] = on_1; - outputs[1] = on_2; - i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, 2); - + i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, outputs, + sizeof(*outputs)); status = i830_sdvo_read_response(output, NULL, 0); return (status == SDVO_CMD_STATUS_SUCCESS); @@ -339,14 +344,13 @@ i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, } static Bool -i830_sdvo_set_target_output(I830OutputPtr output, Bool target_1, Bool target_2) +i830_sdvo_set_target_output(I830OutputPtr output, + struct i830_sdvo_output_flags *outputs) { - CARD8 targets[2]; CARD8 status; - targets[0] = target_1; - targets[1] = target_2; - i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &targets, 2); + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, outputs, + sizeof(*outputs)); status = i830_sdvo_read_response(output, NULL, 0); @@ -508,11 +512,15 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); + struct i830_sdvo_priv *dev_priv = output->dev_priv; CARD16 width = mode->CrtcHDisplay; CARD16 height = mode->CrtcVDisplay; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; struct i830_sdvo_dtd output_dtd; + struct i830_sdvo_output_flags no_outputs; + + memset(&no_outputs, 0, sizeof(no_outputs)); /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; @@ -549,13 +557,13 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, output_dtd.part2.dtd_flags |= 0x4; /* Turn off the screens before adjusting timings */ - i830_sdvo_set_active_outputs(output, FALSE, FALSE); + i830_sdvo_set_active_outputs(output, &no_outputs); /* Set the output timing to the screen */ - i830_sdvo_set_target_output(output, TRUE, FALSE); + i830_sdvo_set_target_output(output, &dev_priv->active_outputs); i830_sdvo_set_output_timing(output, &output_dtd); - /* Set the input timing to the screen */ + /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); /* We would like to use i830_sdvo_create_preferred_input_timing() to @@ -597,29 +605,15 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr mode) { I830Ptr pI830 = I830PTR(pScrn); - Bool out1, out2, input1, input2; + struct i830_sdvo_priv *dev_priv = output->dev_priv; + Bool input1, input2; CARD32 dpll, sdvob, sdvoc; int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; + int i; CARD8 status; - /* the BIOS writes out 6 commands post mode set */ - /* two 03s, 04 05, 10, 1d */ - /* these contain the height and mode clock / 10 by the looks of it */ - - status = i830_sdvo_get_trained_inputs(output, &input1, &input2); - - /* Warn if the device reported failure to sync. */ - if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "First SDVO output reported failure to sync\n"); - } - - i830_sdvo_get_active_outputs(output, &out1, &out2); - i830_sdvo_set_active_outputs(output, TRUE, FALSE); - i830_sdvo_set_target_input(output, FALSE, FALSE); - /* Set the SDVO control regs. */ sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK; sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK; @@ -644,18 +638,37 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, OUTREG(SDVOB, sdvob); OUTREG(SDVOC, sdvoc); + + for (i = 0; i < 2; i++) + i830WaitForVblank(pScrn); + + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); + + /* Warn if the device reported failure to sync. */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First SDVO output reported failure to sync\n"); + } + + i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs); + i830_sdvo_set_target_input(output, TRUE, FALSE); } static void i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { I830Ptr pI830 = I830PTR(pScrn); + struct i830_sdvo_priv *dev_priv = output->dev_priv; if (mode != DPMSModeOn) { - i830_sdvo_set_active_outputs(output, FALSE, FALSE); + struct i830_sdvo_output_flags no_outputs; + + memset(&no_outputs, 0, sizeof(no_outputs)); + + i830_sdvo_set_active_outputs(output, &no_outputs); OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE); } else { - i830_sdvo_set_active_outputs(output, TRUE, FALSE); + i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs); OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE); } } @@ -666,12 +679,13 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) I830Ptr pI830 = I830PTR(pScrn); struct i830_sdvo_priv *dev_priv = output->dev_priv; + /* XXX: We should save the in/out mapping. */ + dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output); - i830_sdvo_get_active_outputs(output, &dev_priv->save_sdvo_active_1, - &dev_priv->save_sdvo_active_2); + i830_sdvo_get_active_outputs(output, &dev_priv->save_active_outputs); if (dev_priv->caps.sdvo_inputs_mask & 0x1) { - i830_sdvo_set_target_input(output, FALSE, FALSE); + i830_sdvo_set_target_input(output, TRUE, FALSE); i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1); } @@ -680,15 +694,11 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2); } - if (dev_priv->caps.output_0_supported) { - i830_sdvo_set_target_output(output, TRUE, FALSE); - i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_1); - } - - if (dev_priv->caps.output_1_supported) { - i830_sdvo_set_target_output(output, FALSE, TRUE); - i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd_2); - } + /* XXX: We should really iterate over the enabled outputs and save each + * one's state. + */ + i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs); + i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd); dev_priv->save_SDVOX = INREG(dev_priv->output_device); } @@ -700,7 +710,7 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) struct i830_sdvo_priv *dev_priv = output->dev_priv; if (dev_priv->caps.sdvo_inputs_mask & 0x1) { - i830_sdvo_set_target_input(output, FALSE, FALSE); + i830_sdvo_set_target_input(output, TRUE, FALSE); i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1); } @@ -709,22 +719,14 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2); } - if (dev_priv->caps.output_0_supported) { - i830_sdvo_set_target_output(output, TRUE, FALSE); - i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_1); - } - - if (dev_priv->caps.output_1_supported) { - i830_sdvo_set_target_output(output, FALSE, TRUE); - i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd_2); - } + i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs); + i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd); i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult); OUTREG(dev_priv->output_device, dev_priv->save_SDVOX); - i830_sdvo_set_active_outputs(output, dev_priv->save_sdvo_active_1, - dev_priv->save_sdvo_active_2); + i830_sdvo_set_active_outputs(output, &dev_priv->save_active_outputs); } static int @@ -743,7 +745,7 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, } static Bool -i830_sdvo_get_capabilities(I830OutputPtr output, i830_sdvo_caps *caps) +i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps) { CARD8 status; @@ -866,7 +868,7 @@ i830_sdvo_dump_device(I830OutputPtr output) i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG); - i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTR_EVENT_SOURCE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART2); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1); @@ -1023,6 +1025,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min, &dev_priv->pixel_clock_max); + memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs)); + dev_priv->active_outputs.tmds0 = 1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SDVO device VID/DID: %02X:%02X.%02X, " "input 1: %c, input 2: %c, " @@ -1031,8 +1036,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) dev_priv->caps.device_rev_id, (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', - dev_priv->caps.output_0_supported ? 'Y' : 'N', - dev_priv->caps.output_1_supported ? 'Y' : 'N'); + dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N', + dev_priv->caps.output_flags.tmds1 ? 'Y' : 'N'); pI830->num_outputs++; } diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index be3294b4..c43e17a8 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -25,7 +25,23 @@ * */ -typedef struct _i830_sdvo_caps { +struct i830_sdvo_output_flags { + unsigned int tmds0:1; + unsigned int rgb0:1; + unsigned int cvbs0:1; + unsigned int svid0:1; + unsigned int yprpb0:1; + unsigned int scart0:1; + unsigned int lvds0:1; + unsigned int pad0:1; + unsigned int tmds1:1; + unsigned int pad1:4; + unsigned int rgb1:1; + unsigned int lvds1:1; + unsigned int pad2:1; +} __attribute__((packed)); + +struct i830_sdvo_caps { CARD8 vendor_id; CARD8 device_id; CARD8 device_rev_id; @@ -38,13 +54,13 @@ typedef struct _i830_sdvo_caps { unsigned int down_scaling:1; unsigned int stall_support:1; unsigned int pad:1; - CARD8 output_0_supported; - CARD8 output_1_supported; -} __attribute__((packed)) i830_sdvo_caps; + struct i830_sdvo_output_flags output_flags; +} __attribute__((packed)); +/** This matches the EDID DTD structure, more or less */ struct i830_sdvo_dtd { struct { - CARD16 clock; + CARD16 clock; /**< pixel clock, in 10kHz units */ CARD8 h_active; CARD8 h_blank; CARD8 h_high; @@ -66,8 +82,8 @@ struct i830_sdvo_dtd { } __attribute__((packed)); struct i830_sdvo_pixel_clock_range { - CARD16 min; - CARD16 max; + CARD16 min; /**< pixel clock, in 10kHz units */ + CARD16 max; /**< pixel clock, in 10kHz units */ } __attribute__((packed)); struct i830_sdvo_preferred_input_timing_args { @@ -103,7 +119,7 @@ struct i830_sdvo_preferred_input_timing_args { #define SDVO_CMD_STATUS_NOTSUPP 0x2 #define SDVO_CMD_STATUS_INVALID_ARG 0x3 #define SDVO_CMD_STATUS_PENDING 0x4 -#define SDVO_CMD_STATUS_TARGET_NOT_SUPP 0x5 +#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 #define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 /* SDVO commands, argument/result registers */ @@ -116,29 +132,93 @@ struct i830_sdvo_preferred_input_timing_args { #define SDVO_CMD_GET_FIRMWARE_REV 0x86 # define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 # define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 +# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 +/** + * Reports which inputs are trained (managed to sync). + * + * Devices must have trained within 2 vsyncs of a mode change. + */ #define SDVO_CMD_GET_TRAINED_INPUTS 0x03 +struct i830_sdvo_get_trained_inputs_response { + unsigned int input0_trained:1; + unsigned int input1_trained:1; + unsigned int pad:6; +} __attribute__((packed)); +/** Returns a struct i830_sdvo_output_flags of active outputs. */ #define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 +/** + * Sets the current set of active outputs. + * + * Takes a struct i830_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP + * on multi-output devices. + */ #define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 +/** + * Returns the current mapping of SDVO inputs to outputs on the device. + * + * Returns two struct i830_sdvo_output_flags structures. + */ #define SDVO_CMD_GET_IN_OUT_MAP 0x06 +/** + * Sets the current mapping of SDVO inputs to outputs on the device. + * + * Takes two struct i380_sdvo_output_flags structures. + */ #define SDVO_CMD_SET_IN_OUT_MAP 0x07 +/** + * Returns a struct i830_sdvo_output_flags of attached displays. + */ #define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b +/** + * Returns a struct i830_sdvo_ouptut_flags of displays supporting hot plugging. + */ #define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c +/** + * Takes a struct i830_sdvo_output_flags. + */ #define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d +/** + * Returns a struct i830_sdvo_output_flags of displays with hot plug + * interrupts enabled. + */ #define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e -#define SDVO_CMD_GET_INTR_EVENT_SOURCE 0x0f +#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f +struct i830_sdvo_get_interrupt_event_source_response { + struct i830_sdvo_output_flags interrupt_status; + unsigned int ambient_light_interrupt:1; + unsigned int pad:7; +} __attribute__((packed)); +/** + * Selects which input is affected by future input commands. + * + * Commands affected include SET_INPUT_TIMINGS_PART[12], + * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], + * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. + */ #define SDVO_CMD_SET_TARGET_INPUT 0x10 +struct i830_sdvo_set_target_input_args { + unsigned int target_1:1; + unsigned int pad:7; +} __attribute__((packed)); +/** + * Takes a struct i830_sdvo_output_flags of which outputs are targetted by + * future output commands. + * + * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], + * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. + */ #define SDVO_CMD_SET_TARGET_OUTPUT 0x11 #define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 @@ -174,6 +254,12 @@ struct i830_sdvo_preferred_input_timing_args { # define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) # define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 +/** + * Generates a DTD based on the given width, height, and flags. + * + * This will be supported by any device supporting scaling or interlaced + * modes. + */ #define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 @@ -193,15 +279,16 @@ struct i830_sdvo_preferred_input_timing_args { /** Returns a struct i830_sdvo_pixel_clock_range */ #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e +/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f +/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 +/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 # define SDVO_CLOCK_RATE_MULT_1X (1 << 0) # define SDVO_CLOCK_RATE_MULT_2X (1 << 1) -# define SDVO_CLOCK_RATE_MULT_3X (1 << 2) # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) -# define SDVO_CLOCK_RATE_MULT_5X (1 << 4) #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 From 4f5d4d8870fc2784192f95a561163cf4fc8737ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 13:37:23 -0800 Subject: [PATCH 200/257] i830SetLVDSPanelPower is now a static function in i830_lvds.c, so remove it. --- src/i830_display.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i830_display.h b/src/i830_display.h index 229e576b..576a1491 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -30,7 +30,6 @@ Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); -void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); From 9fd719fce27f916ab5120f6e1234affa14eaed9d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 14:29:44 -0800 Subject: [PATCH 201/257] Move SDVOB_PRESERVE_MASK next to SDVOC_PRESERVE_MASK. --- src/i810_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index bc6c0f8b..34e6e536 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -880,7 +880,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define CRT_HOTPLUG_MONITOR_NONE (0 << 8) # define SDVOC_HOTPLUG_INT_STATUS (1 << 7) # define SDVOB_HOTPLUG_INT_STATUS (1 << 6) -#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) #define SDVOB 0x61140 #define SDVOC 0x61160 @@ -905,6 +904,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVOB_PCIE_CONCURRENCY (1 << 3) #define SDVO_DETECTED (1 << 2) /* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) #define SDVOC_PRESERVE_MASK (1 << 17) #define I830_HTOTAL_MASK 0xfff0000 From 68cef9f4e028755bbf3e1862da2ef47d46ddaa6a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 14:32:00 -0800 Subject: [PATCH 202/257] Move output connection detection to a per-output method. This will be used by RandR, and should let us clean up some of the initial display configuration, hopefully. Also, analog hotplug-based detection is now enabled on G965. --- src/i830.h | 11 +++ src/i830_crt.c | 162 +++++++++++++++++++++++++++++++++++++++++++++ src/i830_display.c | 147 ---------------------------------------- src/i830_display.h | 1 - src/i830_driver.c | 59 ++++++++++------- src/i830_dvo.c | 12 ++++ src/i830_lvds.c | 14 ++++ src/i830_modes.c | 13 ++-- src/i830_sdvo.c | 12 ++-- src/i830_sdvo.h | 3 - src/i830_tv.c | 13 ++++ 11 files changed, 261 insertions(+), 186 deletions(-) diff --git a/src/i830.h b/src/i830.h index 40c8cce6..b962e88c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -207,6 +207,12 @@ struct _I830DVODriver { extern const char *i830_output_type_names[]; +enum detect_status { + OUTPUT_STATUS_CONNECTED, + OUTPUT_STATUS_DISCONNECTED, + OUTPUT_STATUS_UNKNOWN +}; + struct _I830OutputRec { int type; int pipe; @@ -258,6 +264,11 @@ struct _I830OutputRec { void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode); + /** + * Probe for a connected output, and return detect_status. + */ + enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output); + xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; diff --git a/src/i830_crt.c b/src/i830_crt.c index 7721a0c2..d271eedb 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -112,6 +112,167 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, OUTREG(ADPA, adpa); } +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. + * + * Only for I945G/GM. + * + * \return TRUE if CRT is connected. + * \return FALSE if CRT is disconnected. + */ +static Bool +i830_crt_detect_hotplug(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + const int timeout_ms = 1000; + int starttime, curtime; + + temp = INREG(PORT_HOTPLUG_EN); + + OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5)); + + for (curtime = starttime = GetTimeInMillis(); + (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis()) + { + if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0) + break; + } + + if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == + CRT_HOTPLUG_MONITOR_COLOR) + { + return TRUE; + } else { + return FALSE; + } +} + +/** + * Detects CRT presence by checking for load. + * + * Requires that the current pipe's DPLL is active. This will cause flicker + * on the CRT, so it should not be used while the display is being used. Only + * color (not monochrome) displays are detected. + * + * \return TRUE if CRT is connected. + * \return FALSE if CRT is disconnected. + */ +static Bool +i830_crt_detect_load(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 adpa, pipeconf; + CARD8 st00; + int pipeconf_reg, bclrpat_reg, dpll_reg; + int pipe; + + pipe = pI830->pipe; + if (pipe == 0) { + bclrpat_reg = BCLRPAT_A; + pipeconf_reg = PIPEACONF; + dpll_reg = DPLL_A; + } else { + bclrpat_reg = BCLRPAT_B; + pipeconf_reg = PIPEBCONF; + dpll_reg = DPLL_B; + } + + /* Don't try this if the DPLL isn't running. */ + if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE)) + return FALSE; + + adpa = INREG(ADPA); + + /* Enable CRT output if disabled. */ + if (!(adpa & ADPA_DAC_ENABLE)) { + OUTREG(ADPA, adpa | ADPA_DAC_ENABLE | + ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); + } + + /* Set the border color to red, green. Maybe we should save/restore this + * reg. + */ + OUTREG(bclrpat_reg, 0x00500050); + + /* Force the border color through the active region */ + pipeconf = INREG(pipeconf_reg); + OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); + + /* Read the ST00 VGA status register */ + st00 = pI830->readStandard(pI830, 0x3c2); + + /* Restore previous settings */ + OUTREG(pipeconf_reg, pipeconf); + OUTREG(ADPA, adpa); + + if (st00 & (1 << 4)) + return TRUE; + else + return FALSE; +} + +/** + * Detects CRT presence by probing for a response on the DDC address. + * + * This takes approximately 5ms in testing on an i915GM, with CRT connected or + * not. + * + * \return TRUE if the CRT is connected and responded to DDC. + * \return FALSE if no DDC response was detected. + */ +static Bool +i830_crt_detect_ddc(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct _I830OutputRec *output; + + output = &pI830->output[0]; + /* CRT should always be at 0, but check anyway */ + if (output->type != I830_OUTPUT_ANALOG) + return FALSE; + + return xf86I2CProbeAddress(output->pDDCBus, 0x00A0); +} + +/** + * Attempts to detect CRT presence through any method available. + * + * @param allow_disturb enables detection methods that may cause flickering + * on active displays. + */ +static enum detect_status +i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) { + if (i830_crt_detect_hotplug(pScrn)) + return OUTPUT_STATUS_CONNECTED; + else + return OUTPUT_STATUS_DISCONNECTED; + } + + if (i830_crt_detect_ddc(pScrn)) + return OUTPUT_STATUS_CONNECTED; + + /* Use the load-detect method if we're not currently outputting to the CRT, + * or we don't care. + * + * Actually, the method is unreliable currently. We need to not share a + * pipe, as it seems having other outputs on that pipe will result in a + * false positive. + */ + if (0) { + if (i830_crt_detect_load(pScrn)) + return OUTPUT_STATUS_CONNECTED; + else + return OUTPUT_STATUS_DISCONNECTED; + } + + return OUTPUT_STATUS_UNKNOWN; +} + void i830_crt_init(ScrnInfoPtr pScrn) { @@ -124,6 +285,7 @@ i830_crt_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; + pI830->output[pI830->num_outputs].detect = i830_crt_detect; /* Set up the DDC bus. */ I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, diff --git a/src/i830_display.c b/src/i830_display.c index 41f8c213..3151fd10 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -831,150 +831,3 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) pI830->output[i].pipe == 0 ? 'A' : 'B'); } } - -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. - * - * Only for I945G/GM. - */ -static Bool -i830HotplugDetectCRT(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; - const int timeout_ms = 1000; - int starttime, curtime; - - temp = INREG(PORT_HOTPLUG_EN); - - OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5)); - - for (curtime = starttime = GetTimeInMillis(); - (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis()) - { - if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0) - break; - } - - if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == - CRT_HOTPLUG_MONITOR_COLOR) - { - return TRUE; - } else { - return FALSE; - } -} - -/** - * Detects CRT presence by checking for load. - * - * Requires that the current pipe's DPLL is active. This will cause flicker - * on the CRT, so it should not be used while the display is being used. Only - * color (not monochrome) displays are detected. - */ -static Bool -i830LoadDetectCRT(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - CARD32 adpa, pipeconf; - CARD8 st00; - int pipeconf_reg, bclrpat_reg, dpll_reg; - int pipe; - - pipe = pI830->pipe; - if (pipe == 0) { - bclrpat_reg = BCLRPAT_A; - pipeconf_reg = PIPEACONF; - dpll_reg = DPLL_A; - } else { - bclrpat_reg = BCLRPAT_B; - pipeconf_reg = PIPEBCONF; - dpll_reg = DPLL_B; - } - - /* Don't try this if the DPLL isn't running. */ - if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE)) - return FALSE; - - adpa = INREG(ADPA); - - /* Enable CRT output if disabled. */ - if (!(adpa & ADPA_DAC_ENABLE)) { - OUTREG(ADPA, adpa | ADPA_DAC_ENABLE | - ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); - } - - /* Set the border color to red, green. Maybe we should save/restore this - * reg. - */ - OUTREG(bclrpat_reg, 0x00500050); - - /* Force the border color through the active region */ - pipeconf = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); - - /* Read the ST00 VGA status register */ - st00 = pI830->readStandard(pI830, 0x3c2); - - /* Restore previous settings */ - OUTREG(pipeconf_reg, pipeconf); - OUTREG(ADPA, adpa); - - if (st00 & (1 << 4)) - return TRUE; - else - return FALSE; -} - -/** - * Detects CRT presence by probing for a response on the DDC address. - * - * This takes approximately 5ms in testing on an i915GM, with CRT connected or - * not. - */ -static Bool -i830DDCDetectCRT(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - struct _I830OutputRec *output; - - output = &pI830->output[0]; - /* CRT should always be at 0, but check anyway */ - if (output->type != I830_OUTPUT_ANALOG) - return FALSE; - - return xf86I2CProbeAddress(output->pDDCBus, 0x00A0); -} - -/** - * Attempts to detect CRT presence through any method available. - * - * @param allow_disturb enables detection methods that may cause flickering - * on active displays. - */ -Bool -i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool found_ddc; - - if (IS_I945G(pI830) || IS_I945GM(pI830)) - return i830HotplugDetectCRT(pScrn); - - found_ddc = i830DDCDetectCRT(pScrn); - if (found_ddc) - return TRUE; - - /* Use the load-detect method if we're not currently outputting to the CRT, - * or we don't care. - * - * Actually, the method is unreliable currently. We need to not share a - * pipe, as it seems having other outputs on that pipe will result in a - * false positive. - */ - if (0 && (allow_disturb || !(INREG(ADPA) & !ADPA_DAC_ENABLE))) { - return i830LoadDetectCRT(pScrn); - } - - return FALSE; -} diff --git a/src/i830_display.h b/src/i830_display.h index 576a1491..8a6e9e90 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -29,7 +29,6 @@ Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); -Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index f142c4b2..2c7eca73 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1439,28 +1439,36 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { - /* Choose a default set of outputs to use based on what we've detected. */ - if (i830DetectCRT(pScrn, TRUE)) { - pI830->MonType1 |= PIPE_CRT; - } - - /* Check for attached SDVO outputs. Assume that they're flat panels for - * now. Though really, it's just a name at the moment, since we don't - * treat different SDVO outputs differently. Also, check for LVDS and - * set it to the right pipe if available. + /* Choose a default set of outputs to use based on what we've detected. + * + * Assume that SDVO outputs are flat panels for now. It's just a name + * at the moment, since we don't treat different SDVO outputs + * differently. */ for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].type == I830_OUTPUT_LVDS) - pI830->MonType2 |= PIPE_LFP; + pI830->MonType2 = PIPE_LFP; - if (pI830->output[i].type == I830_OUTPUT_SDVO) { - if (!i830_sdvo_detect_displays(pScrn, &pI830->output[i])) + if (pI830->output[i].type == I830_OUTPUT_SDVO || + pI830->output[i].type == I830_OUTPUT_ANALOG) + { + int pipetype; + + if (pI830->output[i].detect(pScrn, &pI830->output[i]) == + OUTPUT_STATUS_DISCONNECTED) + { continue; + } + + if (pI830->output[i].type == I830_OUTPUT_SDVO) + pipetype = PIPE_DFP; + else + pipetype = PIPE_CRT; if (pI830->MonType1 == PIPE_NONE) - pI830->MonType1 |= PIPE_DFP; + pI830->MonType1 |= pipetype; else if (pI830->MonType2 == PIPE_NONE) - pI830->MonType2 |= PIPE_DFP; + pI830->MonType2 |= pipetype; } } @@ -3891,22 +3899,23 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) if (!pScrn->vtSema) return 1000; - start = GetTimeInMillis(); - found_crt = i830DetectCRT(pScrn, FALSE); - finish = GetTimeInMillis(); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected CRT as %s in %dms\n", - found_crt ? "connected" : "disconnected", finish - start); - for (i = 0; i < pI830->num_outputs; i++) { - Bool found_sdvo = TRUE; + enum output_status ret; + char *result; - if (pI830->output[i].type != I830_OUTPUT_SDVO) - continue; start = GetTimeInMillis(); - found_sdvo = i830_sdvo_detect_displays(pScrn, &pI830->output[i]); + ret = pI830->output[i].detect(pScrn, &pI830->output[i]); finish = GetTimeInMillis(); + + if (ret == OUTPUT_STATUS_CONNECTED) + result = "connected"; + else if (ret == OUTPUT_STATUS_DISCONNECTED) + result = "disconnected"; + else + result = "unknown"; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Detected SDVO as %s in %dms\n", - found_sdvo ? "connected" : "disconnected", finish - start); + result, finish - start); } } #endif diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 01858f2c..ed21ecc5 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -144,6 +144,17 @@ i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, OUTREG(DVOC, dvo); } +/** + * Detect the output connection on our DVO device. + * + * Unimplemented. + */ +static enum detect_status +i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + return OUTPUT_STATUS_UNKNOWN; +} + static Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv) @@ -189,6 +200,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) pI830->output[i].mode_valid = i830_dvo_mode_valid; pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode; pI830->output[i].post_set_mode = i830_dvo_post_set_mode; + pI830->output[i].detect = i830_dvo_detect; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 5b039b8e..e0e471ff 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -31,6 +31,7 @@ #include "xf86.h" #include "i830.h" +#include "i830_bios.h" /** * Sets the power state for the panel. @@ -176,6 +177,18 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, i830SetLVDSPanelPower(pScrn, TRUE); } +/** + * Detect the LVDS connection. + * + * This always returns OUTPUT_STATUS_CONNECTED. This output should only have + * been set up if the LVDS was actually connected anyway. + */ +static enum detect_status +i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + return OUTPUT_STATUS_CONNECTED; +} + void i830_lvds_init(ScrnInfoPtr pScrn) { @@ -221,6 +234,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; + pI830->output[pI830->num_outputs].detect = i830_lvds_detect; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index 633ac832..130b7fe5 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -803,17 +803,18 @@ I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) * is plugged in, then assume that it is. */ if (pI830->pipeMon[pipe] == NULL) { + enum detect_status detect; + + detect = pI830->output[output_index].detect(pScrn, + &pI830->output[output_index]); + switch (pI830->output[output_index].type) { case I830_OUTPUT_SDVO: - if (i830_sdvo_detect_displays(pScrn, &pI830->output[output_index])) + if (detect == OUTPUT_STATUS_CONNECTED) pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); break; case I830_OUTPUT_ANALOG: - /* Do a disruptive detect if necessary, since we want to be sure we - * know if a monitor is attached, and this detect process should be - * infrequent. - */ - if (i830DetectCRT(pScrn, TRUE)) { + if (detect == OUTPUT_STATUS_CONNECTED) { /* if (pipe == pI830->pipe) pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); else */ diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index d3f509e5..3932ea65 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -904,8 +904,8 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) * * Takes 14ms on average on my i945G. */ -Bool -i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output) +static enum detect_status +i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output) { CARD8 response[2]; CARD8 status; @@ -914,9 +914,12 @@ i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output) status = i830_sdvo_read_response(output, &response, 2); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return OUTPUT_STATUS_UNKNOWN; - return (response[0] != 0 || response[1] != 0); + if (response[0] != 0 || response[1] != 0) + return OUTPUT_STATUS_CONNECTED; + else + return OUTPUT_STATUS_DISCONNECTED; } void @@ -936,6 +939,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) output->mode_valid = i830_sdvo_mode_valid; output->pre_set_mode = i830_sdvo_pre_set_mode; output->post_set_mode = i830_sdvo_post_set_mode; + output->detect = i830_sdvo_detect; /* While it's the same bus, we just initialize a new copy to avoid trouble * with tracking refcounting ourselves, since the XFree86 DDX bits don't. diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index b1d86b41..1368e43b 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -31,8 +31,5 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device); int i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode); -Bool -i830_sdvo_detect_displays(ScrnInfoPtr pScrn, I830OutputPtr output); - void i830_sdvo_dump(ScrnInfoPtr pScrn); diff --git a/src/i830_tv.c b/src/i830_tv.c index 2adbe91b..3e728822 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -405,6 +405,18 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, OUTREG(TV_CTL, tv_ctl); } +/** + * Detect the TV connection. + * + * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure + * we have a pipe programmed in order to probe the TV. + */ +static enum detect_status +i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + return OUTPUT_STATUS_UNKNOWN; +} + void i830_tv_init(ScrnInfoPtr pScrn) { @@ -425,6 +437,7 @@ i830_tv_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid; pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode; + pI830->output[pI830->num_outputs].detect = i830_tv_detect; pI830->num_outputs++; } From a71f283650e8cb7b760e5a53c4db79202c4cc5c4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 14:46:23 -0800 Subject: [PATCH 203/257] Connect output detection up to RandR. --- src/i830_randr.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index f64f3dab..23ffaf6c 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -763,11 +763,17 @@ I830RandRSetInfo12 (ScreenPtr pScreen) xfree (rrmodes); - connection = RR_Disconnected; - if (pipe >= 0) - connection = RR_Connected; - - RROutputSetConnection (randrp->outputs[i], connection); + switch (pI830->output[i].detect(pScrn, &pI830->output[i])) { + case OUTPUT_STATUS_CONNECTED: + RROutputSetConnection (randrp->outputs[i], RR_Connected); + break; + case OUTPUT_STATUS_DISCONNECTED: + RROutputSetConnection (randrp->outputs[i], RR_Disconnected); + break; + case OUTPUT_STATUS_UNKNOWN: + RROutputSetConnection (randrp->outputs[i], RR_UnknownConnection); + break; + } RROutputSetSubpixelOrder (randrp->outputs[i], subpixel); From cc3728be2481637dda321d3bc2e4e89a220699cd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 15:00:36 -0800 Subject: [PATCH 204/257] Add compat definitions for M_T_PREFERRED and M_T_DRIVER for older X Servers. --- src/i830.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/i830.h b/src/i830.h index b962e88c..27a9817b 100644 --- a/src/i830.h +++ b/src/i830.h @@ -724,4 +724,12 @@ void i830_tv_init(ScrnInfoPtr pScrn); #define _845_DRAM_RW_CONTROL 0x90 #define DRAM_WRITE 0x33330000 +/* Compat definitions for older X Servers. */ +#ifndef M_T_PREFERRED +#define M_T_PREFERRED 0x08 +#endif +#ifndef M_T_DRIVER +#define M_T_DRIVER 0x40 +#endif + #endif /* _I830_H_ */ From 7195dfabd56239f08cdd8175a2ef3a66ef9600de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 31 Oct 2006 17:10:08 -0800 Subject: [PATCH 205/257] Give each output a get_modes function and expose those modes through RandR. The get_modes should return the probed modes only. The driver should then append to the list (for example, compatible modes listed in other outputs, or standard VESA modes) to create the list to expose through RandR. That isn't done yet. --- src/i830.h | 15 +++++++++ src/i830_crt.c | 1 + src/i830_dvo.c | 1 + src/i830_lvds.c | 5 +++ src/i830_modes.c | 33 +++++++++++++++++++- src/i830_randr.c | 80 +++++++++++++++++++++++++----------------------- src/i830_sdvo.c | 1 + src/i830_tv.c | 13 ++++++++ 8 files changed, 110 insertions(+), 39 deletions(-) diff --git a/src/i830.h b/src/i830.h index 27a9817b..5915a178 100644 --- a/src/i830.h +++ b/src/i830.h @@ -269,6 +269,20 @@ struct _I830OutputRec { */ enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output); + /** + * Query the device for the modes it provides. + * + * \return singly-linked list of modes or NULL if no modes found. + */ + DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output); + + /** + * List of available modes on this output. + * + * This should be the list from get_modes(), plus perhaps additional + * compatible modes added later. + */ + DisplayModePtr probed_modes; xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; @@ -680,6 +694,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, /* i830_modes.c */ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); +DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output); /* i830_randr.c */ Bool I830RandRCreateScreenResources (ScreenPtr pScreen); diff --git a/src/i830_crt.c b/src/i830_crt.c index d271eedb..bd0099ac 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -286,6 +286,7 @@ i830_crt_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; pI830->output[pI830->num_outputs].detect = i830_crt_detect; + pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes; /* Set up the DDC bus. */ I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, diff --git a/src/i830_dvo.c b/src/i830_dvo.c index ed21ecc5..c788e4f4 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -201,6 +201,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode; pI830->output[i].post_set_mode = i830_dvo_post_set_mode; pI830->output[i].detect = i830_dvo_detect; + pI830->output[i].get_modes = i830_ddc_get_modes; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index e0e471ff..4b899033 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -235,6 +235,11 @@ i830_lvds_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; pI830->output[pI830->num_outputs].detect = i830_lvds_detect; + /* This will usually return NULL on laptop panels, which is no good. + * We need to construct a mode from the fixed panel info, and return a copy + * of that when DDC is unavailable. + */ + pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index 130b7fe5..1ba1defb 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -933,11 +933,22 @@ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) { I830Ptr pI830 = I830PTR(pScrn); - int pipe; + int pipe, i; DisplayModePtr saved_mode, last; Bool pipes_reconfigured = FALSE; int originalVirtualX, originalVirtualY; + /* Re-probe the list of modes for each output. */ + for (i = 0; i < pI830->num_outputs; i++) { + while (pI830->output[i].probed_modes != NULL) { + xf86DeleteMode(&pI830->output[i].probed_modes, + pI830->output[i].probed_modes); + } + + pI830->output[i].probed_modes = + pI830->output[i].get_modes(pScrn, &pI830->output[i]); + } + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { I830ReprobePipeModeList(pScrn, pipe); } @@ -1099,3 +1110,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) return 1; /* XXX */ } + +/** + * Generic get_modes function using DDC, used by many outputs. + */ +DisplayModePtr +i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + xf86MonPtr ddc_mon; + DisplayModePtr ddc_modes; + + ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus); + if (ddc_mon == NULL) + return NULL; + + ddc_modes = i830GetDDCModes(pScrn, ddc_mon); + + xfree(ddc_mon); + + return ddc_modes; +} diff --git a/src/i830_randr.c b/src/i830_randr.c index 23ffaf6c..a1c4b12c 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -612,7 +612,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int p; int clone_types; int crtc_types; - int connection; int pipe_type; int pipe; int subpixel; @@ -631,6 +630,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen) randrp->virtualX, randrp->virtualY); for (i = 0; i < pI830->num_outputs; i++) { + MonPtr mon; + output = &pI830->output[i]; /* * Valid crtcs @@ -705,50 +706,53 @@ I830RandRSetInfo12 (ScreenPtr pScreen) nmode = 0; npreferred = 0; rrmodes = NULL; - if (pipe >= 0) - { - MonPtr mon = pI830->pipeMon[pipe]; - modes = mon->Modes; - for (mode = modes; mode; mode = mode->next) - nmode++; + modes = pI830->output[i].probed_modes; - if (nmode) - { - rrmodes = xalloc (nmode * sizeof (RRModePtr)); - if (!rrmodes) - return FALSE; - nmode = 0; - for (p = 1; p >= 0; p--) - { - for (mode = modes; mode; mode = mode->next) - { - if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) - { - modeInfo.nameLength = strlen (mode->name); + if (pI830->output[i].pipe >= 0) + mon = pI830->pipeMon[pipe]; + else + mon = NULL; + + for (mode = modes; mode; mode = mode->next) + nmode++; + + if (nmode) { + rrmodes = xalloc (nmode * sizeof (RRModePtr)); + if (!rrmodes) + return FALSE; + nmode = 0; + + for (p = 1; p >= 0; p--) { + for (mode = modes; mode; mode = mode->next) { + if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) { + modeInfo.nameLength = strlen (mode->name); + if (mon != NULL) { modeInfo.mmWidth = mon->widthmm; modeInfo.mmHeight = mon->heightmm; + } else { + modeInfo.mmWidth = 0; + modeInfo.mmHeight = 0; + } - modeInfo.width = mode->HDisplay; - modeInfo.dotClock = mode->Clock * 1000; - modeInfo.hSyncStart = mode->HSyncStart; - modeInfo.hSyncEnd = mode->HSyncEnd; - modeInfo.hTotal = mode->HTotal; - modeInfo.hSkew = mode->HSkew; + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; - modeInfo.height = mode->VDisplay; - modeInfo.vSyncStart = mode->VSyncStart; - modeInfo.vSyncEnd = mode->VSyncEnd; - modeInfo.vTotal = mode->VTotal; - modeInfo.modeFlags = mode->Flags; + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; - rrmode = RRModeGet (pScreen, &modeInfo, mode->name); - rrmode->devPrivate = mode; - if (rrmode) - { - rrmodes[nmode++] = rrmode; - npreferred += p; - } + rrmode = RRModeGet (pScreen, &modeInfo, mode->name); + rrmode->devPrivate = mode; + if (rrmode) { + rrmodes[nmode++] = rrmode; + npreferred += p; } } } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 3932ea65..b6a3d676 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -940,6 +940,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) output->pre_set_mode = i830_sdvo_pre_set_mode; output->post_set_mode = i830_sdvo_post_set_mode; output->detect = i830_sdvo_detect; + output->get_modes = i830_ddc_get_modes; /* While it's the same bus, we just initialize a new copy to avoid trouble * with tracking refcounting ourselves, since the XFree86 DDX bits don't. diff --git a/src/i830_tv.c b/src/i830_tv.c index 3e728822..47c0d03b 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -417,6 +417,18 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) return OUTPUT_STATUS_UNKNOWN; } +/** + * Stub get_modes function. + * + * This should probably return a set of fixed modes, unless we can figure out + * how to probe modes off of TV connections. + */ +DisplayModePtr +i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + return NULL; +} + void i830_tv_init(ScrnInfoPtr pScrn) { @@ -438,6 +450,7 @@ i830_tv_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode; pI830->output[pI830->num_outputs].detect = i830_tv_detect; + pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes; pI830->num_outputs++; } From f30d7f912f36b110c3af7dc795e35456593781ab Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Nov 2006 11:50:51 -0800 Subject: [PATCH 206/257] Update for the move of RandR phyiscal size information. --- src/i830_randr.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index a1c4b12c..f8064b91 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -723,17 +723,15 @@ I830RandRSetInfo12 (ScreenPtr pScreen) return FALSE; nmode = 0; + /* We should pull info out of EDID to get the output physical + * size when available. + */ + RROutputSetPhysicalSize(randrp->outputs[i], 0, 0); + for (p = 1; p >= 0; p--) { for (mode = modes; mode; mode = mode->next) { if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) { modeInfo.nameLength = strlen (mode->name); - if (mon != NULL) { - modeInfo.mmWidth = mon->widthmm; - modeInfo.mmHeight = mon->heightmm; - } else { - modeInfo.mmWidth = 0; - modeInfo.mmHeight = 0; - } modeInfo.width = mode->HDisplay; modeInfo.dotClock = mode->Clock * 1000; From fb94c1210966f7875e5f034f10ea31c06c502c3a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Nov 2006 12:23:50 -0800 Subject: [PATCH 207/257] Move mode lists from per-pipe to per-output. This should let RandR do the right thing in exposing the modes to userland. As a side effect of getting this working, the SDVO pixel clock range code was fixed and the mode valid tests for various outputs got extended. Also, LVDS grew a get_modes for the fixed panel mode. Note that we now no longer do automatic enabling of outputs at xrandr -s 0, hotkey, or VT switch. That will be left to generic RandR code later. Also, generic modes and user-defined modes are once again not validated into the lists, so this is a regression there. --- src/i830.h | 2 +- src/i830_crt.c | 41 ++- src/i830_display.c | 25 +- src/i830_driver.c | 64 ---- src/i830_dvo.c | 5 + src/i830_lvds.c | 39 ++- src/i830_modes.c | 766 +++++++++---------------------------------- src/i830_randr.c | 19 +- src/i830_sdvo.c | 22 +- src/i830_tv.c | 2 +- src/i830_xf86Modes.c | 53 +++ src/i830_xf86Modes.h | 6 + 12 files changed, 332 insertions(+), 712 deletions(-) diff --git a/src/i830.h b/src/i830.h index 5915a178..a4dc4ba1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -485,7 +485,6 @@ typedef struct _I830Rec { int availablePipes; /* [0] is display plane A, [1] is display plane B. */ int planeEnabled[MAX_DISPLAY_PIPES]; - MonPtr pipeMon[MAX_DISPLAY_PIPES]; DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ @@ -694,6 +693,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, /* i830_modes.c */ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); +void i830_reprobe_output_modes(ScrnInfoPtr pScrn); DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output); /* i830_randr.c */ diff --git a/src/i830_crt.c b/src/i830_crt.c index bd0099ac..407ebe3d 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -31,7 +31,7 @@ #include "xf86.h" #include "i830.h" - +#include "i830_xf86Modes.h" static void i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { @@ -80,6 +80,12 @@ static int i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) { + if (pMode->Flags & V_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (pMode->Clock > 400000 || pMode->Clock < 25000) + return MODE_CLOCK_RANGE; + return MODE_OK; } @@ -273,6 +279,37 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output) return OUTPUT_STATUS_UNKNOWN; } +static DisplayModePtr +i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + DisplayModePtr modes; + MonRec fixed_mon; + + modes = i830_ddc_get_modes(pScrn, output); + if (modes != NULL) + return modes; + + if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED) + return NULL; + + /* We've got a potentially-connected monitor that we can't DDC. Return a + * fixed set of VESA plus user modes for a presumed multisync monitor with + * some reasonable limits. + */ + fixed_mon.nHsync = 1; + fixed_mon.hsync[0].lo = 31.0; + fixed_mon.hsync[0].hi = 100.0; + fixed_mon.nVrefresh = 1; + fixed_mon.vrefresh[0].lo = 50.0; + fixed_mon.vrefresh[0].hi = 70.0; + + modes = i830xf86DuplicateModes(pScrn, pScrn->monitor->Modes); + i830xf86ValidateModesSync(pScrn, modes, &fixed_mon); + i830xf86PruneInvalidModes(pScrn, &modes, TRUE); + + return modes; +} + void i830_crt_init(ScrnInfoPtr pScrn) { @@ -286,7 +323,7 @@ i830_crt_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; pI830->output[pI830->num_outputs].detect = i830_crt_detect; - pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes; + pI830->output[pI830->num_outputs].get_modes = i830_crt_get_modes; /* Set up the DDC bus. */ I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, diff --git a/src/i830_display.c b/src/i830_display.c index 3151fd10..b3019f80 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -260,8 +260,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) } /** - * In the current world order, there is a list of per-pipe modes, which may or - * may not include the mode that was asked to be set by XFree86's mode + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode * selection. Find the closest one, in the following preference order: * * - Equality @@ -272,21 +272,32 @@ static DisplayModePtr i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr pBest = NULL, pScan; + DisplayModePtr pBest = NULL, pScan = NULL; + int i; + + /* Assume that there's only one output connected to the given CRTC. */ + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].pipe == pipe && + !pI830->output[i].disabled && + pI830->output[i].probed_modes != NULL) + { + pScan = pI830->output[i].probed_modes; + } + } /* If the pipe doesn't have any detected modes, just let the system try to * spam the desired mode in. */ - if (pI830->pipeMon[pipe] == NULL) { + if (pScan == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No pipe mode list for pipe %d," "continuing with desired mode\n", pipe); return pMode; } - assert(pScan->VRefresh != 0.0); - for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL; - pScan = pScan->next) { + for (; pScan != NULL; pScan = pScan->next) { + assert(pScan->VRefresh != 0.0); + /* If there's an exact match, we're done. */ if (I830ModesEqual(pScan, pMode)) { pBest = pMode; diff --git a/src/i830_driver.c b/src/i830_driver.c index 2c7eca73..7c151747 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -787,55 +787,6 @@ I830PreInitDDC(ScrnInfoPtr pScrn) } } -static void -I830DetectMonitors(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - - if (!pI830->ddc2) - return; - - for (i=0; inum_outputs; i++) { - switch (pI830->output[i].type) { - case I830_OUTPUT_ANALOG: - case I830_OUTPUT_LVDS: - /* for an analog/LVDS output, just do DDC */ - pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[i].pDDCBus); - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n", - i830_output_type_names[pI830->output[i].type], i, - pI830->output[i].pDDCBus->DriverPrivate.uval); - xf86PrintEDID(pI830->output[i].MonInfo); - break; - case I830_OUTPUT_DVO: - /* check for DDC */ - pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[i].pDDCBus); - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i, - pI830->output[i].pDDCBus->DriverPrivate.uval); - xf86PrintEDID(pI830->output[i].MonInfo); - break; - case I830_OUTPUT_SDVO: - pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, - pI830->output[i].pDDCBus); - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i, - pI830->output[i].pDDCBus->DriverPrivate.uval); - xf86PrintEDID(pI830->output[i].MonInfo); - break; - case I830_OUTPUT_UNUSED: - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Unknown or unhandled output device at %d\n", i); - break; - } - } -} - static void PreInitCleanup(ScrnInfoPtr pScrn) { @@ -1333,21 +1284,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830PreInitDDC(pScrn); - I830DetectMonitors(pScrn); - - /* Walk from the end so we'll happen to hit SDVO first, if we found some. An - * SDVO device is probably a DFP, and so probably pickier than (say) a CRT - * that we might find early in the list. This hackery will go away when we - * start doing independent per-head mode selection. - */ - for (i = pI830->num_outputs - 1; i >= 0; i--) { - if (pI830->output[i].MonInfo) { - pScrn->monitor->DDC = pI830->output[i].MonInfo; - xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); - break; - } - } - pI830->MonType1 = PIPE_NONE; pI830->MonType2 = PIPE_NONE; pI830->specifiedMonitor = FALSE; diff --git a/src/i830_dvo.c b/src/i830_dvo.c index c788e4f4..31fb76ba 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -96,6 +96,11 @@ static int i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) { + if (pMode->Flags & V_DBLSCAN) + return MODE_NO_DBLESCAN; + + /* XXX: Validate clock range */ + if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode)) return MODE_OK; else diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 4b899033..7b9fe634 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -189,6 +189,39 @@ i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output) return OUTPUT_STATUS_CONNECTED; } +/** + * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. + */ +static DisplayModePtr +i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr modes, new; + char stmp[32]; + + modes = i830_ddc_get_modes(pScrn, output); + if (modes != NULL) + return modes; + + new = xnfcalloc(1, sizeof (DisplayModeRec)); + sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); + new->name = xnfalloc(strlen(stmp) + 1); + strcpy(new->name, stmp); + new->HDisplay = pI830->PanelXRes; + new->VDisplay = pI830->PanelYRes; + new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; + new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth; + new->HTotal = new->HSyncEnd + 1; + new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; + new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth; + new->VTotal = new->VSyncEnd + 1; + new->Clock = pI830->panel_fixed_clock; + + new->type = M_T_PREFERRED; + + return new; +} + void i830_lvds_init(ScrnInfoPtr pScrn) { @@ -235,11 +268,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; pI830->output[pI830->num_outputs].detect = i830_lvds_detect; - /* This will usually return NULL on laptop panels, which is no good. - * We need to construct a mode from the fixed panel info, and return a copy - * of that when DDC is unavailable. - */ - pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes; + pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index 1ba1defb..d6866ad8 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -162,27 +162,6 @@ I830PrintModes(ScrnInfoPtr scrp) } while (p != NULL && p != scrp->modes); } -/** - * Allocates and returns a copy of pMode, including pointers within pMode. - */ -static DisplayModePtr -I830DuplicateMode(DisplayModePtr pMode) -{ - DisplayModePtr pNew; - - pNew = xnfalloc(sizeof(DisplayModeRec)); - *pNew = *pMode; - pNew->next = NULL; - pNew->prev = NULL; - if (pNew->name == NULL) { - i830xf86SetModeDefaultName(pMode); - } else { - pNew->name = xnfstrdup(pMode->name); - } - - return pNew; -} - /* This function will sort all modes according to their resolution. * Highest resolution first. */ @@ -244,7 +223,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr pScrn, int i) pMode->VDisplay == est_timings[i].vsize && fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0) { - DisplayModePtr pNew = I830DuplicateMode(pMode); + DisplayModePtr pNew = i830xf86DuplicateMode(pMode); i830xf86SetModeDefaultName(pNew); pNew->VRefresh = i830xf86ModeVRefresh(pMode); return pNew; @@ -391,141 +370,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) return first; } -/** - * This function returns a default mode for flat panels using the timing - * information provided by the BIOS. - */ -static DisplayModePtr -i830FPNativeMode(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr new; - char stmp[32]; - - if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0) - return NULL; - - /* Add native panel size */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - new->HDisplay = pI830->PanelXRes; - new->VDisplay = pI830->PanelYRes; - new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff; - new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth; - new->HTotal = new->HSyncEnd + 1; - new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff; - new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth; - new->VTotal = new->VSyncEnd + 1; - new->Clock = pI830->panel_fixed_clock; - - new->type = M_T_PREFERRED; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No valid mode specified, force to native mode\n"); - - return new; -} - -/** - * FP automatic modelist creation routine for using panel fitting. - * - * Constructs modes for any resolution less than the panel size specified by the - * user, with the user flag set, plus standard VESA mode sizes without the user - * flag set (for randr). - * - * Modes will be faked to use GTF parameters, even though at the time of being - * programmed into the LVDS they'll end up being forced to the panel's fixed - * mode. - * - * \return doubly-linked list of modes. - */ -static DisplayModePtr -i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr last = NULL; - DisplayModePtr new = NULL; - DisplayModePtr first = NULL; - DisplayModePtr p, tmp; - int count = 0; - int i, width, height; - - /* We have a flat panel connected to the primary display, and we - * don't have any DDC info. - */ - for (i = 0; ppModeName[i] != NULL; i++) { - - if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) - continue; - - /* Note: We allow all non-standard modes as long as they do not - * exceed the native resolution of the panel. Since these modes - * need the internal RMX unit in the video chips (and there is - * only one per card), this will only apply to the primary head. - */ - if (width < 320 || width > pI830->PanelXRes || - height < 200 || height > pI830->PanelYRes) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", - ppModeName[i]); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Valid modes must be between 320x200-%dx%d\n", - pI830->PanelXRes, pI830->PanelYRes); - continue; - } - - new = i830GetGTF(width, height, 60.0, FALSE, FALSE); - new->type |= M_T_DEFAULT; - - new->next = NULL; - new->prev = last; - - if (last) - last->next = new; - last = new; - if (!first) - first = new; - - count++; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid mode using panel fitting: %s\n", new->name); - } - - /* If the user hasn't specified modes, add the native mode */ - if (!count) { - new = i830FPNativeMode(pScrn); - if (new) { - I830xf86SortModes(new, &first, &last); - count = 1; - } - } - - /* add in all default vesa modes smaller than panel size, used for randr */ - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) { - tmp = first; - while (tmp) { - if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; - tmp = tmp->next; - } - if (!tmp) { - new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE); - new->type |= M_T_DEFAULT; - - I830xf86SortModes(new, &first, &last); - - count++; - } - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total number of valid FP mode(s) found: %d\n", count); - - return first; -} - static DisplayModePtr i830GetModeListTail(DisplayModePtr pModeList) { @@ -561,330 +405,6 @@ i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, } } -/** - * Duplicates every mode in the given list and returns a pointer to the first - * mode. - * - * \param modeList doubly-linked mode list - */ -static DisplayModePtr -i830DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) -{ - DisplayModePtr first = NULL, last = NULL; - DisplayModePtr mode; - - for (mode = modeList; mode != NULL; mode = mode->next) { - DisplayModePtr new; - - new = I830DuplicateMode(mode); - - /* Insert pNew into modeList */ - if (last) { - last->next = new; - new->prev = last; - } else { - first = new; - new->prev = NULL; - } - new->next = NULL; - last = new; - } - - return first; -} - -static MonPtr -i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus) -{ - xf86MonPtr ddc; - MonPtr mon; - DisplayModePtr userModes; - int i; - - ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus); - - if (ddc == NULL) - return NULL; - - mon = xnfcalloc(1, sizeof(*mon)); - mon->Modes = i830GetDDCModes(pScrn, ddc); - mon->DDC = ddc; - - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &ddc->det_mon[i]; - - switch (ddc->det_mon[i].type) { - case DS_RANGES: - mon->hsync[mon->nHsync].lo = det_mon->section.ranges.min_h; - mon->hsync[mon->nHsync].hi = det_mon->section.ranges.max_h; - mon->nHsync++; - mon->vrefresh[mon->nVrefresh].lo = det_mon->section.ranges.min_v; - mon->vrefresh[mon->nVrefresh].hi = det_mon->section.ranges.max_v; - mon->nVrefresh++; - break; - default: - /* We probably don't care about trying to contruct ranges around - * modes specified by DDC. - */ - break; - } - } - - /* Add in VESA standard and user modelines, and do additional validation - * on them beyond what pipe config will do (x/y/pitch, clocks, flags) - */ - userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); - - i830xf86ValidateModesSync(pScrn, userModes, mon); - i830xf86PruneInvalidModes(pScrn, &userModes, TRUE); - - i830AppendModes(pScrn, &mon->Modes, userModes); - - mon->Last = i830GetModeListTail(mon->Modes); - - return mon; -} - -static MonPtr -i830GetLVDSMonitor(ScrnInfoPtr pScrn) -{ - MonPtr mon; - DisplayModePtr mode; - - mon = xnfcalloc(1, sizeof(*mon)); - mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes); - mon->Last = i830GetModeListTail(mon->Modes); - /* - * Find the preferred mode, use the display resolution to compute - * the effective monitor size - */ - for (mode = mon->Modes; mode; mode = mode->next) - if (mode->type & M_T_PREFERRED) - break; - if (!mode) - mode = mon->Modes; - if (mode) - { -#define MMPERINCH 25.4 - mon->widthmm = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH; - mon->heightmm = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH; - } - - return mon; -} - -static MonPtr -i830GetConfiguredMonitor(ScrnInfoPtr pScrn) -{ - MonPtr mon; - - mon = xnfcalloc(1, sizeof(*mon)); - memcpy(mon, pScrn->monitor, sizeof(*mon)); - - if (pScrn->monitor->id != NULL) - mon->id = xnfstrdup(pScrn->monitor->id); - if (pScrn->monitor->vendor != NULL) - mon->vendor = xnfstrdup(pScrn->monitor->vendor); - if (pScrn->monitor->model != NULL) - mon->model = xnfstrdup(pScrn->monitor->model); - - /* Use VESA standard and user modelines, and do additional validation - * on them beyond what pipe config will do (x/y/pitch, clocks, flags) - */ - mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); - i830xf86ValidateModesSync(pScrn, mon->Modes, mon); - i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE); - mon->Last = i830GetModeListTail(mon->Modes); - - return mon; -} - -static MonPtr -i830GetDefaultMonitor(ScrnInfoPtr pScrn) -{ - MonPtr mon; - - mon = xnfcalloc(1, sizeof(*mon)); - - mon->id = xnfstrdup("Unknown Id"); - mon->vendor = xnfstrdup("Unknown Vendor"); - mon->model = xnfstrdup("Unknown Model"); - - mon->nHsync = 1; - mon->hsync[0].lo = 31.0; - mon->hsync[0].hi = 100.0; - mon->nVrefresh = 1; - mon->vrefresh[0].lo = 50.0; - mon->vrefresh[0].hi = 70.0; - mon->widthmm = 400; - mon->heightmm = 300; - /* Use VESA standard and user modelines, and do additional validation - * on them beyond what pipe config will do (x/y/pitch, clocks, flags) - */ - mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes); - i830xf86ValidateModesSync(pScrn, mon->Modes, mon); - i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE); - mon->Last = i830GetModeListTail(mon->Modes); - - return mon; -} - -static void -i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon) -{ - while (mon->Modes != NULL) - xf86DeleteMode(&mon->Modes, mon->Modes); - xfree(mon->id); - xfree(mon->vendor); - xfree(mon->model); - xfree(mon->DDC); - xfree(mon); -} - -/** - * Performs probing of modes available on the output connected to the given - * pipe. - * - * We do not support multiple outputs per pipe (since the cases for that are - * sufficiently rare we can't imagine the complexity being worth it), so - * the pipe is a sufficient specifier. - */ -static void -I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe) -{ - I830Ptr pI830 = I830PTR(pScrn); - int output_index = -1; - int i; - int outputs; - DisplayModePtr pMode; - MonPtr old_mon = pI830->pipeMon[pipe]; - - if (pipe == 0) - outputs = pI830->operatingDevices & 0xff; - else - outputs = (pI830->operatingDevices >> 8) & 0xff; - - for (i = 0; i < pI830->num_outputs; i++) { - switch (pI830->output[i].type) { - case I830_OUTPUT_ANALOG: - if (outputs & PIPE_CRT) { - output_index = i; - } - break; - case I830_OUTPUT_LVDS: - if (outputs & PIPE_LFP) { - output_index = i; - } - break; - case I830_OUTPUT_DVO: - if (outputs & PIPE_DFP) { - output_index = i; - } - break; - case I830_OUTPUT_SDVO: - if (outputs & PIPE_DFP) { - output_index = i; - } - break; - } - } - /* XXX: If there's no output associated with the pipe, bail for now. */ - if (output_index == -1) - return; - - if (outputs & PIPE_LFP) { - pI830->pipeMon[pipe] = i830GetLVDSMonitor(pScrn); - } else if (pI830->output[output_index].pDDCBus != NULL) { - pI830->pipeMon[pipe] = - i830GetDDCMonitor(pScrn, pI830->output[output_index].pDDCBus); - } - /* If DDC didn't work (or the flat panel equivalent), then see if we can - * detect if a monitor is at least plugged in. If we can't tell that one - * is plugged in, then assume that it is. - */ - if (pI830->pipeMon[pipe] == NULL) { - enum detect_status detect; - - detect = pI830->output[output_index].detect(pScrn, - &pI830->output[output_index]); - - switch (pI830->output[output_index].type) { - case I830_OUTPUT_SDVO: - if (detect == OUTPUT_STATUS_CONNECTED) - pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); - break; - case I830_OUTPUT_ANALOG: - if (detect == OUTPUT_STATUS_CONNECTED) { -/* if (pipe == pI830->pipe) - pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); - else */ - pI830->pipeMon[pipe] = i830GetDefaultMonitor(pScrn); - } - break; - default: - pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn); - break; - } - } - -#ifdef DEBUG_REPROBE - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n", - pipe); -#endif - if (pI830->pipeMon[pipe] != NULL) { - int minclock, maxclock; - - switch (pI830->output[output_index].type) { - case I830_OUTPUT_SDVO: - minclock = 25000; - maxclock = 165000; - case I830_OUTPUT_LVDS: - case I830_OUTPUT_ANALOG: - default: - minclock = 25000; - maxclock = 400000; - } - - i830xf86ValidateModesFlags(pScrn, pI830->pipeMon[pipe]->Modes, - V_INTERLACE); - i830xf86ValidateModesClocks(pScrn, pI830->pipeMon[pipe]->Modes, - &minclock, &maxclock, 1); - - i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE); - - /* silently prune modes down to ones matching the user's configuration. - */ - i830xf86ValidateModesUserConfig(pScrn, pI830->pipeMon[pipe]->Modes); - i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, FALSE); - - for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL; - pMode = pMode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - pMode->VRefresh = i830xf86ModeVRefresh(pMode); - I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V); -#ifdef DEBUG_REPROBE - PrintModeline(pScrn->scrnIndex, pMode); -#endif - } - } - - if (old_mon != NULL && pI830->pipeMon[pipe] == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Failed to probe output on pipe %d, disabling output at next " - "mode switch\n", pipe); - if (pipe == 0) - pI830->operatingDevices &= ~0x00ff; - else - pI830->operatingDevices &= ~0xff00; - } - - if (old_mon != NULL) - i830FreeMonitor(pScrn, old_mon); -} - /** * This function removes a mode from a list of modes. It should probably be * moved to xf86Mode.c. @@ -918,28 +438,18 @@ I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode) mode->next->prev = mode->prev; } } - -/** - * Probes for video modes on attached otuputs, and assembles a list to insert - * into pScrn. - * - * \param first_time indicates that the memory layout has already been set up, - * so displayWidth, virtualX, and virtualY shouldn't be touched. - * - * A SetMode must follow this call in order for operatingDevices to match the - * hardware's state, in case we detect a new output device. - */ -int -I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) + +void +i830_reprobe_output_modes(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int pipe, i; - DisplayModePtr saved_mode, last; - Bool pipes_reconfigured = FALSE; - int originalVirtualX, originalVirtualY; + Bool properties_set = FALSE; + int i; /* Re-probe the list of modes for each output. */ for (i = 0; i < pI830->num_outputs; i++) { + DisplayModePtr mode; + while (pI830->output[i].probed_modes != NULL) { xf86DeleteMode(&pI830->output[i].probed_modes, pI830->output[i].probed_modes); @@ -947,103 +457,66 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) pI830->output[i].probed_modes = pI830->output[i].get_modes(pScrn, &pI830->output[i]); - } - for (pipe = 0; pipe < pI830->availablePipes; pipe++) { - I830ReprobePipeModeList(pScrn, pipe); - } - - /* If we've got a spare pipe, try to detect if a new CRT has been plugged - * in. - */ - if ((pI830->operatingDevices & (PIPE_CRT | (PIPE_CRT << 8))) == 0) { - if ((pI830->operatingDevices & 0xff) == PIPE_NONE) { - pI830->operatingDevices |= PIPE_CRT; - I830ReprobePipeModeList(pScrn, 0); - if (pI830->pipeMon[0] == NULL) { - /* No new output found. */ - pI830->operatingDevices &= ~PIPE_CRT; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Enabled new CRT on pipe A\n"); - pipes_reconfigured = TRUE; - /* Clear the current mode, so we reprogram the pipe for sure. */ - memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0])); - } - } else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) { - pI830->operatingDevices |= PIPE_CRT << 8; - I830ReprobePipeModeList(pScrn, 1); - if (pI830->pipeMon[1] == NULL) { - /* No new output found. */ - pI830->operatingDevices &= ~(PIPE_CRT << 8); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Enabled new CRT on pipe B\n"); - pipes_reconfigured = TRUE; - /* Clear the current mode, so we reprogram the pipe for sure. */ - memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1])); - } - } - } - - if ((pI830->pipeMon[0] == NULL || pI830->pipeMon[0]->Modes == NULL) && - (pI830->pipeMon[1] == NULL || pI830->pipeMon[1]->Modes == NULL)) - { - FatalError("No modes found on either pipe\n"); - } - - if (first_time) { - int maxX = -1, maxY = -1; - - /* Set up a virtual size that will cover any clone mode we'd want to set - * for either of the two pipes. + /* Set the DDC properties to whatever first output has DDC information. */ - for (pipe = 0; pipe < pI830->availablePipes; pipe++) { - MonPtr mon = pI830->pipeMon[pipe]; - DisplayModePtr mode; - - if (mon == NULL) - continue; - - for (mode = mon->Modes; mode != NULL; mode = mode->next) { - if (mode->HDisplay > maxX) - maxX = mode->HDisplay; - if (mode->VDisplay > maxY) - maxY = mode->VDisplay; - } + if (pI830->output[i].MonInfo != NULL && !properties_set) { + xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); + properties_set = TRUE; } - /* let the user specify a bigger virtual size if they like */ - if (pScrn->display->virtualX > maxX) - maxX = pScrn->display->virtualX; - if (pScrn->display->virtualY > maxY) - maxY = pScrn->display->virtualY; - pScrn->virtualX = maxX; - pScrn->virtualY = maxY; - pScrn->displayWidth = (maxX + 63) & ~63; - } - I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + if (pI830->output[i].probed_modes != NULL) { + /* silently prune modes down to ones matching the user's + * configuration. + */ + i830xf86ValidateModesUserConfig(pScrn, + pI830->output[i].probed_modes); + i830xf86PruneInvalidModes(pScrn, &pI830->output[i].probed_modes, + FALSE); + } - /* Disable modes that are larger than the virtual size we decided on - * initially. - */ - if (!first_time) { - for (pipe = 0; pipe < pI830->availablePipes; pipe++) { - MonPtr mon = pI830->pipeMon[pipe]; - DisplayModePtr mode; +#ifdef DEBUG_REPROBE + if (pI830->output[i].probed_modes != NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + i830_output_type_names[pI830->output[i].type]); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + i830_output_type_names[pI830->output[i].type]); + } +#endif + for (mode = pI830->output[i].probed_modes; mode != NULL; + mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = i830xf86ModeVRefresh(mode); + I830xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - if (mon == NULL) - continue; - - for (mode = mon->Modes; mode != NULL; mode = mode->next) - { - if (mode->HDisplay > originalVirtualX) - mode->status = MODE_VIRTUAL_X; - if (mode->VDisplay > originalVirtualY) - mode->status = MODE_VIRTUAL_Y; - } +#ifdef DEBUG_REPROBE + PrintModeline(pScrn->scrnIndex, mode); +#endif } } +} + +/** + * Constructs pScrn->modes from the output mode lists. + * + * Currently it only takes one output's mode list and stuffs it into the + * XFree86 DDX mode list while trimming it for root window size. + * + * This should be obsoleted by RandR 1.2 hopefully. + */ +static void +i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr saved_mode, last; + int originalVirtualX, originalVirtualY; + int i; /* Remove the current mode from the modelist if we're re-validating, so we * can find a new mode to map ourselves to afterwards. @@ -1057,30 +530,34 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) while (pScrn->modes != NULL) xf86DeleteMode(&pScrn->modes, pScrn->modes); - /* Set pScrn->modes to the mode list for the an arbitrary head. + /* Set pScrn->modes to the mode list for an arbitrary output. * pScrn->modes should only be used for XF86VidMode now, which we don't * care about enough to make some sort of unioned list. */ - if (pI830->pipeMon[1] != NULL) { - pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[1]->Modes); - } else { - pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[0]->Modes); - } - if (pScrn->modes == NULL) { - FatalError("No modes found\n"); + for (i = 0; i < pI830->num_outputs; i++) { + if (pI830->output[i].probed_modes != NULL) { + pScrn->modes = + i830xf86DuplicateModes(pScrn, pI830->output[i].probed_modes); + break; + } } - /* Don't let pScrn->modes have modes larger than the max root window size. - * We don't really care about the monitors having it, particularly since we - * eventually want randr to be able to move to those sizes. + I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + + /* Disable modes in the XFree86 DDX list that are larger than the current + * virtual size. */ i830xf86ValidateModesSize(pScrn, pScrn->modes, originalVirtualX, originalVirtualY, pScrn->displayWidth); - /* Strip out anything bad that we threw out for virtualX. */ + /* Strip out anything that we threw out for virtualX/Y. */ i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); + if (pScrn->modes == NULL) { + FatalError("No modes left for XFree86 DDX\n"); + } + /* For some reason, pScrn->modes is circular, unlike the other mode lists. * How great is that? */ @@ -1088,25 +565,70 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) last->next = pScrn->modes; pScrn->modes->prev = last; -#if DEBUG_REPROBE - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n"); - do { - DisplayModePtr pMode; - - for (pMode = pScrn->modes; ; pMode = pMode->next) { - PrintModeline(pScrn->scrnIndex, pMode); - if (pMode->next == pScrn->modes) - break; - } - } while (0); -#endif - /* Save a pointer to the previous current mode. We can't reset * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not * happening so we can hot-enable devices at SwitchMode. We'll notice this * case at SwitchMode and free the saved mode. */ pI830->savedCurrentMode = saved_mode; +} + +/** + * Takes the output mode lists and decides the default root window size + * and framebuffer pitch. + */ +static void +i830_set_default_screen_size(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int maxX = -1, maxY = -1; + int i; + + /* Set up a virtual size that will cover any clone mode we'd want to + * set for the currently-connected outputs. + */ + for (i = 0; i < pI830->num_outputs; i++) { + DisplayModePtr mode; + + for (mode = pI830->output[i].probed_modes; mode != NULL; + mode = mode->next) + { + if (mode->HDisplay > maxX) + maxX = mode->HDisplay; + if (mode->VDisplay > maxY) + maxY = mode->VDisplay; + } + } + /* let the user specify a bigger virtual size if they like */ + if (pScrn->display->virtualX > maxX) + maxX = pScrn->display->virtualX; + if (pScrn->display->virtualY > maxY) + maxY = pScrn->display->virtualY; + pScrn->virtualX = maxX; + pScrn->virtualY = maxY; + pScrn->displayWidth = (maxX + 63) & ~63; +} + +/** + * Probes for video modes on attached otuputs, and assembles a list to insert + * into pScrn. + * + * \param first_time indicates that the memory layout has already been set up, + * so displayWidth, virtualX, and virtualY shouldn't be touched. + * + * A SetMode must follow this call in order for operatingDevices to match the + * hardware's state, in case we detect a new output device. + */ +int +I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) +{ + i830_reprobe_output_modes(pScrn); + + if (first_time) { + i830_set_default_screen_size(pScrn); + } + + i830_set_xf86_modes_from_outputs(pScrn); return 1; /* XXX */ } @@ -1118,14 +640,32 @@ DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) { xf86MonPtr ddc_mon; - DisplayModePtr ddc_modes; + DisplayModePtr ddc_modes, mode; ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus); if (ddc_mon == NULL) return NULL; + if (output->MonInfo != NULL) + xfree(output->MonInfo); + output->MonInfo = ddc_mon; + + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", + i830_output_type_names[output->type]); + xf86PrintEDID(output->MonInfo); + ddc_modes = i830GetDDCModes(pScrn, ddc_mon); + /* Strip out any modes that can't be supported on this output. */ + for (mode = ddc_modes; mode != NULL; mode = mode->next) { + int status = output->mode_valid(pScrn, output, mode); + + if (status != MODE_OK) + mode->status = status; + } + i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE); + xfree(ddc_mon); return ddc_modes; diff --git a/src/i830_randr.c b/src/i830_randr.c index f8064b91..69063a8b 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -630,8 +630,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) randrp->virtualX, randrp->virtualY); for (i = 0; i < pI830->num_outputs; i++) { - MonPtr mon; - output = &pI830->output[i]; /* * Valid crtcs @@ -701,6 +699,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen) RROutputSetCrtc (randrp->outputs[i], crtc); + /* We should pull info out of EDID to get the output physical + * size when available. + */ + RROutputSetPhysicalSize(randrp->outputs[i], 0, 0); + RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); nmode = 0; @@ -709,11 +712,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) modes = pI830->output[i].probed_modes; - if (pI830->output[i].pipe >= 0) - mon = pI830->pipeMon[pipe]; - else - mon = NULL; - for (mode = modes; mode; mode = mode->next) nmode++; @@ -723,11 +721,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) return FALSE; nmode = 0; - /* We should pull info out of EDID to get the output physical - * size when available. - */ - RROutputSetPhysicalSize(randrp->outputs[i], 0, 0); - for (p = 1; p >= 0; p--) { for (mode = modes; mode; mode = mode->next) { if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) { @@ -806,7 +799,7 @@ I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830ValidateXF86ModeList(pScrn, FALSE); + i830_reprobe_output_modes(pScrn); return I830RandRSetInfo12 (pScreen); } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index b6a3d676..eda28579 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -66,8 +66,8 @@ struct i830_sdvo_priv { */ struct i830_sdvo_caps caps; - /** Pixel clock limitations reported by the SDVO device */ - CARD16 pixel_clock_min, pixel_clock_max; + /** Pixel clock limitations reported by the SDVO device, in kHz */ + int pixel_clock_min, pixel_clock_max; /** State for save/restore */ /** @{ */ @@ -323,9 +323,12 @@ i830_sdvo_set_active_outputs(I830OutputPtr output, return (status == SDVO_CMD_STATUS_SUCCESS); } +/** + * Returns the pixel clock range limits of the current target input in kHz. + */ static Bool -i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, - CARD16 *clock_max) +i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min, + int *clock_max) { struct i830_sdvo_pixel_clock_range clocks; CARD8 status; @@ -337,8 +340,9 @@ i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min, if (status != SDVO_CMD_STATUS_SUCCESS) return FALSE; - *clock_min = clocks.min; - *clock_max = clocks.max; + /* Convert the values from units of 10 kHz to kHz. */ + *clock_min = clocks.min * 10; + *clock_max = clocks.max * 10; return TRUE; } @@ -735,6 +739,9 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, { struct i830_sdvo_priv *dev_priv = output->dev_priv; + if (pMode->Flags & V_DBLSCAN) + return MODE_NO_DBLESCAN; + if (dev_priv->pixel_clock_min > pMode->Clock) return MODE_CLOCK_HIGH; @@ -1035,10 +1042,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SDVO device VID/DID: %02X:%02X.%02X, " + "clock range %.1fMHz - %.1fMHz, " "input 1: %c, input 2: %c, " "output 1: %c, output 2: %c\n", dev_priv->caps.vendor_id, dev_priv->caps.device_id, dev_priv->caps.device_rev_id, + dev_priv->pixel_clock_min / 1000.0, + dev_priv->pixel_clock_max / 1000.0, (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N', diff --git a/src/i830_tv.c b/src/i830_tv.c index 47c0d03b..c597db53 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -423,7 +423,7 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) * This should probably return a set of fixed modes, unless we can figure out * how to probe modes off of TV connections. */ -DisplayModePtr +static DisplayModePtr i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) { return NULL; diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 8c34053c..8e8a94c5 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -194,6 +194,59 @@ I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) } } +/** + * Allocates and returns a copy of pMode, including pointers within pMode. + */ +DisplayModePtr +i830xf86DuplicateMode(DisplayModePtr pMode) +{ + DisplayModePtr pNew; + + pNew = xnfalloc(sizeof(DisplayModeRec)); + *pNew = *pMode; + pNew->next = NULL; + pNew->prev = NULL; + if (pNew->name == NULL) { + i830xf86SetModeDefaultName(pMode); + } else { + pNew->name = xnfstrdup(pMode->name); + } + + return pNew; +} + +/** + * Duplicates every mode in the given list and returns a pointer to the first + * mode. + * + * \param modeList doubly-linked mode list + */ +DisplayModePtr +i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + DisplayModePtr first = NULL, last = NULL; + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + DisplayModePtr new; + + new = i830xf86DuplicateMode(mode); + + /* Insert pNew into modeList */ + if (last) { + last->next = new; + new->prev = last; + } else { + first = new; + new->prev = NULL; + } + new->next = NULL; + last = new; + } + + return first; +} + /** * Returns true if the given modes should program to the same timings. * diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 0cba8874..5a26c0e4 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -31,6 +31,12 @@ i830xf86ModeHSync(DisplayModePtr mode); double i830xf86ModeVRefresh(DisplayModePtr mode); +DisplayModePtr +i830xf86DuplicateMode(DisplayModePtr pMode); + +DisplayModePtr +i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); + void i830xf86SetModeDefaultName(DisplayModePtr mode); From 7971c401554c218c84a8c45335c9b31bbccfece7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Nov 2006 12:42:56 -0800 Subject: [PATCH 208/257] Attempt to pull monitor physical size information out of DDC EDID data. --- src/i830.h | 8 ++++++++ src/i830_crt.c | 1 + src/i830_modes.c | 13 ++++++++++++- src/i830_randr.c | 8 ++------ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/i830.h b/src/i830.h index a4dc4ba1..eca9396b 100644 --- a/src/i830.h +++ b/src/i830.h @@ -272,6 +272,8 @@ struct _I830OutputRec { /** * Query the device for the modes it provides. * + * This function may also update MonInfo, mm_width, and mm_height. + * * \return singly-linked list of modes or NULL if no modes found. */ DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output); @@ -283,7 +285,13 @@ struct _I830OutputRec { * compatible modes added later. */ DisplayModePtr probed_modes; + + /** EDID monitor information */ xf86MonPtr MonInfo; + + /** Physical size of the output currently attached. */ + int mm_width, mm_height; + I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; struct _I830DVODriver *i2c_drv; diff --git a/src/i830_crt.c b/src/i830_crt.c index 407ebe3d..0225727b 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "i830.h" #include "i830_xf86Modes.h" + static void i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) { diff --git a/src/i830_modes.c b/src/i830_modes.c index d6866ad8..0bb17a54 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -641,6 +641,7 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) { xf86MonPtr ddc_mon; DisplayModePtr ddc_modes, mode; + int i; ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus); if (ddc_mon == NULL) @@ -666,7 +667,17 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) } i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE); - xfree(ddc_mon); + /* Pull out a phyiscal size from a detailed timing if available. */ + for (i = 0; i < 4; i++) { + if (ddc_mon->det_mon[i].type == DT && + ddc_mon->det_mon[i].section.d_timings.h_size != 0 && + ddc_mon->det_mon[i].section.d_timings.v_size != 0) + { + output->mm_width = ddc_mon->det_mon[i].section.d_timings.h_size; + output->mm_height = ddc_mon->det_mon[i].section.d_timings.v_size; + break; + } + } return ddc_modes; } diff --git a/src/i830_randr.c b/src/i830_randr.c index 69063a8b..59ebcc08 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -698,12 +698,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen) return FALSE; RROutputSetCrtc (randrp->outputs[i], crtc); - - /* We should pull info out of EDID to get the output physical - * size when available. - */ - RROutputSetPhysicalSize(randrp->outputs[i], 0, 0); - + RROutputSetPhysicalSize(randrp->outputs[i], pI830->output[i].mm_width, + pI830->output[i].mm_height); RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); nmode = 0; From 97c3a1b2421031e41f0b2b1630fde1dc4262d264 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Nov 2006 13:04:08 -0800 Subject: [PATCH 209/257] Remove the refresh rate appended to some mode names. This gets the SDVO and CRT outputs I have to have at least 1 common mode according to RandR. --- src/i830_xf86Modes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 8e8a94c5..166f41af 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -100,8 +100,7 @@ i830xf86SetModeDefaultName(DisplayModePtr mode) if (mode->name != NULL) xfree(mode->name); - mode->name = XNFprintf("%dx%dx%.0f", mode->HDisplay, mode->VDisplay, - i830xf86ModeVRefresh(mode)); + mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay); } /* From ffbd6ca09bc2300bf967d7c248a559d85b8706e0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 1 Nov 2006 13:05:44 -0800 Subject: [PATCH 210/257] Remove dead VESARec struct. --- src/i830.h | 13 ------------- src/i830_driver.c | 7 ------- 2 files changed, 20 deletions(-) diff --git a/src/i830.h b/src/i830.h index eca9396b..a07ba8ea 100644 --- a/src/i830.h +++ b/src/i830.h @@ -106,18 +106,6 @@ typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr; #define PIPE_DFP2 1<<6 #define PIPE_LFP2 1<<7 -typedef struct _VESARec { - /* SVGA state */ - pointer state, pstate; - int statePage, stateSize, stateMode, stateRefresh; - CARD32 *savedPal; - int savedScanlinePitch; - xf86MonPtr monitor; - /* display start */ - int x, y; -} VESARec, *VESAPtr; - - typedef struct _I830Rec *I830Ptr; typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr, @@ -480,7 +468,6 @@ typedef struct _I830Rec { /* Video BIOS support. */ vbeInfoPtr pVbe; - VESAPtr vesa; Bool swfSaved; CARD32 saveSWF0; diff --git a/src/i830_driver.c b/src/i830_driver.c index 7c151747..3612af76 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -352,7 +352,6 @@ I830GetRec(ScrnInfoPtr pScrn) if (pScrn->driverPrivate) return TRUE; pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1); - pI830->vesa = xnfcalloc(sizeof(VESARec), 1); return TRUE; } @@ -360,7 +359,6 @@ static void I830FreeRec(ScrnInfoPtr pScrn) { I830Ptr pI830; - VESAPtr pVesa; if (!pScrn) return; @@ -374,11 +372,6 @@ I830FreeRec(ScrnInfoPtr pScrn) vbeFree(pI830->pVbe); } - pVesa = pI830->vesa; - if (pVesa->savedPal) - xfree(pVesa->savedPal); - xfree(pVesa); - xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } From 85e32ad2dadcce1134fcadb14ece8ff30f3925f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 11:56:12 -0800 Subject: [PATCH 211/257] ch7xxxSaveRegs receives real type instead of void * --- src/ch7xxx/ch7xxx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c index fdc96d0a..d11c3550 100644 --- a/src/ch7xxx/ch7xxx.c +++ b/src/ch7xxx/ch7xxx.c @@ -38,7 +38,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ch7xxx.h" #include "ch7xxx_reg.h" -static void ch7xxxSaveRegs(void *d); +static void ch7xxxSaveRegs(I2CDevPtr d); static CARD8 ch7xxxFreqRegs[][7] = { { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 }, @@ -243,9 +243,9 @@ static void ch7xxxPrintRegs(I2CDevPtr d) } } -static void ch7xxxSaveRegs(void *d) +static void ch7xxxSaveRegs(I2CDevPtr d) { - CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d)); + CH7xxxPtr ch7xxx = CH7PTR(d); int ret; int i; From 786ec54c4c1540f4aced63ef21d567c3b9f3282e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 11:56:50 -0800 Subject: [PATCH 212/257] Add a few more registers from the 965 spec --- src/i810_reg.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index 34e6e536..31f88859 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -739,6 +739,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define VSYNC_A 0x60014 #define PIPEASRC 0x6001c #define BCLRPAT_A 0x60020 +#define VSYNCSHIFT_A 0x60028 #define HTOTAL_B 0x61000 #define HBLANK_B 0x61004 @@ -748,6 +749,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define VSYNC_B 0x61014 #define PIPEBSRC 0x6101c #define BCLRPAT_B 0x61020 +#define VSYNCSHIFT_B 0x61028 #define PP_STATUS 0x61200 # define PP_ON (1 << 31) @@ -849,6 +851,28 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 /** @} */ +/* SDVO/UDI Multiplier/Divisor register */ +#define DPLLAMD 0x601c +#define DPLLBMD 0x6020 + +/* Hi res source UDI divider (-1), non-zeor for UDI fixed freq mode */ +# define DPLLMD_UDI_DIVIDER_HIRES_MASK (0x3f << 24) +# define DPLLMD_UDI_DIVIDER_HIRES_SHIFT 24 +# define DPLLMD_UDI_DIVIDER_VGA_MASK (0x3f << 16) +# define DPLLMD_UDI_DIVIDER_VGA_SHIFT 16 +# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_MASK (0x3f << 8) +# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_SHIFT 8 +# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_MASK (0x3f << 0) +# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_SHIFT 0 + +#define DPLL_TEST 0x606c + +#define D_STATE 0x6104 +#define DSPCLK_GATE_D 0x6200 +#define RENCLK_GATE_D1 0x6204 +#define RENCLK_GATE_D2 0x6208 +#define RAMCLK_GATE_D 0x6210 /* CRL only */ + #define BLC_PWM_CTL 0x61254 #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) @@ -856,6 +880,21 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +#define BLM_CTL 0x61260 +#define BLM_THRESHOLD_0 0x61270 +#define BLM_THRESHOLD_1 0x61274 +#define BLM_THRESHOLD_2 0x61278 +#define BLM_THRESHOLD_3 0x6127c +#define BLM_THRESHOLD_4 0x61280 +#define BLM_THRESHOLD_5 0x61284 + +#define BLM_ACCUMULATOR_0 0x61290 +#define BLM_ACCUMULATOR_1 0x61294 +#define BLM_ACCUMULATOR_2 0x61298 +#define BLM_ACCUMULATOR_3 0x6129c +#define BLM_ACCUMULATOR_4 0x612a0 +#define BLM_ACCUMULATOR_5 0x612a4 + #define FPA0 0x06040 #define FPA1 0x06044 #define FPB0 0x06048 @@ -907,6 +946,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) #define SDVOC_PRESERVE_MASK (1 << 17) +#define UDIB_SVB_SHB_CODES 0x61144 +#define UDIB_SHA_BLANK_CODES 0x61148 +#define UDIB_START_END_FILL_CODES 0x6114c + + +#define SDVOUDI 0x61150 + #define I830_HTOTAL_MASK 0xfff0000 #define I830_HACTIVE_MASK 0x7ff @@ -1554,6 +1600,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PIPEACONF_GAMMA (1<<24) #define PIPECONF_FORCE_BORDER (1<<25) +#define PIPEAGCMAXRED 0x70010 +#define PIPEAGCMAXGREEN 0x70014 +#define PIPEAGCMAXBLUE 0x70018 +#define PIPEASTAT 0x70024 + +#define DSPARB 0x70030 +#define DSPFW1 0x70034 +#define DSPFW2 0x70038 +#define DSPFW3 0x7003c +#define PIPEAFRAMEHIGH 0x70040 +#define PIPEAFRAMEPIXEL 0x70044 + + #define PIPEBCONF 0x71008 #define PIPEBCONF_ENABLE (1<<31) #define PIPEBCONF_DISABLE 0 @@ -1562,6 +1621,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PIPEBCONF_GAMMA (1<<24) #define PIPEBCONF_PALETTE 0 +#define PIPEBGCMAXRED 0x71010 +#define PIPEBGCMAXGREEN 0x71014 +#define PIPEBGCMAXBLUE 0x71018 +#define PIPEBSTAT 0x71024 +#define PIPEBFRAMEHIGH 0x71040 +#define PIPEBFRAMEPIXEL 0x71044 + #define DSPACNTR 0x70180 #define DSPBCNTR 0x71180 #define DISPLAY_PLANE_ENABLE (1<<31) From 2636d68663a02f6d9eaf36971706b67036ebf56c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 11:57:11 -0800 Subject: [PATCH 213/257] Dump more registers for debug purposes --- src/i830_debug.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 1 deletion(-) diff --git a/src/i830_debug.c b/src/i830_debug.c index a48e9f2f..802330e9 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -41,6 +41,26 @@ static struct i830SnapshotRec { char *name; CARD32 regval; } i830_snapshot[] = { + DEFINEREG(VCLK_DIVISOR_VGA0), + DEFINEREG(VCLK_DIVISOR_VGA1), + DEFINEREG(VCLK_POST_DIV), + DEFINEREG(DPLL_TEST), + DEFINEREG(D_STATE), + DEFINEREG(DSPCLK_GATE_D), + DEFINEREG(RENCLK_GATE_D1), + DEFINEREG(RENCLK_GATE_D2), +/* DEFINEREG(RAMCLK_GATE_D), CRL only */ + DEFINEREG(SDVOB), + DEFINEREG(SDVOC), +/* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */ +/* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */ + DEFINEREG(SDVOUDI), + DEFINEREG(DSPARB), + DEFINEREG(DSPFW1), + DEFINEREG(DSPFW2), + DEFINEREG(DSPFW3), + + DEFINEREG(ADPA), DEFINEREG(LVDS), DEFINEREG(DVOA), @@ -62,36 +82,46 @@ static struct i830SnapshotRec { DEFINEREG(DSPAPOS), DEFINEREG(DSPASIZE), DEFINEREG(DSPABASE), + DEFINEREG(DSPASURF), + DEFINEREG(DSPATILEOFF), DEFINEREG(PIPEACONF), DEFINEREG(PIPEASRC), DEFINEREG(FPA0), DEFINEREG(FPA1), DEFINEREG(DPLL_A), + DEFINEREG(DPLLAMD), DEFINEREG(HTOTAL_A), DEFINEREG(HBLANK_A), DEFINEREG(HSYNC_A), DEFINEREG(VTOTAL_A), DEFINEREG(VBLANK_A), DEFINEREG(VSYNC_A), + DEFINEREG(BCLRPAT_A), + DEFINEREG(VSYNCSHIFT_A), DEFINEREG(DSPBCNTR), DEFINEREG(DSPBSTRIDE), DEFINEREG(DSPBPOS), DEFINEREG(DSPBSIZE), DEFINEREG(DSPBBASE), + DEFINEREG(DSPBSURF), + DEFINEREG(DSPBTILEOFF), DEFINEREG(PIPEBCONF), DEFINEREG(PIPEBSRC), DEFINEREG(FPB0), DEFINEREG(FPB1), DEFINEREG(DPLL_B), + DEFINEREG(DPLLBMD), DEFINEREG(HTOTAL_B), DEFINEREG(HBLANK_B), DEFINEREG(HSYNC_B), DEFINEREG(VTOTAL_B), DEFINEREG(VBLANK_B), DEFINEREG(VSYNC_B), + DEFINEREG(BCLRPAT_B), + DEFINEREG(VSYNCSHIFT_B), DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), @@ -129,13 +159,115 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn) } } +static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = min; i <= max; i++) { + OUTREG8 (id, i); + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%18.18s%02x: 0x%02x\n", + name, i, INREG8(val)); + } +} + void i830DumpRegs (ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int i; + int fp, dpll; + int pipe; + int n, m1, m2, m, p1, p2; + int ref; + int dot; + int phase; + int msr; + int crt; + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsBegin\n"); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%10.10s: 0x%08x\n", + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%08x\n", i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg)); } + i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7); + msr = INREG8(0x3cc); + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%02x\n", + "MSR", (unsigned int) msr); + + if (msr & 1) + crt = 0x3d0; + else + crt = 0x3b0; + i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24); + for (pipe = 0; pipe <= 1; pipe++) + { + fp = INREG(pipe == 0 ? FPA0 : FPB0); + dpll = INREG(pipe == 0 ? DPLL_A : DPLL_B); + switch ((dpll >> 24) & 0x3) { + case 0: + p2 = 10; + break; + case 1: + p2 = 5; + break; + default: + p2 = 1; + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p2 out of range\n"); + break; + } + switch ((dpll >> 16) & 0xff) { + case 1: + p1 = 1; break; + case 2: + p1 = 2; break; + case 4: + p1 = 3; break; + case 8: + p1 = 4; break; + case 16: + p1 = 5; break; + case 32: + p1 = 6; break; + case 64: + p1 = 7; break; + case 128: + p1 = 8; break; + default: + p1 = 1; + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p1 out of range\n"); + break; + } + switch ((dpll >> 13) & 0x3) { + case 0: + ref = 96000; + break; + default: + ref = 0; + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "ref out of range\n"); + break; + } + phase = (dpll >> 9) & 0xf; + switch (phase) { + case 6: + break; + default: + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "phase %d out of range\n", phase); + break; + } + switch ((dpll >> 8) & 1) { + case 0: + break; + default: + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "fp select out of range\n"); + break; + } + n = ((fp >> 16) & 0x3f); + m1 = ((fp >> 8) & 0x3f); + m2 = ((fp >> 0) & 0x3f); + m = 5 * (m1 + 2) + (m2 + 2); + dot = (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2); + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n", + pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2); + } + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsEnd\n"); } From 87b15cfbf762468d4b8728b3e7a39c76654017de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Nov 2006 11:30:21 -0800 Subject: [PATCH 214/257] Remove dead specifiedMonitor field. --- src/i830.h | 1 - src/i830_driver.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/i830.h b/src/i830.h index a07ba8ea..bb17f3fd 100644 --- a/src/i830.h +++ b/src/i830.h @@ -397,7 +397,6 @@ typedef struct _I830Rec { int MonType1; int MonType2; - Bool specifiedMonitor; DGAModePtr DGAModes; int numDGAModes; diff --git a/src/i830_driver.c b/src/i830_driver.c index 3612af76..779037b0 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1279,7 +1279,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType1 = PIPE_NONE; pI830->MonType2 = PIPE_NONE; - pI830->specifiedMonitor = FALSE; if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { @@ -1366,7 +1365,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pipe = 1; pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; - pI830->specifiedMonitor = TRUE; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. * From 7887c76062b7c79e14fb8e4f13486aa592dcbce8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Nov 2006 12:27:21 -0800 Subject: [PATCH 215/257] Add airlied's I2C code, ifdeffed out. I've gone back to compare our behavior to it several times, so I'll just keep the code in tree for now. --- src/i810_reg.h | 2 + src/i830_i2c.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index 31f88859..11c06596 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -276,11 +276,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define GPIOG 0x5028 #define GPIOH 0x502c # define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR_IN (0 << 1) # define GPIO_CLOCK_DIR_OUT (1 << 1) # define GPIO_CLOCK_VAL_MASK (1 << 2) # define GPIO_CLOCK_VAL_OUT (1 << 3) # define GPIO_CLOCK_VAL_IN (1 << 4) # define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR_IN (0 << 9) # define GPIO_DATA_DIR_OUT (1 << 9) # define GPIO_DATA_VAL_MASK (1 << 10) # define GPIO_DATA_VAL_OUT (1 << 11) diff --git a/src/i830_i2c.c b/src/i830_i2c.c index cee7bb51..8b93c8e6 100644 --- a/src/i830_i2c.c +++ b/src/i830_i2c.c @@ -48,6 +48,219 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "shadow.h" #include "i830.h" +#define AIRLIED_I2C 0 + +#if AIRLIED_I2C + +#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ +#define I2C_TRACE(x) /*(x)*/ /* Report progress */ + +static void i830_setscl(I2CBusPtr b, int state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, + (state ? GPIO_CLOCK_VAL_OUT : 0) | GPIO_CLOCK_DIR_OUT | + GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK); + val = INREG(b->DriverPrivate.uval); +} + +static void i830_setsda(I2CBusPtr b, int state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, + (state ? GPIO_DATA_VAL_OUT : 0) | GPIO_DATA_DIR_OUT | + GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK); + val = INREG(b->DriverPrivate.uval); +} + +static void i830_getscl(I2CBusPtr b, int *state) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK); + OUTREG(b->DriverPrivate.uval, 0); + val = INREG(b->DriverPrivate.uval); + *state = ((val & GPIO_DATA_VAL_IN) != 0); +} + +static int i830_getsda(I2CBusPtr b) + { + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 val; + + OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK); + OUTREG(b->DriverPrivate.uval, 0); + val = INREG(b->DriverPrivate.uval); + return ((val & GPIO_DATA_VAL_IN) != 0); +} + +static inline void sdalo(I2CBusPtr b) +{ + i830_setsda(b, 0); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline void sdahi(I2CBusPtr b) +{ + i830_setsda(b, 1); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline void scllo(I2CBusPtr b) +{ + i830_setscl(b, 0); + b->I2CUDelay(b, b->RiseFallTime); +} + +static inline int sclhi(I2CBusPtr b, int timeout) +{ + int scl = 0; + int i; + + i830_setscl(b, 1); + b->I2CUDelay(b, b->RiseFallTime); + + for (i = timeout; i > 0; i -= b->RiseFallTime) { + i830_getscl(b, &scl); + if (scl) break; + b->I2CUDelay(b, b->RiseFallTime); + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]", + b->BusName, timeout)); + return FALSE; + } + return TRUE; +} + +static Bool +I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +{ + I2CBusPtr b = d->pI2CBus; + int i, sda; + unsigned char indata = 0; + + sdahi(b); + + for (i = 0; i < 8; i++) { + if (sclhi(b, d->BitTimeout) == FALSE) { + I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i)); + return FALSE; + }; + indata *= 2; + if (i830_getsda(b)) + indata |= 0x01; + scllo(b); + } + + if (last) { + sdahi(b); + } else { + sdalo(b); + } + + if (sclhi(b, d->BitTimeout) == FALSE) { + sdahi(b); + return FALSE; + }; + + scllo(b); + sdahi(b); + + *data = indata & 0xff; + I2C_TRACE(ErrorF("R%02x ", (int) *data)); + + return TRUE; +} + +static Bool +I830I2CPutByte(I2CDevPtr d, I2CByte c) +{ + Bool r; + int i, scl, sda; + int sb, ack; + I2CBusPtr b = d->pI2CBus; + + for (i = 7; i >= 0; i--) { + sb = c & (1 << i); + i830_setsda(b, sb); + b->I2CUDelay(b, b->RiseFallTime); + + if (sclhi(b, d->ByteTimeout) == FALSE) { + sdahi(b); + return FALSE; + } + + i830_setscl(b, 0); + b->I2CUDelay(b, b->RiseFallTime); + } + sdahi(b); + if (sclhi(b, d->ByteTimeout) == FALSE) { + I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", + b->BusName, c, d->BitTimeout, + d->ByteTimeout, d->AcknTimeout)); + return FALSE; + } + ack = i830_getsda(b); + I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack)); + + scllo(b); + return (0 == ack); +} + +static Bool +I830I2CStart(I2CBusPtr b, int timeout) +{ + if (sclhi(b, timeout) == FALSE) + return FALSE; + + sdalo(b); + scllo(b); + + return TRUE; +} + +static void +I830I2CStop(I2CDevPtr d) +{ + I2CBusPtr b = d->pI2CBus; + + sdalo(b); + sclhi(b, d->ByteTimeout); + sdahi(b); +} + +static Bool +I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + if (I830I2CStart(d->pI2CBus, d->StartTimeout)) { + if (I830I2CPutByte(d, addr & 0xFF)) { + if ((addr & 0xF8) != 0xF0 && + (addr & 0xFE) != 0x00) + return TRUE; + + if (I830I2CPutByte(d, (addr >> 8) & 0xFF)) + return TRUE; + } + + I830I2CStop(d); + } + + return FALSE; +} + +#else + static void i830I2CGetBits(I2CBusPtr b, int *clock, int *data) { @@ -76,6 +289,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, int data) GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK); } +#endif /* the i830 has a number of I2C Buses */ Bool @@ -90,8 +304,16 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) pI2CBus->BusName = name; pI2CBus->scrnIndex = pScrn->scrnIndex; +#if AIRLIED_I2C + pI2CBus->I2CGetByte = I830I2CGetByte; + pI2CBus->I2CPutByte = I830I2CPutByte; + pI2CBus->I2CStart = I830I2CStart; + pI2CBus->I2CStop = I830I2CStop; + pI2CBus->I2CAddress = I830I2CAddress; +#else pI2CBus->I2CGetBits = i830I2CGetBits; pI2CBus->I2CPutBits = i830I2CPutBits; +#endif pI2CBus->DriverPrivate.uval = i2c_reg; if (!xf86I2CBusInit(pI2CBus)) From a9eac38bcdb49df2ce1122b49bd8b1eb19e8cae5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Nov 2006 13:24:54 -0800 Subject: [PATCH 216/257] Remove duplicated register defs that were just added. --- src/i810_reg.h | 14 -------------- src/i830_debug.c | 5 ++--- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index 11c06596..d6f7147b 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -853,20 +853,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 /** @} */ -/* SDVO/UDI Multiplier/Divisor register */ -#define DPLLAMD 0x601c -#define DPLLBMD 0x6020 - -/* Hi res source UDI divider (-1), non-zeor for UDI fixed freq mode */ -# define DPLLMD_UDI_DIVIDER_HIRES_MASK (0x3f << 24) -# define DPLLMD_UDI_DIVIDER_HIRES_SHIFT 24 -# define DPLLMD_UDI_DIVIDER_VGA_MASK (0x3f << 16) -# define DPLLMD_UDI_DIVIDER_VGA_SHIFT 16 -# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_MASK (0x3f << 8) -# define DPLLMD_SDVOUDI_MULTIPLIER_HIRES_SHIFT 8 -# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_MASK (0x3f << 0) -# define DPLLMD_SDVOUDI_MULTIPLIER_VGA_SHIFT 0 - #define DPLL_TEST 0x606c #define D_STATE 0x6104 diff --git a/src/i830_debug.c b/src/i830_debug.c index 802330e9..7922af0a 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -59,7 +59,6 @@ static struct i830SnapshotRec { DEFINEREG(DSPFW1), DEFINEREG(DSPFW2), DEFINEREG(DSPFW3), - DEFINEREG(ADPA), DEFINEREG(LVDS), @@ -90,7 +89,7 @@ static struct i830SnapshotRec { DEFINEREG(FPA0), DEFINEREG(FPA1), DEFINEREG(DPLL_A), - DEFINEREG(DPLLAMD), + DEFINEREG(DPLL_A_MD), DEFINEREG(HTOTAL_A), DEFINEREG(HBLANK_A), DEFINEREG(HSYNC_A), @@ -113,7 +112,7 @@ static struct i830SnapshotRec { DEFINEREG(FPB0), DEFINEREG(FPB1), DEFINEREG(DPLL_B), - DEFINEREG(DPLLBMD), + DEFINEREG(DPLL_B_MD), DEFINEREG(HTOTAL_B), DEFINEREG(HBLANK_B), DEFINEREG(HSYNC_B), From f22d9bcc25aea19ba38d35282367b591fd1b7ca0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 13:34:45 -0800 Subject: [PATCH 217/257] Add another couple of new registers --- src/i810_reg.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i810_reg.h b/src/i810_reg.h index d6f7147b..e126904f 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -1652,6 +1652,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DSPBADDR DSPBBASE #define DSPBSTRIDE 0x71188 +#define DSPAKEYVAL 0x70194 +#define DSPAKEYMASK 0x70198 + #define DSPAPOS 0x7018C /* reserved */ #define DSPASIZE 0x70190 #define DSPBPOS 0x7118C From 56f6d4f1bb67f447500af3f4f7fa557c3e887baa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 13:42:17 -0800 Subject: [PATCH 218/257] Disable the panel fitter when not using it. Cleans up SDVO DVI output. The panel fitter appears to exist on the 965 hardware (at least) and causes troubles with DVI output over SDVO when enabled. This patch checks to see if the panel fitter is pointing at the pipe being configured and disables it unconditionally in that case. The LVDS driver will configure it correctly if necessary afterwards. --- src/i830_display.c | 10 ++++++++++ src/i830_driver.c | 4 ++++ src/i830_lvds.c | 2 -- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index b3019f80..4716e865 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -607,6 +607,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode); } + /* + * If the panel fitter is stuck on our pipe, turn it off + * the LVDS output will whack it correctly if it needs it + */ + if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) + OUTREG(PFIT_CONTROL, 0); + + OUTREG(PFIT_PGM_RATIOS, 0x10001000); + OUTREG(DSPARB, (47 << 0) | (95 << 7)); + OUTREG(htot_reg, htot); OUTREG(hblank_reg, hblank); OUTREG(hsync_reg, hsync); diff --git a/src/i830_driver.c b/src/i830_driver.c index 779037b0..4fb8ac26 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2308,6 +2308,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveSWF[15] = INREG(SWF31); pI830->saveSWF[16] = INREG(SWF32); + pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); + for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].save != NULL) pI830->output[i].save(pScrn, &pI830->output[i]); @@ -2426,6 +2428,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + i830CompareRegsToSnapshot(pScrn); return TRUE; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 7b9fe634..ea45420f 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -86,7 +86,6 @@ i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); pI830->savePP_ON = INREG(LVDSPP_ON); pI830->savePP_OFF = INREG(LVDSPP_OFF); pI830->saveLVDS = INREG(LVDS); @@ -115,7 +114,6 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) OUTREG(LVDSPP_ON, pI830->savePP_ON); OUTREG(LVDSPP_OFF, pI830->savePP_OFF); OUTREG(PP_CYCLE, pI830->savePP_CYCLE); - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); OUTREG(LVDS, pI830->saveLVDS); OUTREG(PP_CONTROL, pI830->savePP_CONTROL); if (pI830->savePP_CONTROL & POWER_TARGET_ON) From 2c9ab6e0594769274f2dbcdf7c00fe297fc385d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Nov 2006 13:44:55 -0800 Subject: [PATCH 219/257] set the v_sync_off_high to zero. XXX should check docs --- src/i830_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index eda28579..da611590 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -553,7 +553,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, output_dtd.part2.sync_off_width_high = 0; output_dtd.part2.dtd_flags = 0x18; output_dtd.part2.sdvo_flags = 0; - output_dtd.part2.v_sync_off_width = 0; + output_dtd.part2.v_sync_off_high = 0; output_dtd.part2.reserved = 0; if (mode->Flags & V_PHSYNC) output_dtd.part2.dtd_flags |= 0x2; From 0510671a6c5233468ac20f0ec8096e084df03ce6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Nov 2006 10:58:23 -0800 Subject: [PATCH 220/257] Fix a pasteo in I965 register restore. --- src/i830_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3612af76..d996bcdc 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2404,8 +2404,8 @@ RestoreHWState(ScrnInfoPtr pScrn) } if (IS_I965G(pI830)) { - OUTREG(DSPASURF, pI830->saveDSPABASE); - OUTREG(DSPBSURF, pI830->saveDSPBBASE); + OUTREG(DSPASURF, pI830->saveDSPASURF); + OUTREG(DSPBSURF, pI830->saveDSPBSURF); } OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); From 9681602177124e84a817a1e1d428f1779f2a45c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 12:55:25 -0800 Subject: [PATCH 221/257] Create I830PipeRec to hold pipe-specific data. Remove unused I830 members. I830 contained six parallel arrays for pipe-specific data; these have been moved to a I830PipeRec structure instead. I830 also contained several unused members: unsigned int bios_version; Bool newPipeSwitch; Bool fakeSwitch; int fixedPipe; These have been removed, along with the code that set them. --- src/i830.h | 28 +++++------ src/i830_cursor.c | 35 +++++++------ src/i830_display.c | 119 +++++++++++++++++---------------------------- src/i830_dri.c | 2 +- src/i830_driver.c | 35 ++++--------- src/i830_modes.c | 21 -------- src/i830_randr.c | 31 ++++++------ 7 files changed, 101 insertions(+), 170 deletions(-) diff --git a/src/i830.h b/src/i830.h index bb17f3fd..b4b17ded 100644 --- a/src/i830.h +++ b/src/i830.h @@ -287,31 +287,29 @@ struct _I830OutputRec { void *dev_priv; }; +typedef struct _I830PipeRec { + Bool gammaEnabled; + int x; + int y; + Bool cursorInRange; + Bool cursorShown; + Bool planeEnabled; + DisplayModeRec curMode; +} I830PipeRec, *I830PipePtr; + typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; int cpp; - unsigned int bios_version; - - Bool newPipeSwitch; - - Bool fakeSwitch; - - int fixedPipe; - DisplayModePtr currentMode; /* Mode saved during randr reprobe, which will need to be freed at the point * of the next SwitchMode, when we lose this last reference to it. */ DisplayModePtr savedCurrentMode; - Bool gammaEnabled[MAX_DISPLAY_PIPES]; - - int pipeX[MAX_DISPLAY_PIPES]; - int pipeY[MAX_DISPLAY_PIPES]; - Bool cursorInRange[MAX_DISPLAY_PIPES]; - Bool cursorShown[MAX_DISPLAY_PIPES]; + I830PipeRec pipes[MAX_DISPLAY_PIPES]; + Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -478,8 +476,6 @@ typedef struct _I830Rec { /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; /* [0] is display plane A, [1] is display plane B. */ - int planeEnabled[MAX_DISPLAY_PIPES]; - DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ Bool preinit; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 92239f1b..0b7e772b 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -105,14 +105,15 @@ void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) { I830Ptr pI830 = I830PTR(pScrn); + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; CARD32 temp; Bool show; - if (!pI830->planeEnabled[pipe]) + if (!pI830Pipe->planeEnabled) return; - show = pI830->cursorOn && pI830->cursorInRange[pipe]; - if (show && (force || !pI830->cursorShown[pipe])) + show = pI830->cursorOn && pI830Pipe->cursorInRange; + if (show && (force || !pI830Pipe->cursorShown)) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { int cursor_control; @@ -124,7 +125,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) { temp |= CURSOR_MODE_64_ARGB_AX; - if (pI830->gammaEnabled[pipe]) + if (pI830Pipe->gammaEnabled) temp |= MCURSOR_GAMMA_ENABLE; } else temp |= CURSOR_MODE_64_4C_AX; @@ -138,15 +139,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp |= CURSOR_ENABLE; if (pI830->CursorIsARGB) { temp |= CURSOR_FORMAT_ARGB; - if (pI830->gammaEnabled[pipe]) + if (pI830Pipe->gammaEnabled) temp |= CURSOR_GAMMA_ENABLE; } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); } - pI830->cursorShown[pipe] = TRUE; + pI830Pipe->cursorShown = TRUE; } - else if (!show && (force || pI830->cursorShown[pipe])) + else if (!show && (force || pI830Pipe->cursorShown)) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { @@ -164,7 +165,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); OUTREG(CURSOR_CONTROL, temp); } - pI830->cursorShown[pipe] = FALSE; + pI830Pipe->cursorShown = FALSE; } /* Flush cursor changes. */ @@ -179,7 +180,8 @@ I830InitHWCursor(ScrnInfoPtr pScrn) int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE; + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + pI830->pipes[i].cursorShown = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { for (i = 0; i < MAX_DISPLAY_PIPES; i++) @@ -484,11 +486,12 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) { - DisplayModePtr mode = &pI830->pipeCurMode[pipe]; - int thisx = x - pI830->pipeX[pipe]; - int thisy = y - pI830->pipeY[pipe]; + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; + DisplayModePtr mode = &pI830Pipe->curMode; + int thisx = x - pI830Pipe->x; + int thisy = y - pI830Pipe->y; - if (!pI830->planeEnabled[pipe]) + if (!pI830Pipe->planeEnabled) continue; /* @@ -524,7 +527,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) if (pipe == 1) OUTREG(CURSOR_B_POSITION, temp); - pI830->cursorInRange[pipe] = inrange; + pI830Pipe->cursorInRange = inrange; I830SetPipeCursor (pScrn, pipe, FALSE); } @@ -577,14 +580,14 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - if (pI830->planeEnabled[0]) + if (pI830->pipes[0].planeEnabled) { OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); } - if (pI830->planeEnabled[1]) + if (pI830->pipes[1].planeEnabled) { OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); diff --git a/src/i830_display.c b/src/i830_display.c index 4716e865..1175cf10 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -237,6 +237,7 @@ void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) { I830Ptr pI830 = I830PTR(pScrn); + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; unsigned long Start; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); @@ -255,8 +256,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } - pI830->pipeX[pipe] = x; - pI830->pipeY[pipe] = y; + pI830Pipe->x = x; + pI830Pipe->y = y; } /** @@ -363,6 +364,7 @@ Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) { I830Ptr pI830 = I830PTR(pScrn); + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; @@ -391,7 +393,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) else outputs = (pI830->operatingDevices >> 8) & 0xff; - if (I830ModesEqual(&pI830->pipeCurMode[pipe], pMode)) + if (I830ModesEqual(&pI830Pipe->curMode, pMode)) return TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", @@ -576,7 +578,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) FatalError("unknown display bpp\n"); } - if (pI830->gammaEnabled[pipe]) { + if (pI830Pipe->gammaEnabled) { dspcntr |= DISPPLANE_GAMMA_ENABLE; } @@ -626,7 +628,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp); OUTREG(dspsize_reg, dspsize); OUTREG(dsppos_reg, 0); - i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]); + i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y); OUTREG(pipesrc_reg, pipesrc); /* Then, turn the pipe on first */ @@ -636,7 +638,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) /* And then turn the plane on */ OUTREG(dspcntr_reg, dspcntr); - pI830->pipeCurMode[pipe] = *pMode; + pI830Pipe->curMode = *pMode; return TRUE; } @@ -658,63 +660,49 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - if (!pI830->planeEnabled[0]) { - CARD32 dspcntr, pipeconf, dpll; + for (i = 0; i < MAX_DISPLAY_PIPES; i++) { + I830PipePtr pI830Pipe = &pI830->pipes[i]; + int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; + int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; + int dpll_reg = pipe == 0 ? DPLL_A : DPLL_B; + CARD32 dspcntr, pipeconf, dpll; + char *pipe_name = pipe == 0 ? "A" : "B"; - dspcntr = INREG(DSPACNTR); + if (pI830Pipe->planeEnabled) + continue; + + dspcntr = INREG(dspcntr_reg); if (dspcntr & DISPLAY_PLANE_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane A\n"); - OUTREG(DSPACNTR, dspcntr & ~DISPLAY_PLANE_ENABLE); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane %s\n", + pipe_name); + + OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); /* Wait for vblank for the disable to take effect */ i830WaitForVblank(pScrn); } - pipeconf = INREG(PIPEACONF); + pipeconf = INREG(pipeconf_reg); if (pipeconf & PIPEACONF_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe A\n"); - OUTREG(PIPEACONF, pipeconf & ~PIPEACONF_ENABLE); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe %s\n", + pipe_name); + OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); } - dpll = INREG(DPLL_A); + dpll = INREG(dpll_reg); if (dpll & DPLL_VCO_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL A\n"); - OUTREG(DPLL_A, dpll & ~DPLL_VCO_ENABLE); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL %s\n", + pipe_name); + OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE); } - memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0])); - } - - if (!pI830->planeEnabled[1]) { - CARD32 dspcntr, pipeconf, dpll; - - dspcntr = INREG(DSPBCNTR); - if (dspcntr & DISPLAY_PLANE_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane B\n"); - OUTREG(DSPBCNTR, dspcntr & ~DISPLAY_PLANE_ENABLE); - - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - } - - pipeconf = INREG(PIPEBCONF); - if (pipeconf & PIPEBCONF_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe B\n"); - OUTREG(PIPEBCONF, pipeconf & ~PIPEBCONF_ENABLE); - } - - dpll = INREG(DPLL_B); - if (dpll & DPLL_VCO_ENABLE) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL B\n"); - OUTREG(DPLL_B, dpll & ~DPLL_VCO_ENABLE); - } - - memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1])); + memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode)); } } /** - * This function sets the given mode on the active pipes. + * This function configures the screens in clone mode on + * all active outputs using a mode similar to the specified mode. */ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) @@ -732,31 +720,17 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) didLock = I830DRILock(pScrn); #endif - if (pI830->operatingDevices & 0xff) { - pI830->planeEnabled[0] = 1; - } else { - pI830->planeEnabled[0] = 0; - } + pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0; + pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0; - if (pI830->operatingDevices & 0xff00) { - pI830->planeEnabled[1] = 1; - } else { - pI830->planeEnabled[1] = 0; - } - - for (i = 0; i < pI830->num_outputs; i++) { + for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); - } - if (pI830->planeEnabled[0]) { - ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode), - 0); - if (!ok) - goto done; - } - if (pI830->planeEnabled[1]) { - ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode), - 1); + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + { + if (pI830->pipes[i].planeEnabled) + ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), + i); if (!ok) goto done; } @@ -776,13 +750,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* If we might have enabled/disabled some pipes, we need to reset * cloning mode support. */ - if ((pI830->operatingDevices & 0x00ff) && - (pI830->operatingDevices & 0xff00)) - { + if (pI830->pipes[0].planeEnabled && pI830->pipes[1].planeEnabled) pI830->Clone = TRUE; - } else { + else pI830->Clone = FALSE; - } /* If HW cursor currently showing, reset cursor state */ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) @@ -821,7 +792,7 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Display plane %c is now %s and connected to pipe %c.\n", 'A' + i, - pI830->planeEnabled[i] ? "enabled" : "disabled", + pI830->pipes[i].planeEnabled ? "enabled" : "disabled", dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A'); } diff --git a/src/i830_dri.c b/src/i830_dri.c index c9b52c48..41ea21ca 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1485,7 +1485,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->planeEnabled[1]) + if (pI830->pipes[1].planeEnabled) pipe.pipe = DRM_I830_VBLANK_PIPE_B; else pipe.pipe = DRM_I830_VBLANK_PIPE_A; diff --git a/src/i830_driver.c b/src/i830_driver.c index 4fb8ac26..3b219748 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -640,6 +640,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, pI830 = I830PTR(pScrn); for(p=0; p < pI830->availablePipes; p++) { + I830PipePtr pI830Pipe = &pI830->pipes[p]; if (p == 0) { palreg = PALETTE_A; @@ -653,10 +654,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, dspsurf = DSPBSURF; } - if (pI830->planeEnabled[p] == 0) + if (pI830Pipe->planeEnabled == 0) continue; - pI830->gammaEnabled[p] = 1; + pI830Pipe->gammaEnabled = 1; /* To ensure gamma is enabled we need to turn off and on the plane */ temp = INREG(dspreg); @@ -1265,16 +1266,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->LinearAlloc = 0; } - pI830->fixedPipe = -1; - if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) && - I830IsPrimary(pScrn)) { - - if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0")) - pI830->fixedPipe = 0; - else if (strstr(s, "B") || strstr(s, "b") || strstr(s, "1")) - pI830->fixedPipe = 1; - } - I830PreInitDDC(pScrn); pI830->MonType1 = PIPE_NONE; @@ -1681,16 +1672,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - if (IS_I9XX(pI830)) - pI830->newPipeSwitch = TRUE; - else - if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) { - /* BIOS build 3062 changed the pipe switching functionality */ - pI830->newPipeSwitch = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n"); - } else - pI830->newPipeSwitch = FALSE; - PrintDisplayDeviceInfo(pScrn); if (xf86IsEntityShared(pScrn->entityList[0])) { @@ -3400,7 +3381,8 @@ static Bool I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI830 = I830PTR(pScrn); + int i; DPRINTF(PFX, "Enter VT\n"); @@ -3431,7 +3413,8 @@ I830EnterVT(int scrnIndex, int flags) SetHWOperatingState(pScrn); /* Mark that we'll need to re-set the mode for sure */ - memset(pI830->pipeCurMode, 0, sizeof(pI830->pipeCurMode)); + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode)); if (!i830SetMode(pScrn, pScrn->currentMode)) return FALSE; @@ -3584,7 +3567,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) base = DSPBADDR; surf = DSPBSURF; } - if (pI830->planeEnabled[i]) { + if (pI830->pipes[i].planeEnabled) { temp = INREG(ctrl); if (on) temp |= DISPLAY_PLANE_ENABLE; @@ -3633,7 +3616,7 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, ctrl = DSPBCNTR; base = DSPBADDR; } - if (pI830->planeEnabled[i]) { + if (pI830->pipes[i].planeEnabled) { temp = INREG(ctrl); if (PowerManagementMode == DPMSModeOn) temp |= DISPLAY_PLANE_ENABLE; diff --git a/src/i830_modes.c b/src/i830_modes.c index 0bb17a54..b6867c3c 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -384,27 +384,6 @@ i830GetModeListTail(DisplayModePtr pModeList) return last; } -/** - * Appends a list of modes to another mode list, without duplication. - */ -static void -i830AppendModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, - DisplayModePtr addModes) -{ - DisplayModePtr first = *modeList; - DisplayModePtr last = i830GetModeListTail(first); - - if (addModes == NULL) - return; - - if (first == NULL) { - *modeList = addModes; - } else { - last->next = addModes; - addModes->prev = last; - } -} - /** * This function removes a mode from a list of modes. It should probably be * moved to xf86Mode.c. diff --git a/src/i830_randr.c b/src/i830_randr.c index 59ebcc08..67641d6a 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -489,12 +489,13 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) struct _I830OutputRec *output; RROutputPtr rrout; int pipe = (int) crtc->devPrivate; + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; int i, j; - DisplayModePtr pipeMode = &pI830->pipeCurMode[pipe]; + DisplayModePtr pipeMode = &pI830Pipe->curMode; int pipe_type; - x = pI830->pipeX[pipe]; - y = pI830->pipeY[pipe]; + x = pI830Pipe->x; + y = pI830Pipe->y; rotation = RR_Rotate_0; numOutputs = 0; for (i = 0; i < pI830->num_outputs; i++) @@ -550,6 +551,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int pipe = (int) (crtc->devPrivate); + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; DisplayModePtr display_mode = mode ? mode->devPrivate : NULL; /* Sync the engine before adjust mode */ @@ -560,7 +562,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, if (display_mode != randrp->modes[pipe]) { - pI830->planeEnabled[pipe] = mode != NULL; + pI830Pipe->planeEnabled = mode != NULL; if (display_mode) { if (!i830PipeSetMode (pScrn, display_mode, pipe)) @@ -833,18 +835,15 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) { int mmWidth, mmHeight; - if (mode->HDisplay == pScreen->width && - mode->VDisplay == pScreen->height) - { - mmWidth = pScrn->widthmm; - mmHeight = pScrn->heightmm; - } - else - { -#define MMPERINCH 25.4 - mmWidth = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH; - mmHeight = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH; - } + mmWidth = pScreen->mmWidth; + mmHeight = pScreen->mmHeight; + if (mode->HDisplay != pScreen->width) + mmWidth = mmWidth * mode->HDisplay / pScreen->width; + if (mode->VDisplay == pScreen->height) + mmHeight = mmHeight * mode->VDisplay / pScreen->height; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Setting screen physical size to %d x %d\n", + mmWidth, mmHeight); I830RandRScreenSetSize (pScreen, mode->HDisplay, mode->VDisplay, From 282a9e073ea985cbf0d0f3f296d593af1426bad5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Nov 2006 13:46:09 -0800 Subject: [PATCH 222/257] Don't memset the modes pointer on init, which was dereferencing NULL. --- src/i830_randr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 59ebcc08..e4ae9d04 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -874,7 +874,6 @@ I830RandRInit12 (ScreenPtr pScreen) rp->rrCrtcSet = I830RandRCrtcSet; rp->rrCrtcSetGamma = I830RandRCrtcSetGamma; rp->rrSetConfig = NULL; - memset (rp->modes, '\0', sizeof (rp->modes)); pScrn->PointerMoved = I830RandRPointerMoved; return TRUE; } From e416b426d83de031441ada7a77b6bd66cec8b5c9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Nov 2006 15:25:41 -0800 Subject: [PATCH 223/257] Print out modelines as info, not error (which had been used for debugging). --- src/i830_xf86Modes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 166f41af..ca92e4d0 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -317,7 +317,7 @@ PrintModeline(int scrnIndex,DisplayModePtr mode) #if 0 if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); #endif - xf86DrvMsg(scrnIndex, X_ERROR, + xf86DrvMsg(scrnIndex, X_INFO, "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s " "(%.01f kHz)\n", mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay, From 561af007974b8cdad1eea907fb73ed9d430c21ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Nov 2006 15:26:14 -0800 Subject: [PATCH 224/257] Add support for load-based CRT detection. --- src/i830.h | 5 ++ src/i830_crt.c | 20 ++++---- src/i830_display.c | 117 ++++++++++++++++++++++++++++++++++++++++++--- src/i830_display.h | 5 +- src/i830_randr.c | 2 +- 5 files changed, 129 insertions(+), 20 deletions(-) diff --git a/src/i830.h b/src/i830.h index a07ba8ea..4ce1a550 100644 --- a/src/i830.h +++ b/src/i830.h @@ -205,6 +205,11 @@ struct _I830OutputRec { int type; int pipe; Bool disabled; + /** + * Marks that the output and associated pipe is temporarily enabled for + * load detection. + */ + Bool load_detect_temp; /** * Turns the output on/off, or sets intermediate power levels if available. diff --git a/src/i830_crt.c b/src/i830_crt.c index 0225727b..4c704b2c 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "i830.h" #include "i830_xf86Modes.h" +#include "i830_display.h" static void i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) @@ -166,7 +167,7 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScrn) * \return FALSE if CRT is disconnected. */ static Bool -i830_crt_detect_load(ScrnInfoPtr pScrn) +i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); CARD32 adpa, pipeconf; @@ -174,7 +175,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn) int pipeconf_reg, bclrpat_reg, dpll_reg; int pipe; - pipe = pI830->pipe; + pipe = output->pipe; if (pipe == 0) { bclrpat_reg = BCLRPAT_A; pipeconf_reg = PIPEACONF; @@ -263,15 +264,12 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output) if (i830_crt_detect_ddc(pScrn)) return OUTPUT_STATUS_CONNECTED; - /* Use the load-detect method if we're not currently outputting to the CRT, - * or we don't care. - * - * Actually, the method is unreliable currently. We need to not share a - * pipe, as it seems having other outputs on that pipe will result in a - * false positive. - */ - if (0) { - if (i830_crt_detect_load(pScrn)) + /* Use the load-detect method if we have no other way of telling. */ + if (i830GetLoadDetectPipe(pScrn, output) != -1) { + Bool connected = i830_crt_detect_load(pScrn, output); + + i830ReleaseLoadDetectPipe(pScrn, output); + if (connected) return OUTPUT_STATUS_CONNECTED; else return OUTPUT_STATUS_DISCONNECTED; diff --git a/src/i830_display.c b/src/i830_display.c index b3019f80..6107c475 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -356,11 +356,16 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) } /** - * Sets the given video mode on the given pipe. Assumes that plane A feeds - * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. + * Sets the given video mode on the given pipe. + * + * Plane A is always output to pipe A, and plane B to pipe B. The plane + * will not be enabled if plane_enable is FALSE, which is used for + * load detection, when something else will be output to the pipe other than + * display data. */ Bool -i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, + Bool plane_enable) { I830Ptr pI830 = I830PTR(pScrn); int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; @@ -623,8 +628,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) temp = INREG(pipeconf_reg); OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); - /* And then turn the plane on */ - OUTREG(dspcntr_reg, dspcntr); + if (plane_enable) { + /* And then turn the plane on */ + OUTREG(dspcntr_reg, dspcntr); + } pI830->pipeCurMode[pipe] = *pMode; @@ -740,13 +747,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) if (pI830->planeEnabled[0]) { ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode), - 0); + 0, TRUE); if (!ok) goto done; } if (pI830->planeEnabled[1]) { ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode), - 1); + 1, TRUE); if (!ok) goto done; } @@ -842,3 +849,99 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) pI830->output[i].pipe == 0 ? 'A' : 'B'); } } + +/** + * Get a pipe with a simple mode set on it for doing load-based monitor + * detection. + * + * It will be up to the load-detect code to adjust the pipe as appropriate for + * its requirements. The pipe will be connected to no other outputs. + * + * Currently this code will only succeed if there is a pipe with no outputs + * configured for it. In the future, it could choose to temporarily disable + * some outputs to free up a pipe for its use. + * + * \return monitor number, or -1 if no pipes are available. + */ +int +i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool pipe_available[MAX_DISPLAY_PIPES]; + int i; + /* VESA 640x480x72Hz mode to set on the pipe */ + DisplayModeRec mode = { + NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT, + 31500, + 640, 664, 704, 832, 0, + 480, 489, 491, 520, 0, + V_NHSYNC | V_NVSYNC, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + FALSE, FALSE, 0, NULL, 0, 0.0, 0.0 + }; + + /* If the output is not marked disabled, check if it's already assigned + * to an active pipe, and is alone on that pipe. If so, we're done. + */ + if (!output->disabled) { + int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF; + + if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) { + /* Actually, maybe we don't need to be all alone on the pipe. + * The worst that should happen is false positives. Need to test, + * but actually fixing this during server startup is messy. + */ +#if 0 + for (i = 0; i < pI830->num_outputs; i++) { + if (&pI830->output[i] != output && + pI830->output[i].pipe == output->pipe) + { + return -1; + } + } +#endif + return output->pipe; + } + } + + for (i = 0; i < pI830->availablePipes; i++) { + pipe_available[i] = TRUE; + } + + for (i = 0; i < pI830->num_outputs; i++) { + if (!pI830->output[i].disabled) + { + pipe_available[pI830->output[i].pipe] = FALSE; + } + } + + for (i = 0; i < pI830->availablePipes; i++) { + if (pipe_available[i]) + break; + } + + if (i == pI830->availablePipes) { + return -1; + } + output->load_detect_temp = TRUE; + output->pipe = i; + output->disabled = FALSE; + + I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V); + + i830PipeSetMode(pScrn, &mode, i, FALSE); + + return i; +} + +void +i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) +{ + if (output->load_detect_temp) { + output->disabled = TRUE; + i830DisableUnusedFunctions(pScrn); + output->load_detect_temp = FALSE; + } +} diff --git a/src/i830_display.h b/src/i830_display.h index 8a6e9e90..5c0f1339 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -26,9 +26,12 @@ */ /* i830_display.c */ -Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); +Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, + Bool plane_enable); void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); +int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); +void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); diff --git a/src/i830_randr.c b/src/i830_randr.c index e4ae9d04..5b02a537 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -563,7 +563,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, pI830->planeEnabled[pipe] = mode != NULL; if (display_mode) { - if (!i830PipeSetMode (pScrn, display_mode, pipe)) + if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE)) return FALSE; /* XXX need I830SDVOPostSetMode here */ } From 27df2ff7908ea7ea2943a5f3445e12dbc24d97c9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 3 Nov 2006 15:55:10 -0800 Subject: [PATCH 225/257] Report pipe status (and status mismatches) in i830DescribeOutputConfiguration() --- src/i830_display.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index e3db8ad7..e36b5efc 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -796,12 +796,32 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) for (i = 0; i < pI830->availablePipes; i++) { CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i); + CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i); + Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0; + Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " Pipe %c is %s\n", + 'A' + i, pI830->pipes[i].planeEnabled ? "on" : "off"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Display plane %c is now %s and connected to pipe %c.\n", 'A' + i, pI830->pipes[i].planeEnabled ? "enabled" : "disabled", dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A'); + if (hw_pipe_enable != pI830->pipes[i].planeEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " Hardware claims pipe %c is %s while software " + "believes it is %s\n", + 'A' + i, hw_pipe_enable ? "on" : "off", + pI830->pipes[i].planeEnabled ? "on" : "off"); + } + if (hw_plane_enable != pI830->pipes[i].planeEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " Hardware claims plane %c is %s while software " + "believes it is %s\n", + 'A' + i, hw_plane_enable ? "on" : "off", + pI830->pipes[i].planeEnabled ? "on" : "off"); + } } for (i = 0; i < pI830->num_outputs; i++) { From 719ad68515be9b996a6314de5448843de1146b88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 19:41:41 -0800 Subject: [PATCH 226/257] Use VBE only temporarily to fetch BIOS rom image (cherry picked from 6a9386651785afc70a29e355255e8295b321f28e commit) --- src/i830.h | 2 ++ src/i830_bios.c | 9 ++++++--- src/i830_driver.c | 8 ++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/i830.h b/src/i830.h index b4b17ded..10061d1a 100644 --- a/src/i830.h +++ b/src/i830.h @@ -463,8 +463,10 @@ typedef struct _I830Rec { /* Stolen memory support */ Bool StolenOnly; +#if 0 /* Video BIOS support. */ vbeInfoPtr pVbe; +#endif Bool swfSaved; CARD32 saveSWF0; diff --git a/src/i830_bios.c b/src/i830_bios.c index 97fb7fc3..0821845a 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -84,15 +84,18 @@ i830GetBIOS(ScrnInfoPtr pScrn) struct vbt_header *vbt; int vbt_off; unsigned char *bios; + vbeInfoPtr pVbe; bios = xalloc(INTEL_VBIOS_SIZE); if (bios == NULL) return NULL; - if (pI830->pVbe != NULL) { - memcpy(bios, xf86int10Addr(pI830->pVbe->pInt10, - pI830->pVbe->pInt10->BIOSseg << 4), + pVbe = VBEInit (NULL, pI830->pEnt->index); + if (pVbe != NULL) { + memcpy(bios, xf86int10Addr(pVbe->pInt10, + pVbe->pInt10->BIOSseg << 4), INTEL_VBIOS_SIZE); + vbeFree (pVbe); } else { xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE); } diff --git a/src/i830_driver.c b/src/i830_driver.c index 3b219748..1e92dac8 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -367,10 +367,12 @@ I830FreeRec(ScrnInfoPtr pScrn) pI830 = I830PTR(pScrn); +#if 0 if (I830IsPrimary(pScrn)) { if (pI830->pVbe) vbeFree(pI830->pVbe); } +#endif xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -477,7 +479,9 @@ I830DetectMemory(ScrnInfoPtr pScrn) CARD16 gmch_ctrl; int memsize = 0; int range; +#if 0 VbeInfoBlock *vbeInfo; +#endif bridge = pciTag(0, 0, 0); /* This is always the host bridge */ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); @@ -543,6 +547,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n"); } +#if 0 /* Sanity check: compare with what the BIOS thinks. */ vbeInfo = VBEGetVBEInfo(pI830->pVbe); if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) { @@ -554,6 +559,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) } if (vbeInfo != NULL) VBEFreeVBEInfo(vbeInfo); +#endif return memsize; } @@ -1001,6 +1007,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* We have to use PIO to probe, because we haven't mapped yet. */ I830SetPIOAccess(pI830); +#if 0 /* Initialize VBE record */ if (I830IsPrimary(pScrn)) { if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) { @@ -1011,6 +1018,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); pI830->pVbe = pI8301->pVbe; } +#endif switch (pI830->PciInfo->chipType) { case PCI_CHIP_I830_M: From 4625073244d4f521a07e12adcf0609e85658acbe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 23:23:38 -0800 Subject: [PATCH 227/257] Oops, martian memset of randr modes pointer --- src/i830_randr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 67641d6a..c4e91fd7 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -873,7 +873,6 @@ I830RandRInit12 (ScreenPtr pScreen) rp->rrCrtcSet = I830RandRCrtcSet; rp->rrCrtcSetGamma = I830RandRCrtcSetGamma; rp->rrSetConfig = NULL; - memset (rp->modes, '\0', sizeof (rp->modes)); pScrn->PointerMoved = I830RandRPointerMoved; return TRUE; } From b7262a9a9110dac66e1a92c39dcb3ab59d95d081 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 23:24:07 -0800 Subject: [PATCH 228/257] Finish removing persistant vbe data --- src/i830.h | 5 ----- src/i830_driver.c | 34 ---------------------------------- 2 files changed, 39 deletions(-) diff --git a/src/i830.h b/src/i830.h index 10061d1a..3e0625ef 100644 --- a/src/i830.h +++ b/src/i830.h @@ -463,11 +463,6 @@ typedef struct _I830Rec { /* Stolen memory support */ Bool StolenOnly; -#if 0 - /* Video BIOS support. */ - vbeInfoPtr pVbe; -#endif - Bool swfSaved; CARD32 saveSWF0; CARD32 saveSWF4; diff --git a/src/i830_driver.c b/src/i830_driver.c index 1e92dac8..dd96ff1a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -367,13 +367,6 @@ I830FreeRec(ScrnInfoPtr pScrn) pI830 = I830PTR(pScrn); -#if 0 - if (I830IsPrimary(pScrn)) { - if (pI830->pVbe) - vbeFree(pI830->pVbe); - } -#endif - xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } @@ -547,20 +540,6 @@ I830DetectMemory(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n"); } -#if 0 - /* Sanity check: compare with what the BIOS thinks. */ - vbeInfo = VBEGetVBEInfo(pI830->pVbe); - if (vbeInfo != NULL && vbeInfo->TotalMemory != memsize / 1024 / 64) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Detected stolen memory (%d kB) doesn't match what the BIOS" - " reports (%d kB)\n", - ROUND_DOWN_TO(memsize / 1024, 64), - vbeInfo->TotalMemory * 64); - } - if (vbeInfo != NULL) - VBEFreeVBEInfo(vbeInfo); -#endif - return memsize; } @@ -1007,19 +986,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* We have to use PIO to probe, because we haven't mapped yet. */ I830SetPIOAccess(pI830); -#if 0 - /* Initialize VBE record */ - if (I830IsPrimary(pScrn)) { - if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n"); - return FALSE; - } - } else { - I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->pVbe = pI8301->pVbe; - } -#endif - switch (pI830->PciInfo->chipType) { case PCI_CHIP_I830_M: chipname = "830M"; From e4bcec796e80e9fd66ab0c36394f5946915531f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 23:29:12 -0800 Subject: [PATCH 229/257] Use pI830->availablePipes instead of MAX_DISPLAY_PIPES everywhere --- src/i830.h | 5 ++--- src/i830_cursor.c | 10 +++++----- src/i830_display.c | 4 ++-- src/i830_driver.c | 2 +- src/i830_randr.c | 8 ++++---- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/i830.h b/src/i830.h index 3e0625ef..ea7f4c90 100644 --- a/src/i830.h +++ b/src/i830.h @@ -308,8 +308,6 @@ typedef struct _I830Rec { */ DisplayModePtr savedCurrentMode; - I830PipeRec pipes[MAX_DISPLAY_PIPES]; - Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -473,7 +471,8 @@ typedef struct _I830Rec { /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; /* [0] is display plane A, [1] is display plane B. */ - + I830PipeRec pipes[MAX_DISPLAY_PIPES]; + /* Driver phase/state information */ Bool preinit; Bool starting; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 0b7e772b..6b0e58c4 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn) int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) pI830->pipes[i].cursorShown = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; temp = INREG(cursor_control); @@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= hotspotx; y -= hotspoty; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { I830PipePtr pI830Pipe = &pI830->pipes[pipe]; DisplayModePtr mode = &pI830Pipe->curMode; @@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } @@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } diff --git a/src/i830_display.c b/src/i830_display.c index 1175cf10..8cb66603 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -660,7 +660,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) { + for (i = 0; i < pI830->availablePipes; i++) { I830PipePtr pI830Pipe = &pI830->pipes[i]; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; @@ -726,7 +726,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { if (pI830->pipes[i].planeEnabled) ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), diff --git a/src/i830_driver.c b/src/i830_driver.c index dd96ff1a..1b75649d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3387,7 +3387,7 @@ I830EnterVT(int scrnIndex, int flags) SetHWOperatingState(pScrn); /* Mark that we'll need to re-set the mode for sure */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode)); if (!i830SetMode(pScrn, pScrn->currentMode)) diff --git a/src/i830_randr.c b/src/i830_randr.c index c4e91fd7..d0972830 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -682,7 +682,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) ncrtc = 0; pipe = -1; crtc = NULL; - for (j = 0; j < MAX_DISPLAY_PIPES; j++) + for (j = 0; j < pI830->availablePipes; j++) { #if 0 /* Can't flip outputs among crtcs yet */ @@ -782,7 +782,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) return FALSE; } - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) I830RandRCrtcNotify (randrp->crtcs[i]); return TRUE; } @@ -815,7 +815,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) /* * Create RandR resources, then probe them */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); RRCrtcGammaSetSize (randrp->crtcs[i], 256); @@ -851,7 +851,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmHeight); } - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) i830PipeSetBase(pScrn, i, 0, 0); return I830RandRSetInfo12 (pScreen); From 3ab7f9693217d8fe993bdc94c376b219b0082961 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Nov 2006 00:46:18 -0800 Subject: [PATCH 230/257] Eliminate operatingDevices member and PIPE_* values. operatingDevices and MonType1/MonType2 duplicate information already stored in the device structures. Eliminate them and replace uses with direct references to the appropriate other data. --- src/i830.h | 30 ++-------- src/i830_crt.c | 15 ++++- src/i830_display.c | 57 +++++++++++++----- src/i830_driver.c | 146 ++++++--------------------------------------- src/i830_randr.c | 72 +++++++--------------- src/i830_video.c | 9 ++- 6 files changed, 107 insertions(+), 222 deletions(-) diff --git a/src/i830.h b/src/i830.h index ea7f4c90..9e5c8442 100644 --- a/src/i830.h +++ b/src/i830.h @@ -86,26 +86,6 @@ typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr; * Paulo César Pereira de Andrade . */ -#define PIPE_CRT_ID 0 -#define PIPE_TV_ID 1 -#define PIPE_DFP_ID 2 -#define PIPE_LFP_ID 3 -#define PIPE_CRT2_ID 4 -#define PIPE_TV2_ID 5 -#define PIPE_DFP2_ID 6 -#define PIPE_LFP2_ID 7 -#define PIPE_NUM_ID 8 - -#define PIPE_NONE 0<<0 -#define PIPE_CRT 1<<0 -#define PIPE_TV 1<<1 -#define PIPE_DFP 1<<2 -#define PIPE_LFP 1<<3 -#define PIPE_CRT2 1<<4 -#define PIPE_TV2 1<<5 -#define PIPE_DFP2 1<<6 -#define PIPE_LFP2 1<<7 - typedef struct _I830Rec *I830Ptr; typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr, @@ -314,7 +294,9 @@ typedef struct _I830Rec { int CloneVDisplay; I830EntPtr entityPrivate; +#if 0 int pipe, origPipe; +#endif int init; unsigned int bufferOffset; /* for I830SelectBuffer */ @@ -391,9 +373,6 @@ typedef struct _I830Rec { Bool CursorIsARGB; CursorPtr pCurs; - int MonType1; - int MonType2; - DGAModePtr DGAModes; int numDGAModes; Bool DGAactive; @@ -466,7 +445,6 @@ typedef struct _I830Rec { CARD32 saveSWF4; Bool checkDevices; - int operatingDevices; /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; @@ -660,6 +638,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* i830_display.c */ +Bool +i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type); + /* i830_crt.c */ void i830_crt_init(ScrnInfoPtr pScrn); diff --git a/src/i830_crt.c b/src/i830_crt.c index 0225727b..4c6c3ca5 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -169,12 +169,19 @@ static Bool i830_crt_detect_load(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 adpa, pipeconf; + CARD32 adpa, pipeconf, bclrpat; CARD8 st00; int pipeconf_reg, bclrpat_reg, dpll_reg; int pipe; - pipe = pI830->pipe; + for (pipe = 0; pipe < pI830->availablePipes; pipe++) + if (!pI830->pipes[pipe].planeEnabled) + break; + + /* No available pipes for load detection */ + if (pipe == pI830->availablePipes) + return FALSE; + if (pipe == 0) { bclrpat_reg = BCLRPAT_A; pipeconf_reg = PIPEACONF; @@ -197,9 +204,10 @@ i830_crt_detect_load(ScrnInfoPtr pScrn) ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); } - /* Set the border color to red, green. Maybe we should save/restore this + /* Set the border color to purple. Maybe we should save/restore this * reg. */ + bclrpat = INREG(bclrpat_reg); OUTREG(bclrpat_reg, 0x00500050); /* Force the border color through the active region */ @@ -210,6 +218,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn) st00 = pI830->readStandard(pI830, 0x3c2); /* Restore previous settings */ + OUTREG(bclrpat_reg, bclrpat); OUTREG(pipeconf_reg, pipeconf); OUTREG(ADPA, adpa); diff --git a/src/i830_display.c b/src/i830_display.c index 8cb66603..c9b6b4dd 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -60,6 +60,24 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) m1, m2, n, p1, p2); } +/** + * Returns whether any output on the specified pipe is an LVDS output + */ +Bool +i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->num_outputs; i++) + if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + { + if (pI830->output[i].type == type) + return TRUE; + } + return FALSE; +} + /** * Returns whether the given set of divisors are valid for a given refclk with * the given outputs. @@ -68,7 +86,7 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, +i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2, int n, int p1, int p2) { I830Ptr pI830 = I830PTR(pScrn); @@ -87,7 +105,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, max_n = 8; min_p1 = 1; max_p1 = 8; - if (outputs & PIPE_LCD_ACTIVE) { + if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { min_p = 7; max_p = 98; } else { @@ -153,7 +171,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, +i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, int *outm1, int *outm2, int *outn, int *outp1, int *outp2) { I830Ptr pI830 = I830PTR(pScrn); @@ -170,7 +188,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, max_n = 8; min_p1 = 1; max_p1 = 8; - if (outputs & PIPE_LCD_ACTIVE) { + if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { if (target < 200000) /* XXX: Is this the right cutoff? */ p2 = 14; else @@ -203,7 +221,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, for (p1 = min_p1; p1 <= max_p1; p1++) { int clock, this_err; - if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, + if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n, p1, p2)) { continue; } @@ -372,7 +390,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) Bool ok, is_sdvo = FALSE, is_dvo = FALSE; Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE; int refclk, pixel_clock; - int outputs, i; + int i; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int fp_reg = (pipe == 0) ? FPA0 : FPB0; @@ -388,11 +406,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - if (pipe == 0) - outputs = pI830->operatingDevices & 0xff; - else - outputs = (pI830->operatingDevices >> 8) & 0xff; - if (I830ModesEqual(&pI830Pipe->curMode, pMode)) return TRUE; @@ -497,7 +510,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) } else { refclk = 48000; } - ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n, + ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -700,6 +713,22 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) } } +/** + * Return whether any outputs are connected to the specified pipe + */ + +static Bool +i830PipeInUse (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->num_outputs; i++) + if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + return TRUE; + return FALSE; +} + /** * This function configures the screens in clone mode on * all active outputs using a mode similar to the specified mode. @@ -720,8 +749,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) didLock = I830DRILock(pScrn); #endif - pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0; - pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0; + for (i = 0; i < pI830->availablePipes; i++) + pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i); for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 1b75649d..92c27af8 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -382,88 +382,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int index) ConfiguredMonitor = vbeDoEDID(pVbe, NULL); } -/* - * Returns a string matching the device corresponding to the first bit set - * in "device". savedDevice is then set to device with that bit cleared. - * Subsequent calls with device == -1 will use savedDevice. - */ - -static const char *displayDevices[] = { - "CRT", - "TV", - "DFP (digital flat panel)", - "LFP (local flat panel)", - "CRT2 (second CRT)", - "TV2 (second TV)", - "DFP2 (second digital flat panel)", - "LFP2 (second local flat panel)", - NULL -}; - -static const char * -DeviceToString(int device) -{ - static int savedDevice = -1; - int bit = 0; - const char *name; - - if (device == -1) { - device = savedDevice; - bit = 0; - } - - if (device == -1) - return NULL; - - while (displayDevices[bit]) { - if (device & (1 << bit)) { - name = displayDevices[bit]; - savedDevice = device & ~(1 << bit); - bit++; - return name; - } - bit++; - } - return NULL; -} - -static void -PrintDisplayDeviceInfo(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int pipe, n; - int displays; - - DPRINTF(PFX, "PrintDisplayDeviceInfo\n"); - - displays = pI830->operatingDevices; - if (displays == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No active display devices.\n"); - return; - } - - /* Check for active devices connected to each display pipe. */ - for (n = 0; n < pI830->availablePipes; n++) { - pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); - if (pipe) { - const char *name; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Currently active displays on Pipe %c:\n", PIPE_NAME(n)); - name = DeviceToString(pipe); - do { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name); - name = DeviceToString(-1); - } while (name); - - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No active displays on Pipe %c.\n", PIPE_NAME(n)); - } - } -} - static int I830DetectMemory(ScrnInfoPtr pScrn) { @@ -1242,9 +1160,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830PreInitDDC(pScrn); - pI830->MonType1 = PIPE_NONE; - pI830->MonType2 = PIPE_NONE; - +#if 0 + /* + * This moves to generic RandR-based configuration code + */ if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { char *Mon1; @@ -1329,7 +1248,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) else pI830->pipe = 1; - pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. * @@ -1375,7 +1293,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pipe = 0; else pI830->pipe = 1; - pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; if (pI830->MonType1 != 0 && pI830->MonType2 != 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1384,11 +1301,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->operatingDevices = pI8301->operatingDevices; pI830->pipe = !pI8301->pipe; pI830->MonType1 = pI8301->MonType1; pI830->MonType2 = pI8301->MonType2; } +#endif if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { if (pI830->availablePipes == 1) { @@ -1408,38 +1325,23 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } - /* Perform the pipe assignment of outputs. This code shouldn't exist, - * but for now we're supporting the existing MonitorLayout configuration - * scheme. + /* Perform the pipe assignment of outputs. This is a kludge until + * we have better configuration support in the generic RandR code */ for (i = 0; i < pI830->num_outputs; i++) { pI830->output[i].disabled = FALSE; switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: - if (pI830->MonType1 & PIPE_LFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_LFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + /* LVDS must live on pipe B for two-pipe devices */ + pI830->output[i].pipe = pI830->availablePipes - 1; break; case I830_OUTPUT_ANALOG: - if (pI830->MonType1 & PIPE_CRT) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_CRT) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + pI830->output[i].pipe = 0; break; case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: - if (pI830->MonType1 & PIPE_DFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_DFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + pI830->output[i].pipe = 0; break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); @@ -1447,8 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - - +#if 0 pI830->CloneRefresh = 60; /* default to 60Hz */ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH, &(pI830->CloneRefresh))) { @@ -1471,6 +1372,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } } +#endif pI830->rotation = RR_Rotate_0; if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { @@ -1646,8 +1548,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - PrintDisplayDeviceInfo(pScrn); - +#if 0 if (xf86IsEntityShared(pScrn->entityList[0])) { if (!I830IsPrimary(pScrn)) { /* This could be made to work with a little more fiddling */ @@ -1663,6 +1564,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n", pI830->pipe ? "B" : "A"); } +#endif /* Alloc our pointers for the primary head */ if (I830IsPrimary(pScrn)) { @@ -2872,17 +2774,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } #endif - if (xf86IsEntityShared(pScrn->entityList[0])) { - /* PreInit failed on the second head, so make sure we turn it off */ - if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { - if (pI830->pipe == 0) { - pI830->operatingDevices &= 0xFF; - } else { - pI830->operatingDevices &= 0xFF00; - } - } - } - pI830->starting = TRUE; /* Alloc our pointers for the primary head */ @@ -3269,6 +3160,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); + int i; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); @@ -3279,9 +3171,9 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) pI830->AccelInfoRec->NeedToSync = FALSE; } - i830PipeSetBase(pScrn, pI830->pipe, x, y); - if (pI830->Clone) - i830PipeSetBase(pScrn, !pI830->pipe, x, y); + for (i = 0; i < pI830->availablePipes; i++) + if (pI830->pipes[i].planeEnabled) + i830PipeSetBase(pScrn, i, x, y); } static void diff --git a/src/i830_randr.c b/src/i830_randr.c index d0972830..afa18483 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -492,45 +492,31 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) I830PipePtr pI830Pipe = &pI830->pipes[pipe]; int i, j; DisplayModePtr pipeMode = &pI830Pipe->curMode; - int pipe_type; x = pI830Pipe->x; y = pI830Pipe->y; rotation = RR_Rotate_0; numOutputs = 0; + mode = NULL; for (i = 0; i < pI830->num_outputs; i++) { output = &pI830->output[i]; - /* - * Valid crtcs - */ - switch (output->type) { - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - pipe_type = PIPE_DFP; - break; - case I830_OUTPUT_ANALOG: - pipe_type = PIPE_CRT; - break; - case I830_OUTPUT_LVDS: - pipe_type = PIPE_LFP; - break; - case I830_OUTPUT_TVOUT: - pipe_type = PIPE_TV; - break; - default: - pipe_type = PIPE_NONE; - break; - } - if (pI830->operatingDevices & (pipe_type << (pipe << 3))) + if (!output->disabled && output->pipe == pipe) { rrout = randrp->outputs[i]; outputs[numOutputs++] = rrout; + /* + * We make copies of modes, so pointer equality + * isn't sufficient + */ for (j = 0; j < rrout->numModes; j++) { DisplayModePtr outMode = rrout->modes[j]->devPrivate; if (I830ModesEqual(pipeMode, outMode)) + { mode = rrout->modes[j]; + break; + } } } } @@ -571,14 +557,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, } else { - CARD32 operatingDevices = pI830->operatingDevices; - - if (pipe == 0) - pI830->operatingDevices &= ~0xff; - else - pI830->operatingDevices &= ~0xff00; i830DisableUnusedFunctions (pScrn); - pI830->operatingDevices = operatingDevices; } randrp->modes[pipe] = display_mode; } @@ -614,7 +593,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int p; int clone_types; int crtc_types; - int pipe_type; int pipe; int subpixel; DisplayModePtr modes, mode; @@ -644,7 +622,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); - pipe_type = PIPE_DFP; subpixel = SubPixelHorizontalRGB; break; case I830_OUTPUT_ANALOG: @@ -652,13 +629,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen) clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); - pipe_type = PIPE_CRT; subpixel = SubPixelNone; break; case I830_OUTPUT_LVDS: crtc_types = (1 << 1); clone_types = (1 << I830_OUTPUT_LVDS); - pipe_type = PIPE_LFP; subpixel = SubPixelHorizontalRGB; possibleOptions = (RROutputOptionScaleNone| RROutputOptionScaleMaxAspect | @@ -669,32 +644,27 @@ I830RandRSetInfo12 (ScreenPtr pScreen) crtc_types = ((1 << 0) | (1 << 1)); clone_types = (1 << I830_OUTPUT_TVOUT); - pipe_type = PIPE_TV; subpixel = SubPixelNone; break; default: crtc_types = 0; clone_types = 0; - pipe_type = PIPE_NONE; subpixel = SubPixelUnknown; break; } - ncrtc = 0; - pipe = -1; - crtc = NULL; - for (j = 0; j < pI830->availablePipes; j++) + if (!output->disabled) { -#if 0 - /* Can't flip outputs among crtcs yet */ - if (crtc_types & (1 << j)) - crtcs[ncrtc++] = randrp->crtcs[j]; -#endif - if (pI830->operatingDevices & (pipe_type << (j << 3))) - { - pipe = j; - crtc = randrp->crtcs[j]; - crtcs[ncrtc++] = crtc; - } + /* Can't flip outputs among crtcs yet */ + ncrtc = 1; + pipe = output->pipe; + crtc = randrp->crtcs[pipe]; + crtcs[0] = randrp->crtcs[pipe]; + } + else + { + ncrtc = 0; + pipe = -1; + crtc = NULL; } if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc)) return FALSE; diff --git a/src/i830_video.c b/src/i830_video.c index 47f4a03f..a5cd77cf 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -722,7 +722,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) pPriv->brightness = 0; pPriv->contrast = 64; pPriv->saturation = 128; - pPriv->pipe = pI830->pipe; /* default to current pipe */ + pPriv->pipe = 0; /* XXX must choose pipe wisely */ pPriv->linear = NULL; pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; @@ -3592,6 +3592,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) pPriv->overlayOK = TRUE; +#if 0 + /* XXX Must choose pipe wisely */ /* ensure pipe is updated on mode switch */ if (!pI830->Clone) { if (pPriv->pipe != pI830->pipe) { @@ -3600,6 +3602,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) pPriv->pipe = pI830->pipe; } } +#endif if (!IS_I965G(pI830)) { if (pPriv->pipe == 0) { @@ -3628,8 +3631,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } /* Check we have an LFP connected */ - if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || - (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) { + if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) + { size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); hsize = (size >> 16) & 0x7FF; vsize = size & 0x7FF; From 7fcb555735a58e19ccc10875b211402983170a87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Nov 2006 00:52:21 -0800 Subject: [PATCH 231/257] Rename availablePipes to num_pipes --- src/i830.h | 2 +- src/i830_crt.c | 4 ++-- src/i830_cursor.c | 12 ++++++------ src/i830_display.c | 8 ++++---- src/i830_driver.c | 30 +++++++++++++++--------------- src/i830_randr.c | 6 +++--- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9e5c8442..333b595d 100644 --- a/src/i830.h +++ b/src/i830.h @@ -447,7 +447,7 @@ typedef struct _I830Rec { Bool checkDevices; /* [0] is Pipe A, [1] is Pipe B. */ - int availablePipes; + int num_pipes; /* [0] is display plane A, [1] is display plane B. */ I830PipeRec pipes[MAX_DISPLAY_PIPES]; diff --git a/src/i830_crt.c b/src/i830_crt.c index 4c6c3ca5..adc2d624 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -174,12 +174,12 @@ i830_crt_detect_load(ScrnInfoPtr pScrn) int pipeconf_reg, bclrpat_reg, dpll_reg; int pipe; - for (pipe = 0; pipe < pI830->availablePipes; pipe++) + for (pipe = 0; pipe < pI830->num_pipes; pipe++) if (!pI830->pipes[pipe].planeEnabled) break; /* No available pipes for load detection */ - if (pipe == pI830->availablePipes) + if (pipe == pI830->num_pipes) return FALSE; if (pipe == 0) { diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 6b0e58c4..05e93faf 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -86,7 +86,7 @@ I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe) int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); I830MemRange *cursor_mem; - if (pipe >= pI830->availablePipes) + if (pipe >= pI830->num_pipes) FatalError("Bad pipe number for cursor base setting\n"); if (pI830->CursorIsARGB) @@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn) int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) pI830->pipes[i].cursorShown = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; temp = INREG(cursor_control); @@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= hotspotx; y -= hotspoty; - for (pipe = 0; pipe < pI830->availablePipes; pipe++) + for (pipe = 0; pipe < pI830->num_pipes; pipe++) { I830PipePtr pI830Pipe = &pI830->pipes[pipe]; DisplayModePtr mode = &pI830Pipe->curMode; @@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - for (pipe = 0; pipe < pI830->availablePipes; pipe++) + for (pipe = 0; pipe < pI830->num_pipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } @@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - for (pipe = 0; pipe < pI830->availablePipes; pipe++) + for (pipe = 0; pipe < pI830->num_pipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } diff --git a/src/i830_display.c b/src/i830_display.c index c9b6b4dd..6c5645b9 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -673,7 +673,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (i = 0; i < pI830->availablePipes; i++) { + for (i = 0; i < pI830->num_pipes; i++) { I830PipePtr pI830Pipe = &pI830->pipes[i]; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; @@ -749,13 +749,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) didLock = I830DRILock(pScrn); #endif - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i); for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) { if (pI830->pipes[i].planeEnabled) ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), @@ -815,7 +815,7 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n"); - for (i = 0; i < pI830->availablePipes; i++) { + for (i = 0; i < pI830->num_pipes; i++) { CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i); xf86DrvMsg(pScrn->scrnIndex, X_INFO, diff --git a/src/i830_driver.c b/src/i830_driver.c index 92c27af8..8d9712ae 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -542,7 +542,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - for(p=0; p < pI830->availablePipes; p++) { + for(p=0; p < pI830->num_pipes; p++) { I830PipePtr pI830Pipe = &pI830->pipes[p]; if (p == 0) { @@ -1080,14 +1080,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) - pI830->availablePipes = 1; + pI830->num_pipes = 1; else if (IS_MOBILE(pI830) || IS_I9XX(pI830)) - pI830->availablePipes = 2; + pI830->num_pipes = 2; else - pI830->availablePipes = 1; + pI830->num_pipes = 1; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", - pI830->availablePipes, pI830->availablePipes > 1 ? "s" : ""); + pI830->num_pipes, pI830->num_pipes > 1 ? "s" : ""); /* * Get the pre-allocated (stolen) memory size. @@ -1231,7 +1231,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } while (sub); } - if (pI830->availablePipes == 1 && pI830->MonType2 != PIPE_NONE) { + if (pI830->num_pipes == 1 && pI830->MonType2 != PIPE_NONE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 2 cannot be specified on single pipe devices\n"); return FALSE; @@ -1308,7 +1308,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #endif if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { - if (pI830->availablePipes == 1) { + if (pI830->num_pipes == 1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable Clone Mode because this is a single pipe device\n"); PreInitCleanup(pScrn); @@ -1334,7 +1334,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: /* LVDS must live on pipe B for two-pipe devices */ - pI830->output[i].pipe = pI830->availablePipes - 1; + pI830->output[i].pipe = pI830->num_pipes - 1; break; case I830_OUTPUT_ANALOG: pI830->output[i].pipe = 0; @@ -2091,7 +2091,7 @@ SaveHWState(ScrnInfoPtr pScrn) temp = INREG(PIPEACONF); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", (unsigned long) temp); - if (pI830->availablePipes == 2) { + if (pI830->num_pipes == 2) { temp = INREG(PIPEBCONF); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", (unsigned long) temp); @@ -2123,7 +2123,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); } - if(pI830->availablePipes == 2) { + if(pI830->num_pipes == 2) { pI830->savePIPEBCONF = INREG(PIPEBCONF); pI830->savePIPEBSRC = INREG(PIPEBSRC); pI830->saveDSPBCNTR = INREG(DSPBCNTR); @@ -2234,7 +2234,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); } - if(pI830->availablePipes == 2) { + if(pI830->num_pipes == 2) { OUTREG(FPB0, pI830->saveFPB0); OUTREG(FPB1, pI830->saveFPB1); OUTREG(DPLL_B, pI830->saveDPLL_B); @@ -3171,7 +3171,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) pI830->AccelInfoRec->NeedToSync = FALSE; } - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) if (pI830->pipes[i].planeEnabled) i830PipeSetBase(pScrn, i, x, y); } @@ -3279,7 +3279,7 @@ I830EnterVT(int scrnIndex, int flags) SetHWOperatingState(pScrn); /* Mark that we'll need to re-set the mode for sure */ - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode)); if (!i830SetMode(pScrn, pScrn->currentMode)) @@ -3423,7 +3423,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { - for (i = 0; i < pI830->availablePipes; i++) { + for (i = 0; i < pI830->num_pipes; i++) { if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; @@ -3474,7 +3474,7 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode); } - for (i = 0; i < pI830->availablePipes; i++) { + for (i = 0; i < pI830->num_pipes; i++) { if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; diff --git a/src/i830_randr.c b/src/i830_randr.c index afa18483..84727a61 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -752,7 +752,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) return FALSE; } - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) I830RandRCrtcNotify (randrp->crtcs[i]); return TRUE; } @@ -785,7 +785,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) /* * Create RandR resources, then probe them */ - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) { randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); RRCrtcGammaSetSize (randrp->crtcs[i], 256); @@ -821,7 +821,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmHeight); } - for (i = 0; i < pI830->availablePipes; i++) + for (i = 0; i < pI830->num_pipes; i++) i830PipeSetBase(pScrn, i, 0, 0); return I830RandRSetInfo12 (pScreen); From 15ef08046bcc3e746453301379f7c5d1bf929ee1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Nov 2006 13:29:56 -0800 Subject: [PATCH 232/257] Move remaining pipe mode setting logic to i830PipeSetMode --- src/i830_display.c | 86 +++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 6c5645b9..795c6f99 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -374,6 +374,22 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) return pMode; } +/** + * Return whether any outputs are connected to the specified pipe + */ + +static Bool +i830PipeInUse (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->num_outputs; i++) + if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + return TRUE; + return FALSE; +} + /** * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. @@ -405,6 +421,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; + Bool ret = FALSE; +#ifdef XF86DRI + Bool didLock = FALSE; +#endif if (I830ModesEqual(&pI830Pipe->curMode, pMode)) return TRUE; @@ -412,10 +432,21 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", pMode->Clock); + pI830->pipes[pipe].planeEnabled = i830PipeInUse (pScrn, pipe); + + if (!pI830->pipes[pipe].planeEnabled) + return TRUE; + +#ifdef XF86DRI + didLock = I830DRILock(pScrn); +#endif + for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].pipe != pipe || pI830->output[i].disabled) continue; + pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); + switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: is_lvds = TRUE; @@ -438,18 +469,18 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable LVDS and non-LVDS on the same pipe\n"); - return FALSE; + goto done; } if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable a TV and any other output on the same " "pipe\n"); - return FALSE; + goto done; } if (pipe == 0 && is_lvds) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't support LVDS on pipe A\n"); - return FALSE; + goto done; } htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); @@ -515,7 +546,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't find PLL settings for mode!\n"); - return FALSE; + goto done; } dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; @@ -629,7 +660,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) OUTREG(PFIT_CONTROL, 0); - OUTREG(PFIT_PGM_RATIOS, 0x10001000); OUTREG(DSPARB, (47 << 0) | (95 << 7)); OUTREG(htot_reg, htot); @@ -653,7 +683,13 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) pI830Pipe->curMode = *pMode; - return TRUE; + ret = TRUE; +done: +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn); +#endif + return ret; } void @@ -713,22 +749,6 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) } } -/** - * Return whether any outputs are connected to the specified pipe - */ - -static Bool -i830PipeInUse (ScrnInfoPtr pScrn, int pipe) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - - for (i = 0; i < pI830->num_outputs; i++) - if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) - return TRUE; - return FALSE; -} - /** * This function configures the screens in clone mode on * all active outputs using a mode similar to the specified mode. @@ -738,28 +758,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; -#ifdef XF86DRI - Bool didLock = FALSE; -#endif int i; DPRINTF(PFX, "i830SetMode\n"); -#ifdef XF86DRI - didLock = I830DRILock(pScrn); -#endif - - for (i = 0; i < pI830->num_pipes; i++) - pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i); - - for (i = 0; i < pI830->num_outputs; i++) - pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); - for (i = 0; i < pI830->num_pipes; i++) { - if (pI830->pipes[i].planeEnabled) - ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), - i); + ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), i); if (!ok) goto done; } @@ -797,11 +802,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) I830DRISetVBlankInterrupt (pScrn, TRUE); #endif done: -#ifdef XF86DRI - if (didLock) - I830DRIUnlock(pScrn); -#endif - i830DumpRegs (pScrn); i830_sdvo_dump(pScrn); return ok; From 68c3185046b27ab936ca6c92b924b443b3cd6fce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Nov 2006 13:30:32 -0800 Subject: [PATCH 233/257] Avoid crashing when disabling sdvo output. XXX --- src/i830_sdvo.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index da611590..4d4817a5 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -517,8 +517,8 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, { I830Ptr pI830 = I830PTR(pScrn); struct i830_sdvo_priv *dev_priv = output->dev_priv; - CARD16 width = mode->CrtcHDisplay; - CARD16 height = mode->CrtcVDisplay; + CARD16 width; + CARD16 height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; struct i830_sdvo_dtd output_dtd; @@ -526,6 +526,11 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, memset(&no_outputs, 0, sizeof(no_outputs)); + if (!mode) + return; + width = mode->CrtcHDisplay; + height = mode->CrtcVDisplay; + /* do some mode translations */ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; From 5a355c72614ed77f2000e5ede45f3ff5990c79d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Nov 2006 18:51:28 -0800 Subject: [PATCH 234/257] Fix CRT output on 965 chipset. A few more register settings are needed to get CRT output working on the 965 chipset, in particular the the SDVO/UDI clock multiplier register needed to get set to the default value (3). No, I really don't know what this does, but it does get the CRT running at a wide range of sizes. --- src/i810_reg.h | 17 ++++++++++++++--- src/i830_crt.c | 8 +++++++- src/i830_display.c | 10 +++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/i810_reg.h b/src/i810_reg.h index e126904f..0ece7ee8 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -800,11 +800,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ # define PLL_REF_INPUT_DREFCLK (0 << 13) # define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ -# define PLL_REF_INPUT_TVCLKINBC (2 << 13) +# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ # define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +# define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) # define DISPLAY_RATE_SELECT_FPA1 (1 << 8) /** - * SDVO multiplier for 945G/GM. + * SDVO multiplier for 945G/GM. Not used on 965. * * \sa DPLL_MD_UDI_MULTIPLIER_MASK */ @@ -848,7 +856,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 # define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 -/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. */ +/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ # define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f # define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 /** @} */ diff --git a/src/i830_crt.c b/src/i830_crt.c index adc2d624..a7b04937 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -101,8 +101,14 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); + int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; + CARD32 adpa; - CARD32 adpa; + /* + * Not quite sure precisely what this does... + */ + if (IS_I965G(pI830)) + OUTREG(dpll_md_reg, 0x3 << DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT); adpa = ADPA_DAC_ENABLE; diff --git a/src/i830_display.c b/src/i830_display.c index 795c6f99..077e318c 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -570,6 +570,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } + if (IS_I965G(pI830)) + dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { dpll |= (p1 - 2) << 16; if (p2 == 4) @@ -660,8 +662,14 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) OUTREG(PFIT_CONTROL, 0); + /* + * Docs say to not mess with this register. I think we will + * need to eventually though + */ +#if 0 OUTREG(DSPARB, (47 << 0) | (95 << 7)); - +#endif + OUTREG(htot_reg, htot); OUTREG(hblank_reg, hblank); OUTREG(hsync_reg, hsync); From 997e8c9bb4235cab1fff4738387df9afcbea0a03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Nov 2006 18:56:33 -0800 Subject: [PATCH 235/257] Don't allocate stuff in the first 256K of video memory (GATT?) Letting the ring buffer or other objects be allocated within the lowest portion of memory appears to trash some memory mapping data; I'm assuming this is the GATT table on the 965. Just marking this out of bounds for allocation fixes this problem. --- src/i830_driver.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 8d9712ae..b6320730 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -776,6 +776,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pointer pVBEModule = NULL; Bool enable; const char *chipname; + int mem_skip; if (pScrn->numEntities != 1) return FALSE; @@ -1092,8 +1093,15 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* * Get the pre-allocated (stolen) memory size. */ - pI830->StolenMemory.Size = I830DetectMemory(pScrn); - pI830->StolenMemory.Start = 0; + + mem_skip = 0; + + /* On 965, it looks like the GATT table is inside the aperture? */ + if (IS_I965G(pI830)) + mem_skip = pI830->FbMapSize >> 10; + + pI830->StolenMemory.Size = I830DetectMemory(pScrn) - mem_skip; + pI830->StolenMemory.Start = mem_skip; pI830->StolenMemory.End = pI830->StolenMemory.Size; /* Find the maximum amount of agpgart memory available. */ @@ -1341,7 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) break; case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: - pI830->output[i].pipe = 0; + pI830->output[i].pipe = 1; break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); From beb89163d73376e70870e6e2a6b19863f3a058b1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Nov 2006 19:06:45 -0800 Subject: [PATCH 236/257] DSPSURF must be page aligned. Place intra-screen offset in DSPBASE. DSPASURF/DSPBSURF can only take page aligned values, ignoring the lower order bits. So, place the offset for the output within the frame buffer in the DSPABASE/DSPBBASE registers instead. --- src/i830_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 077e318c..6804a4d8 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -268,8 +268,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) } if (IS_I965G(pI830)) { - OUTREG(dspbase, 0); - OUTREG(dspsurf, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); + OUTREG(dspsurf, Start); } else { OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } From 94a3731c2b4f2ea2e696a8c87dccc0d214d41e8e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Nov 2006 18:26:48 -0800 Subject: [PATCH 237/257] Move PFIT_CONTROL disable for G965 up before post_set_mode. Also, remove setting of some other random registers that appears to have been spammed in at the same time, and don't try to disable on the I830, before this register existed. --- src/i830_display.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index e36b5efc..672bc533 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -609,21 +609,20 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); + /* + * If the panel fitter is stuck on our pipe, turn it off. + * The LVDS output will set it as necessary in post_set_mode. + */ + if (!IS_I830(pI830)) { + if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) + OUTREG(PFIT_CONTROL, 0); + } + for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].pipe == pipe) pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode); } - /* - * If the panel fitter is stuck on our pipe, turn it off - * the LVDS output will whack it correctly if it needs it - */ - if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) - OUTREG(PFIT_CONTROL, 0); - - OUTREG(PFIT_PGM_RATIOS, 0x10001000); - OUTREG(DSPARB, (47 << 0) | (95 << 7)); - OUTREG(htot_reg, htot); OUTREG(hblank_reg, hblank); OUTREG(hsync_reg, hsync); From d0ef9e99acb9e999e1b6d3eb76edc6355555043b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Nov 2006 18:30:46 -0800 Subject: [PATCH 238/257] Restore PFIT_CONTROL before turning the LVDS back on in the restore method. --- src/i830_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 79b4f606..8dcda421 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2380,6 +2380,8 @@ RestoreHWState(ScrnInfoPtr pScrn) } } + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + for (i = 0; i < pI830->num_outputs; i++) { pI830->output[i].restore(pScrn, &pI830->output[i]); } @@ -2409,8 +2411,6 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - i830CompareRegsToSnapshot(pScrn); return TRUE; From 0b2d36d4f038c4e8fa08632b6f1368627f010392 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Nov 2006 23:29:12 -0800 Subject: [PATCH 239/257] Use pI830->availablePipes instead of MAX_DISPLAY_PIPES everywhere (cherry picked from e4bcec796e80e9fd66ab0c36394f5946915531f1 commit) --- src/i830.h | 5 ++--- src/i830_cursor.c | 10 +++++----- src/i830_display.c | 4 ++-- src/i830_driver.c | 2 +- src/i830_randr.c | 8 ++++---- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/i830.h b/src/i830.h index b93ab3c9..84c0dbea 100644 --- a/src/i830.h +++ b/src/i830.h @@ -313,8 +313,6 @@ typedef struct _I830Rec { */ DisplayModePtr savedCurrentMode; - I830PipeRec pipes[MAX_DISPLAY_PIPES]; - Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -481,7 +479,8 @@ typedef struct _I830Rec { /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; /* [0] is display plane A, [1] is display plane B. */ - + I830PipeRec pipes[MAX_DISPLAY_PIPES]; + /* Driver phase/state information */ Bool preinit; Bool starting; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 0b7e772b..6b0e58c4 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -180,11 +180,11 @@ I830InitHWCursor(ScrnInfoPtr pScrn) int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) pI830->pipes[i].cursorShown = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; temp = INREG(cursor_control); @@ -484,7 +484,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= hotspotx; y -= hotspoty; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { I830PipePtr pI830Pipe = &pI830->pipes[pipe]; DisplayModePtr mode = &pI830Pipe->curMode; @@ -550,7 +550,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } @@ -563,7 +563,7 @@ I830HideCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + for (pipe = 0; pipe < pI830->availablePipes; pipe++) I830SetPipeCursor (pScrn, pipe, TRUE); } diff --git a/src/i830_display.c b/src/i830_display.c index 672bc533..2f9b3fd9 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -666,7 +666,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) { + for (i = 0; i < pI830->availablePipes; i++) { I830PipePtr pI830Pipe = &pI830->pipes[i]; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; @@ -732,7 +732,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { if (pI830->pipes[i].planeEnabled) ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, diff --git a/src/i830_driver.c b/src/i830_driver.c index 8dcda421..78f83d76 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3413,7 +3413,7 @@ I830EnterVT(int scrnIndex, int flags) SetHWOperatingState(pScrn); /* Mark that we'll need to re-set the mode for sure */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode)); if (!i830SetMode(pScrn, pScrn->currentMode)) diff --git a/src/i830_randr.c b/src/i830_randr.c index 8b6ad493..4f3cbee4 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -682,7 +682,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) ncrtc = 0; pipe = -1; crtc = NULL; - for (j = 0; j < MAX_DISPLAY_PIPES; j++) + for (j = 0; j < pI830->availablePipes; j++) { #if 0 /* Can't flip outputs among crtcs yet */ @@ -782,7 +782,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) return FALSE; } - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) I830RandRCrtcNotify (randrp->crtcs[i]); return TRUE; } @@ -815,7 +815,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) /* * Create RandR resources, then probe them */ - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) { randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); RRCrtcGammaSetSize (randrp->crtcs[i], 256); @@ -851,7 +851,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmHeight); } - for (i = 0; i < MAX_DISPLAY_PIPES; i++) + for (i = 0; i < pI830->availablePipes; i++) i830PipeSetBase(pScrn, i, 0, 0); return I830RandRSetInfo12 (pScreen); From f1ff01e31eb8e9dc05190bf1a8b318d4f587f64a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Nov 2006 00:46:18 -0800 Subject: [PATCH 240/257] Eliminate operatingDevices member and PIPE_* values. operatingDevices and MonType1/MonType2 duplicate information already stored in the device structures. Eliminate them and replace uses with direct references to the appropriate other data. (cherry picked from 3ab7f9693217d8fe993bdc94c376b219b0082961 commit) --- src/i830.h | 30 ++-------- src/i830_crt.c | 6 +- src/i830_display.c | 57 +++++++++++++----- src/i830_driver.c | 146 ++++++--------------------------------------- src/i830_randr.c | 72 +++++++--------------- src/i830_video.c | 9 ++- 6 files changed, 99 insertions(+), 221 deletions(-) diff --git a/src/i830.h b/src/i830.h index 84c0dbea..9de73948 100644 --- a/src/i830.h +++ b/src/i830.h @@ -86,26 +86,6 @@ typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr; * Paulo César Pereira de Andrade . */ -#define PIPE_CRT_ID 0 -#define PIPE_TV_ID 1 -#define PIPE_DFP_ID 2 -#define PIPE_LFP_ID 3 -#define PIPE_CRT2_ID 4 -#define PIPE_TV2_ID 5 -#define PIPE_DFP2_ID 6 -#define PIPE_LFP2_ID 7 -#define PIPE_NUM_ID 8 - -#define PIPE_NONE 0<<0 -#define PIPE_CRT 1<<0 -#define PIPE_TV 1<<1 -#define PIPE_DFP 1<<2 -#define PIPE_LFP 1<<3 -#define PIPE_CRT2 1<<4 -#define PIPE_TV2 1<<5 -#define PIPE_DFP2 1<<6 -#define PIPE_LFP2 1<<7 - typedef struct _I830Rec *I830Ptr; typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr, @@ -319,7 +299,9 @@ typedef struct _I830Rec { int CloneVDisplay; I830EntPtr entityPrivate; +#if 0 int pipe, origPipe; +#endif int init; unsigned int bufferOffset; /* for I830SelectBuffer */ @@ -396,9 +378,6 @@ typedef struct _I830Rec { Bool CursorIsARGB; CursorPtr pCurs; - int MonType1; - int MonType2; - DGAModePtr DGAModes; int numDGAModes; Bool DGAactive; @@ -474,7 +453,6 @@ typedef struct _I830Rec { CARD32 saveSWF4; Bool checkDevices; - int operatingDevices; /* [0] is Pipe A, [1] is Pipe B. */ int availablePipes; @@ -668,6 +646,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* i830_display.c */ +Bool +i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type); + /* i830_crt.c */ void i830_crt_init(ScrnInfoPtr pScrn); diff --git a/src/i830_crt.c b/src/i830_crt.c index 4c704b2c..9287a205 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -170,7 +170,7 @@ static Bool i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 adpa, pipeconf; + CARD32 adpa, pipeconf, bclrpat; CARD8 st00; int pipeconf_reg, bclrpat_reg, dpll_reg; int pipe; @@ -198,9 +198,10 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); } - /* Set the border color to red, green. Maybe we should save/restore this + /* Set the border color to purple. Maybe we should save/restore this * reg. */ + bclrpat = INREG(bclrpat_reg); OUTREG(bclrpat_reg, 0x00500050); /* Force the border color through the active region */ @@ -211,6 +212,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) st00 = pI830->readStandard(pI830, 0x3c2); /* Restore previous settings */ + OUTREG(bclrpat_reg, bclrpat); OUTREG(pipeconf_reg, pipeconf); OUTREG(ADPA, adpa); diff --git a/src/i830_display.c b/src/i830_display.c index 2f9b3fd9..c1fc562b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -60,6 +60,24 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) m1, m2, n, p1, p2); } +/** + * Returns whether any output on the specified pipe is an LVDS output + */ +Bool +i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->num_outputs; i++) + if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + { + if (pI830->output[i].type == type) + return TRUE; + } + return FALSE; +} + /** * Returns whether the given set of divisors are valid for a given refclk with * the given outputs. @@ -68,7 +86,7 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, +i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2, int n, int p1, int p2) { I830Ptr pI830 = I830PTR(pScrn); @@ -87,7 +105,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, max_n = 8; min_p1 = 1; max_p1 = 8; - if (outputs & PIPE_LCD_ACTIVE) { + if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { min_p = 7; max_p = 98; } else { @@ -153,7 +171,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int outputs, int refclk, int m1, int m2, * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, +i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, int *outm1, int *outm2, int *outn, int *outp1, int *outp2) { I830Ptr pI830 = I830PTR(pScrn); @@ -170,7 +188,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, max_n = 8; min_p1 = 1; max_p1 = 8; - if (outputs & PIPE_LCD_ACTIVE) { + if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { if (target < 200000) /* XXX: Is this the right cutoff? */ p2 = 14; else @@ -203,7 +221,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int outputs, int target, int refclk, for (p1 = min_p1; p1 <= max_p1; p1++) { int clock, this_err; - if (!i830PllIsValid(pScrn, outputs, refclk, m1, m2, n, + if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n, p1, p2)) { continue; } @@ -377,7 +395,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, Bool ok, is_sdvo = FALSE, is_dvo = FALSE; Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE; int refclk, pixel_clock; - int outputs, i; + int i; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int fp_reg = (pipe == 0) ? FPA0 : FPB0; @@ -393,11 +411,6 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - if (pipe == 0) - outputs = pI830->operatingDevices & 0xff; - else - outputs = (pI830->operatingDevices >> 8) & 0xff; - if (I830ModesEqual(&pI830Pipe->curMode, pMode)) return TRUE; @@ -502,7 +515,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, } else { refclk = 48000; } - ok = i830FindBestPLL(pScrn, outputs, pixel_clock, refclk, &m1, &m2, &n, + ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -706,6 +719,22 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) } } +/** + * Return whether any outputs are connected to the specified pipe + */ + +static Bool +i830PipeInUse (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + + for (i = 0; i < pI830->num_outputs; i++) + if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + return TRUE; + return FALSE; +} + /** * This function configures the screens in clone mode on * all active outputs using a mode similar to the specified mode. @@ -726,8 +755,8 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) didLock = I830DRILock(pScrn); #endif - pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0; - pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0; + for (i = 0; i < pI830->availablePipes; i++) + pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i); for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); diff --git a/src/i830_driver.c b/src/i830_driver.c index 78f83d76..e6cd9bcb 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -387,88 +387,6 @@ I830ProbeDDC(ScrnInfoPtr pScrn, int index) ConfiguredMonitor = vbeDoEDID(pVbe, NULL); } -/* - * Returns a string matching the device corresponding to the first bit set - * in "device". savedDevice is then set to device with that bit cleared. - * Subsequent calls with device == -1 will use savedDevice. - */ - -static const char *displayDevices[] = { - "CRT", - "TV", - "DFP (digital flat panel)", - "LFP (local flat panel)", - "CRT2 (second CRT)", - "TV2 (second TV)", - "DFP2 (second digital flat panel)", - "LFP2 (second local flat panel)", - NULL -}; - -static const char * -DeviceToString(int device) -{ - static int savedDevice = -1; - int bit = 0; - const char *name; - - if (device == -1) { - device = savedDevice; - bit = 0; - } - - if (device == -1) - return NULL; - - while (displayDevices[bit]) { - if (device & (1 << bit)) { - name = displayDevices[bit]; - savedDevice = device & ~(1 << bit); - bit++; - return name; - } - bit++; - } - return NULL; -} - -static void -PrintDisplayDeviceInfo(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int pipe, n; - int displays; - - DPRINTF(PFX, "PrintDisplayDeviceInfo\n"); - - displays = pI830->operatingDevices; - if (displays == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No active display devices.\n"); - return; - } - - /* Check for active devices connected to each display pipe. */ - for (n = 0; n < pI830->availablePipes; n++) { - pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); - if (pipe) { - const char *name; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Currently active displays on Pipe %c:\n", PIPE_NAME(n)); - name = DeviceToString(pipe); - do { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name); - name = DeviceToString(-1); - } while (name); - - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No active displays on Pipe %c.\n", PIPE_NAME(n)); - } - } -} - static int I830DetectMemory(ScrnInfoPtr pScrn) { @@ -1268,9 +1186,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830PreInitDDC(pScrn); - pI830->MonType1 = PIPE_NONE; - pI830->MonType2 = PIPE_NONE; - +#if 0 + /* + * This moves to generic RandR-based configuration code + */ if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && I830IsPrimary(pScrn)) { char *Mon1; @@ -1355,7 +1274,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) else pI830->pipe = 1; - pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; } else if (I830IsPrimary(pScrn)) { /* Choose a default set of outputs to use based on what we've detected. * @@ -1401,7 +1319,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pipe = 0; else pI830->pipe = 1; - pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; if (pI830->MonType1 != 0 && pI830->MonType2 != 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1410,11 +1327,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); - pI830->operatingDevices = pI8301->operatingDevices; pI830->pipe = !pI8301->pipe; pI830->MonType1 = pI8301->MonType1; pI830->MonType2 = pI8301->MonType2; } +#endif if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { if (pI830->availablePipes == 1) { @@ -1434,38 +1351,23 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } - /* Perform the pipe assignment of outputs. This code shouldn't exist, - * but for now we're supporting the existing MonitorLayout configuration - * scheme. + /* Perform the pipe assignment of outputs. This is a kludge until + * we have better configuration support in the generic RandR code */ for (i = 0; i < pI830->num_outputs; i++) { pI830->output[i].disabled = FALSE; switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: - if (pI830->MonType1 & PIPE_LFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_LFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + /* LVDS must live on pipe B for two-pipe devices */ + pI830->output[i].pipe = pI830->availablePipes - 1; break; case I830_OUTPUT_ANALOG: - if (pI830->MonType1 & PIPE_CRT) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_CRT) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + pI830->output[i].pipe = 0; break; case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: - if (pI830->MonType1 & PIPE_DFP) - pI830->output[i].pipe = 0; - else if (pI830->MonType2 & PIPE_DFP) - pI830->output[i].pipe = 1; - else - pI830->output[i].disabled = TRUE; + pI830->output[i].pipe = 0; break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); @@ -1473,8 +1375,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - - +#if 0 pI830->CloneRefresh = 60; /* default to 60Hz */ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH, &(pI830->CloneRefresh))) { @@ -1497,6 +1398,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } } +#endif pI830->rotation = RR_Rotate_0; if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { @@ -1672,8 +1574,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - PrintDisplayDeviceInfo(pScrn); - +#if 0 if (xf86IsEntityShared(pScrn->entityList[0])) { if (!I830IsPrimary(pScrn)) { /* This could be made to work with a little more fiddling */ @@ -1689,6 +1590,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n", pI830->pipe ? "B" : "A"); } +#endif /* Alloc our pointers for the primary head */ if (I830IsPrimary(pScrn)) { @@ -2898,17 +2800,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } #endif - if (xf86IsEntityShared(pScrn->entityList[0])) { - /* PreInit failed on the second head, so make sure we turn it off */ - if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { - if (pI830->pipe == 0) { - pI830->operatingDevices &= 0xFF; - } else { - pI830->operatingDevices &= 0xFF00; - } - } - } - pI830->starting = TRUE; /* Alloc our pointers for the primary head */ @@ -3295,6 +3186,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); + int i; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); @@ -3305,9 +3197,9 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) pI830->AccelInfoRec->NeedToSync = FALSE; } - i830PipeSetBase(pScrn, pI830->pipe, x, y); - if (pI830->Clone) - i830PipeSetBase(pScrn, !pI830->pipe, x, y); + for (i = 0; i < pI830->availablePipes; i++) + if (pI830->pipes[i].planeEnabled) + i830PipeSetBase(pScrn, i, x, y); } static void diff --git a/src/i830_randr.c b/src/i830_randr.c index 4f3cbee4..d2228cfb 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -492,45 +492,31 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) I830PipePtr pI830Pipe = &pI830->pipes[pipe]; int i, j; DisplayModePtr pipeMode = &pI830Pipe->curMode; - int pipe_type; x = pI830Pipe->x; y = pI830Pipe->y; rotation = RR_Rotate_0; numOutputs = 0; + mode = NULL; for (i = 0; i < pI830->num_outputs; i++) { output = &pI830->output[i]; - /* - * Valid crtcs - */ - switch (output->type) { - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - pipe_type = PIPE_DFP; - break; - case I830_OUTPUT_ANALOG: - pipe_type = PIPE_CRT; - break; - case I830_OUTPUT_LVDS: - pipe_type = PIPE_LFP; - break; - case I830_OUTPUT_TVOUT: - pipe_type = PIPE_TV; - break; - default: - pipe_type = PIPE_NONE; - break; - } - if (pI830->operatingDevices & (pipe_type << (pipe << 3))) + if (!output->disabled && output->pipe == pipe) { rrout = randrp->outputs[i]; outputs[numOutputs++] = rrout; + /* + * We make copies of modes, so pointer equality + * isn't sufficient + */ for (j = 0; j < rrout->numModes; j++) { DisplayModePtr outMode = rrout->modes[j]->devPrivate; if (I830ModesEqual(pipeMode, outMode)) + { mode = rrout->modes[j]; + break; + } } } } @@ -571,14 +557,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, } else { - CARD32 operatingDevices = pI830->operatingDevices; - - if (pipe == 0) - pI830->operatingDevices &= ~0xff; - else - pI830->operatingDevices &= ~0xff00; i830DisableUnusedFunctions (pScrn); - pI830->operatingDevices = operatingDevices; } randrp->modes[pipe] = display_mode; } @@ -614,7 +593,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) int p; int clone_types; int crtc_types; - int pipe_type; int pipe; int subpixel; DisplayModePtr modes, mode; @@ -644,7 +622,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen) clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); - pipe_type = PIPE_DFP; subpixel = SubPixelHorizontalRGB; break; case I830_OUTPUT_ANALOG: @@ -652,13 +629,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen) clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); - pipe_type = PIPE_CRT; subpixel = SubPixelNone; break; case I830_OUTPUT_LVDS: crtc_types = (1 << 1); clone_types = (1 << I830_OUTPUT_LVDS); - pipe_type = PIPE_LFP; subpixel = SubPixelHorizontalRGB; possibleOptions = (RROutputOptionScaleNone| RROutputOptionScaleMaxAspect | @@ -669,32 +644,27 @@ I830RandRSetInfo12 (ScreenPtr pScreen) crtc_types = ((1 << 0) | (1 << 1)); clone_types = (1 << I830_OUTPUT_TVOUT); - pipe_type = PIPE_TV; subpixel = SubPixelNone; break; default: crtc_types = 0; clone_types = 0; - pipe_type = PIPE_NONE; subpixel = SubPixelUnknown; break; } - ncrtc = 0; - pipe = -1; - crtc = NULL; - for (j = 0; j < pI830->availablePipes; j++) + if (!output->disabled) { -#if 0 - /* Can't flip outputs among crtcs yet */ - if (crtc_types & (1 << j)) - crtcs[ncrtc++] = randrp->crtcs[j]; -#endif - if (pI830->operatingDevices & (pipe_type << (j << 3))) - { - pipe = j; - crtc = randrp->crtcs[j]; - crtcs[ncrtc++] = crtc; - } + /* Can't flip outputs among crtcs yet */ + ncrtc = 1; + pipe = output->pipe; + crtc = randrp->crtcs[pipe]; + crtcs[0] = randrp->crtcs[pipe]; + } + else + { + ncrtc = 0; + pipe = -1; + crtc = NULL; } if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc)) return FALSE; diff --git a/src/i830_video.c b/src/i830_video.c index 47f4a03f..a5cd77cf 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -722,7 +722,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) pPriv->brightness = 0; pPriv->contrast = 64; pPriv->saturation = 128; - pPriv->pipe = pI830->pipe; /* default to current pipe */ + pPriv->pipe = 0; /* XXX must choose pipe wisely */ pPriv->linear = NULL; pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; @@ -3592,6 +3592,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) pPriv->overlayOK = TRUE; +#if 0 + /* XXX Must choose pipe wisely */ /* ensure pipe is updated on mode switch */ if (!pI830->Clone) { if (pPriv->pipe != pI830->pipe) { @@ -3600,6 +3602,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) pPriv->pipe = pI830->pipe; } } +#endif if (!IS_I965G(pI830)) { if (pPriv->pipe == 0) { @@ -3628,8 +3631,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } /* Check we have an LFP connected */ - if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || - (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) { + if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) + { size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); hsize = (size >> 16) & 0x7FF; vsize = size & 0x7FF; From b649f95ea6fd3555d073fdbf8f2f035dfe1afd33 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 8 Nov 2006 19:01:25 +0000 Subject: [PATCH 241/257] Disable some debug message --- src/i915_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/i915_video.c b/src/i915_video.c index 0833d508..78907efb 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -65,8 +65,10 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, int nbox, dxo, dyo; Bool planar; +#if 0 ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height, video_pitch); +#endif switch (id) { case FOURCC_UYVY: @@ -78,7 +80,9 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, planar = TRUE; break; default: +#if 0 ErrorF("Unknown format 0x%x\n", id); +#endif planar = FALSE; break; } From 35ab689bbde5f74752598cd743d735640486b639 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Nov 2006 19:35:49 -0800 Subject: [PATCH 242/257] Fix i830DisableUnusedFunctions after pipe structure change. Using "pipe" instead of the index "i" meant pipe(3) got referenced instead of a nice small integer. Oops. --- src/i830_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index c1fc562b..893b9b07 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -666,7 +666,7 @@ void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int i; + int i, pipe; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); @@ -679,8 +679,8 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (i = 0; i < pI830->availablePipes; i++) { - I830PipePtr pI830Pipe = &pI830->pipes[i]; + for (pipe = 0; pipe < pI830->availablePipes; pipe++) { + I830PipePtr pI830Pipe = &pI830->pipes[pipe]; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; int dpll_reg = pipe == 0 ? DPLL_A : DPLL_B; From 9b267014b55f49d9362c1d432d6ba19ddd0ad95d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Nov 2006 19:39:18 -0800 Subject: [PATCH 243/257] Go back to only setting up outputs that have a display connected. --- src/i830_display.c | 2 +- src/i830_display.h | 1 + src/i830_driver.c | 24 ++++++++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index 893b9b07..72037c47 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -723,7 +723,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * Return whether any outputs are connected to the specified pipe */ -static Bool +Bool i830PipeInUse (ScrnInfoPtr pScrn, int pipe) { I830Ptr pI830 = I830PTR(pScrn); diff --git a/src/i830_display.h b/src/i830_display.h index 5c0f1339..67f3c7b8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -35,3 +35,4 @@ void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); +Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe); diff --git a/src/i830_driver.c b/src/i830_driver.c index e6cd9bcb..75c3b0e5 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1355,19 +1355,27 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * we have better configuration support in the generic RandR code */ for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].disabled = FALSE; + pI830->output[i].disabled = TRUE; switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: - /* LVDS must live on pipe B for two-pipe devices */ - pI830->output[i].pipe = pI830->availablePipes - 1; + /* LVDS must always be on pipe B. */ + pI830->output[i].pipe = 1; + pI830->output[i].disabled = FALSE; break; case I830_OUTPUT_ANALOG: - pI830->output[i].pipe = 0; - break; case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: - pI830->output[i].pipe = 0; + if (pI830->output[i].detect(pScrn, &pI830->output[i]) != + OUTPUT_STATUS_DISCONNECTED) { + if (!i830PipeInUse(pScrn, 0)) { + pI830->output[i].pipe = 0; + pI830->output[i].disabled = FALSE; + } else if (!i830PipeInUse(pScrn, 1)) { + pI830->output[i].pipe = 1; + pI830->output[i].disabled = FALSE; + } + } break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); @@ -1375,6 +1383,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } + for (i = 0; i < pI830->availablePipes; i++) { + pI830->pipes[i].planeEnabled = i830PipeInUse(pScrn, i); + } + #if 0 pI830->CloneRefresh = 60; /* default to 60Hz */ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH, From ff77e9d84f2037b99a8e4ac55da0b0ac92ed6b9b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Nov 2006 19:53:31 -0800 Subject: [PATCH 244/257] Clean up i830_crt_detect_load() a bit more. ADPA might not have been set right in some cases (DPMS-off monitor, for example), and a wait for vsync that the bios does was missing. --- src/i830_crt.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 9287a205..68006f99 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -170,7 +170,7 @@ static Bool i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 adpa, pipeconf, bclrpat; + CARD32 save_adpa, adpa, pipeconf, bclrpat; CARD8 st00; int pipeconf_reg, bclrpat_reg, dpll_reg; int pipe; @@ -186,17 +186,17 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) dpll_reg = DPLL_B; } - /* Don't try this if the DPLL isn't running. */ - if (!(INREG(dpll_reg) & DPLL_VCO_ENABLE)) - return FALSE; - adpa = INREG(ADPA); + save_adpa = adpa; - /* Enable CRT output if disabled. */ - if (!(adpa & ADPA_DAC_ENABLE)) { - OUTREG(ADPA, adpa | ADPA_DAC_ENABLE | - ((pipe == 1) ? ADPA_PIPE_B_SELECT : 0)); - } + /* Enable CRT output. */ + adpa |= ADPA_DAC_ENABLE; + if (pipe == 1) + adpa |= ADPA_PIPE_B_SELECT; + else + adpa &= ~ADPA_PIPE_B_SELECT; + adpa |= ADPA_VSYNC_CNTL_ENABLE | ADPA_HSYNC_CNTL_ENABLE; + OUTREG(ADPA, adpa); /* Set the border color to purple. Maybe we should save/restore this * reg. @@ -204,6 +204,8 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) bclrpat = INREG(bclrpat_reg); OUTREG(bclrpat_reg, 0x00500050); + i830WaitForVblank(pScrn); + /* Force the border color through the active region */ pipeconf = INREG(pipeconf_reg); OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); @@ -214,7 +216,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) /* Restore previous settings */ OUTREG(bclrpat_reg, bclrpat); OUTREG(pipeconf_reg, pipeconf); - OUTREG(ADPA, adpa); + OUTREG(ADPA, save_adpa); if (st00 & (1 << 4)) return TRUE; From 713c5b0899428edfea7cea0780244488115dbe1d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 8 Nov 2006 19:55:31 -0800 Subject: [PATCH 245/257] Change the output and pipe "is it on/off" field name to "enabled". --- src/i830.h | 4 ++-- src/i830_cursor.c | 8 ++++---- src/i830_display.c | 50 +++++++++++++++++++--------------------------- src/i830_dri.c | 2 +- src/i830_driver.c | 18 ++++++++--------- src/i830_randr.c | 6 +++--- 6 files changed, 40 insertions(+), 48 deletions(-) diff --git a/src/i830.h b/src/i830.h index 9de73948..6a8e36e8 100644 --- a/src/i830.h +++ b/src/i830.h @@ -184,7 +184,7 @@ enum detect_status { struct _I830OutputRec { int type; int pipe; - Bool disabled; + Bool enabled; /** * Marks that the output and associated pipe is temporarily enabled for * load detection. @@ -273,12 +273,12 @@ struct _I830OutputRec { }; typedef struct _I830PipeRec { + Bool enabled; Bool gammaEnabled; int x; int y; Bool cursorInRange; Bool cursorShown; - Bool planeEnabled; DisplayModeRec curMode; } I830PipeRec, *I830PipePtr; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 6b0e58c4..bf35d4e3 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -109,7 +109,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) CARD32 temp; Bool show; - if (!pI830Pipe->planeEnabled) + if (!pI830Pipe->enabled) return; show = pI830->cursorOn && pI830Pipe->cursorInRange; @@ -491,7 +491,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) int thisx = x - pI830Pipe->x; int thisy = y - pI830Pipe->y; - if (!pI830Pipe->planeEnabled) + if (!pI830Pipe->enabled) continue; /* @@ -580,14 +580,14 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - if (pI830->pipes[0].planeEnabled) + if (pI830->pipes[0].enabled) { OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); } - if (pI830->pipes[1].planeEnabled) + if (pI830->pipes[1].enabled) { OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); diff --git a/src/i830_display.c b/src/i830_display.c index 72037c47..c81f4548 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -70,7 +70,7 @@ i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type) int i; for (i = 0; i < pI830->num_outputs; i++) - if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + if (pI830->output[i].enabled && pI830->output[i].pipe == pipe) { if (pI830->output[i].type == type) return TRUE; @@ -297,7 +297,7 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) /* Assume that there's only one output connected to the given CRTC. */ for (i = 0; i < pI830->num_outputs; i++) { if (pI830->output[i].pipe == pipe && - !pI830->output[i].disabled && + pI830->output[i].enabled && pI830->output[i].probed_modes != NULL) { pScan = pI830->output[i].probed_modes; @@ -418,7 +418,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, pMode->Clock); for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].pipe != pipe || pI830->output[i].disabled) + if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled) continue; switch (pI830->output[i].type) { @@ -671,7 +671,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].disabled) + if (!pI830->output[i].enabled) pI830->output[i].dpms(pScrn, &pI830->output[i], DPMSModeOff); } @@ -687,7 +687,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) CARD32 dspcntr, pipeconf, dpll; char *pipe_name = pipe == 0 ? "A" : "B"; - if (pI830Pipe->planeEnabled) + if (pI830Pipe->enabled) continue; dspcntr = INREG(dspcntr_reg); @@ -730,7 +730,7 @@ i830PipeInUse (ScrnInfoPtr pScrn, int pipe) int i; for (i = 0; i < pI830->num_outputs; i++) - if (!pI830->output[i].disabled && pI830->output[i].pipe == pipe) + if (pI830->output[i].enabled && pI830->output[i].pipe == pipe) return TRUE; return FALSE; } @@ -756,14 +756,14 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) #endif for (i = 0; i < pI830->availablePipes; i++) - pI830->pipes[i].planeEnabled = i830PipeInUse (pScrn, i); + pI830->pipes[i].enabled = i830PipeInUse (pScrn, i); for (i = 0; i < pI830->num_outputs; i++) pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); for (i = 0; i < pI830->availablePipes; i++) { - if (pI830->pipes[i].planeEnabled) + if (pI830->pipes[i].enabled) ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode), i, TRUE); @@ -786,7 +786,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* If we might have enabled/disabled some pipes, we need to reset * cloning mode support. */ - if (pI830->pipes[0].planeEnabled && pI830->pipes[1].planeEnabled) + if (pI830->pipes[0].enabled && pI830->pipes[1].enabled) pI830->Clone = TRUE; else pI830->Clone = FALSE; @@ -830,25 +830,25 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Pipe %c is %s\n", - 'A' + i, pI830->pipes[i].planeEnabled ? "on" : "off"); + 'A' + i, pI830->pipes[i].enabled ? "on" : "off"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Display plane %c is now %s and connected to pipe %c.\n", 'A' + i, - pI830->pipes[i].planeEnabled ? "enabled" : "disabled", + pI830->pipes[i].enabled ? "enabled" : "disabled", dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A'); - if (hw_pipe_enable != pI830->pipes[i].planeEnabled) { + if (hw_pipe_enable != pI830->pipes[i].enabled) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, " Hardware claims pipe %c is %s while software " "believes it is %s\n", 'A' + i, hw_pipe_enable ? "on" : "off", - pI830->pipes[i].planeEnabled ? "on" : "off"); + pI830->pipes[i].enabled ? "on" : "off"); } - if (hw_plane_enable != pI830->pipes[i].planeEnabled) { + if (hw_plane_enable != pI830->pipes[i].enabled) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, " Hardware claims plane %c is %s while software " "believes it is %s\n", 'A' + i, hw_plane_enable ? "on" : "off", - pI830->pipes[i].planeEnabled ? "on" : "off"); + pI830->pipes[i].enabled ? "on" : "off"); } } @@ -875,7 +875,7 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Output %s is %sabled and connected to pipe %c\n", - name, pI830->output[i].disabled ? "dis" : "en", + name, pI830->output[i].enabled ? "en" : "dis", pI830->output[i].pipe == 0 ? 'A' : 'B'); } } @@ -915,7 +915,7 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) /* If the output is not marked disabled, check if it's already assigned * to an active pipe, and is alone on that pipe. If so, we're done. */ - if (!output->disabled) { + if (output->enabled) { int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF; if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) { @@ -936,16 +936,8 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) } } - for (i = 0; i < pI830->availablePipes; i++) { - pipe_available[i] = TRUE; - } - - for (i = 0; i < pI830->num_outputs; i++) { - if (!pI830->output[i].disabled) - { - pipe_available[pI830->output[i].pipe] = FALSE; - } - } + for (i = 0; i < pI830->availablePipes; i++) + pipe_available[i] = i830PipeInUse(pScrn, i); for (i = 0; i < pI830->availablePipes; i++) { if (pipe_available[i]) @@ -957,7 +949,7 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) } output->load_detect_temp = TRUE; output->pipe = i; - output->disabled = FALSE; + output->enabled = TRUE; I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V); @@ -970,7 +962,7 @@ void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) { if (output->load_detect_temp) { - output->disabled = TRUE; + output->enabled = FALSE; i830DisableUnusedFunctions(pScrn); output->load_detect_temp = FALSE; } diff --git a/src/i830_dri.c b/src/i830_dri.c index 41ea21ca..9e4ead0b 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1485,7 +1485,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->pipes[1].planeEnabled) + if (pI830->pipes[1].enabled) pipe.pipe = DRM_I830_VBLANK_PIPE_B; else pipe.pipe = DRM_I830_VBLANK_PIPE_A; diff --git a/src/i830_driver.c b/src/i830_driver.c index 75c3b0e5..ab0af4e5 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -572,7 +572,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, dspsurf = DSPBSURF; } - if (pI830Pipe->planeEnabled == 0) + if (pI830Pipe->enabled == 0) continue; pI830Pipe->gammaEnabled = 1; @@ -1355,13 +1355,13 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * we have better configuration support in the generic RandR code */ for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].disabled = TRUE; + pI830->output[i].enabled = FALSE; switch (pI830->output[i].type) { case I830_OUTPUT_LVDS: /* LVDS must always be on pipe B. */ pI830->output[i].pipe = 1; - pI830->output[i].disabled = FALSE; + pI830->output[i].enabled = TRUE; break; case I830_OUTPUT_ANALOG: case I830_OUTPUT_DVO: @@ -1370,10 +1370,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) OUTPUT_STATUS_DISCONNECTED) { if (!i830PipeInUse(pScrn, 0)) { pI830->output[i].pipe = 0; - pI830->output[i].disabled = FALSE; + pI830->output[i].enabled = TRUE; } else if (!i830PipeInUse(pScrn, 1)) { pI830->output[i].pipe = 1; - pI830->output[i].disabled = FALSE; + pI830->output[i].enabled = TRUE; } } break; @@ -1384,7 +1384,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } for (i = 0; i < pI830->availablePipes; i++) { - pI830->pipes[i].planeEnabled = i830PipeInUse(pScrn, i); + pI830->pipes[i].enabled = i830PipeInUse(pScrn, i); } #if 0 @@ -3210,7 +3210,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) } for (i = 0; i < pI830->availablePipes; i++) - if (pI830->pipes[i].planeEnabled) + if (pI830->pipes[i].enabled) i830PipeSetBase(pScrn, i, x, y); } @@ -3471,7 +3471,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) base = DSPBADDR; surf = DSPBSURF; } - if (pI830->pipes[i].planeEnabled) { + if (pI830->pipes[i].enabled) { temp = INREG(ctrl); if (on) temp |= DISPLAY_PLANE_ENABLE; @@ -3520,7 +3520,7 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, ctrl = DSPBCNTR; base = DSPBADDR; } - if (pI830->pipes[i].planeEnabled) { + if (pI830->pipes[i].enabled) { temp = INREG(ctrl); if (PowerManagementMode == DPMSModeOn) temp |= DISPLAY_PLANE_ENABLE; diff --git a/src/i830_randr.c b/src/i830_randr.c index d2228cfb..184bf012 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -501,7 +501,7 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) for (i = 0; i < pI830->num_outputs; i++) { output = &pI830->output[i]; - if (!output->disabled && output->pipe == pipe) + if (output->enabled && output->pipe == pipe) { rrout = randrp->outputs[i]; outputs[numOutputs++] = rrout; @@ -548,7 +548,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, if (display_mode != randrp->modes[pipe]) { - pI830Pipe->planeEnabled = mode != NULL; + pI830Pipe->enabled = mode != NULL; if (display_mode) { if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE)) @@ -652,7 +652,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) subpixel = SubPixelUnknown; break; } - if (!output->disabled) + if (output->enabled) { /* Can't flip outputs among crtcs yet */ ncrtc = 1; From 81b7b489afa2cab4d8614c64f4906be627f1d07e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 8 Nov 2006 21:38:00 -0800 Subject: [PATCH 246/257] Adapt to RandR updates that split object creation from screen association. RandR DIX code is preparing for xf86 drivers that want to allocate RandR objects at PreInit time. This patch adapts to that change without taking advantage of it. --- src/i830_crt.c | 10 +++++++--- src/i830_randr.c | 16 +++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 46eb788f..f067260d 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -103,13 +103,17 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, { I830Ptr pI830 = I830PTR(pScrn); int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; - CARD32 adpa; + CARD32 adpa, dpll_md; /* - * Not quite sure precisely what this does... + * Disable separate mode multiplier used when cloning SDVO to CRT + * XXX this needs to be adjusted when we really are cloning */ if (IS_I965G(pI830)) - OUTREG(dpll_md_reg, 0x3 << DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT); + { + dpll_md = INREG(dpll_md_reg); + OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); + } adpa = ADPA_DAC_ENABLE; diff --git a/src/i830_randr.c b/src/i830_randr.c index 32cc8773..d6e5f0b8 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -707,7 +707,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) modeInfo.vTotal = mode->VTotal; modeInfo.modeFlags = mode->Flags; - rrmode = RRModeGet (pScreen, &modeInfo, mode->name); + rrmode = RRModeGet (&modeInfo, mode->name); rrmode->devPrivate = mode; if (rrmode) { rrmodes[nmode++] = rrmode; @@ -787,7 +787,11 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) */ for (i = 0; i < pI830->num_pipes; i++) { - randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); + randrp->crtcs[i] = RRCrtcCreate ((void *) i); + if (!randrp->crtcs[i]) + return FALSE; + if (!RRCrtcAttachScreen (randrp->crtcs[i], pScreen)) + return FALSE; RRCrtcGammaSetSize (randrp->crtcs[i], 256); } @@ -795,9 +799,11 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) { output = &pI830->output[i]; name = i830_output_type_names[output->type]; - randrp->outputs[i] = RROutputCreate (pScreen, - name, strlen (name), - (void *) i); + randrp->outputs[i] = RROutputCreate (name, strlen (name), (void *) i); + if (!randrp->outputs[i]) + return FALSE; + if (!RROutputAttachScreen (randrp->outputs[i], pScreen)) + return FALSE; } mode = pScrn->currentMode; From 679c7bd82639a09cdce133becb8a08629ce3a4e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 8 Nov 2006 21:39:28 -0800 Subject: [PATCH 247/257] ignore edited man page --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b13e38f1..cb52e9fa 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ libtool ltmain.sh missing stamp-h1 +i810.4 From 0f5886689d7ef7dbbef6425d5c855ac6b67d3350 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 8 Nov 2006 23:19:59 -0800 Subject: [PATCH 248/257] Create RandR 1.2 objects in I830PreInit. Creating the objects early will allow the driver to use randr structures to select a reasonable configuration. That part has not been done yet. --- src/i830.h | 7 + src/i830_driver.c | 6 +- src/i830_randr.c | 321 ++++++++++++++++++++++++++-------------------- 3 files changed, 193 insertions(+), 141 deletions(-) diff --git a/src/i830.h b/src/i830.h index ef46979f..96f0c29c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -270,6 +270,9 @@ struct _I830OutputRec { struct _I830DVODriver *i2c_drv; /** Output-private structure. Should replace i2c_drv */ void *dev_priv; +#ifdef RANDR_12_INTERFACE + RROutputPtr randr_output; +#endif }; typedef struct _I830PipeRec { @@ -280,6 +283,9 @@ typedef struct _I830PipeRec { Bool cursorInRange; Bool cursorShown; DisplayModeRec curMode; +#ifdef RANDR_12_INTERFACE + RRCrtcPtr randr_crtc; +#endif } I830PipeRec, *I830PipePtr; typedef struct _I830Rec { @@ -676,6 +682,7 @@ Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); Rotation I830GetRotation(ScreenPtr pScreen); void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); +Bool I830RandRPreInit (ScrnInfoPtr pScrn); /* i830_tv.c */ void i830_tv_init(ScrnInfoPtr pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index 63c1fd2e..1f3ff0a7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -771,7 +771,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) I830EntPtr pI830Ent = NULL; int mem; int flags24; - int i, n; + int i; char *s; pointer pVBEModule = NULL; Bool enable; @@ -1653,8 +1653,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - n = I830ValidateXF86ModeList(pScrn, TRUE); - if (n <= 0) { + if (!I830RandRPreInit (pScrn)) + { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); PreInitCleanup(pScrn); return FALSE; diff --git a/src/i830_randr.c b/src/i830_randr.c index d6e5f0b8..87864f29 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -53,8 +53,6 @@ typedef struct _i830RandRInfo { Rotation rotation; /* current mode */ Rotation supported_rotations; /* driver supported */ #ifdef RANDR_12_INTERFACE - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - RROutputPtr outputs[MAX_OUTPUTS]; DisplayModePtr modes[MAX_DISPLAY_PIPES]; #endif } XF86RandRInfoRec, *XF86RandRInfoPtr; @@ -477,7 +475,6 @@ static Bool I830RandRCrtcNotify (RRCrtcPtr crtc) { ScreenPtr pScreen = crtc->pScreen; - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); RRModePtr mode = NULL; @@ -503,7 +500,7 @@ I830RandRCrtcNotify (RRCrtcPtr crtc) output = &pI830->output[i]; if (output->enabled && output->pipe == pipe) { - rrout = randrp->outputs[i]; + rrout = output->randr_output; outputs[numOutputs++] = rrout; /* * We make copies of modes, so pointer equality @@ -572,45 +569,91 @@ I830RandRCrtcSetGamma (ScreenPtr pScreen, return FALSE; } +/** + * Given a list of xf86 modes and a RandR Output object, construct + * RandR modes and assign them to the output + */ +static Bool +I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) +{ + DisplayModePtr mode; + RRModePtr *rrmodes = NULL; + int nmode = 0; + int npreferred = 0; + Bool ret = TRUE; + int pref; + + for (mode = modes; mode; mode = mode->next) + nmode++; + + if (nmode) { + rrmodes = xalloc (nmode * sizeof (RRModePtr)); + + if (!rrmodes) + return FALSE; + nmode = 0; + + for (pref = 1; pref >= 0; pref--) { + for (mode = modes; mode; mode = mode->next) { + if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { + xRRModeInfo modeInfo; + RRModePtr rrmode; + + modeInfo.nameLength = strlen (mode->name); + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (&modeInfo, mode->name); + rrmode->devPrivate = mode; + if (rrmode) { + rrmodes[nmode++] = rrmode; + npreferred += pref; + } + } + } + } + } + + ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); + xfree (rrmodes); + return ret; +} + /* * Mirror the current mode configuration to RandR */ static Bool -I830RandRSetInfo12 (ScreenPtr pScreen) +I830RandRSetInfo12 (ScrnInfoPtr pScrn) { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - RROutputPtr clones[MAX_OUTPUTS]; - RRCrtcPtr crtc; - int nclone; - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - int ncrtc; - int nmode, npreferred; - struct _I830OutputRec *output; - int i; - int j; - int p; - int clone_types; - int crtc_types; - int pipe; - int subpixel; - DisplayModePtr modes, mode; - xRRModeInfo modeInfo; - RRModePtr rrmode, *rrmodes; - CARD32 possibleOptions = 0; - CARD32 currentOptions = 0; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) + I830Ptr pI830 = I830PTR(pScrn); + RROutputPtr clones[MAX_OUTPUTS]; + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + int ncrtc; + I830OutputPtr output; + int o, c, p; + int clone_types; + int crtc_types; + int subpixel; + CARD32 possibleOptions = 0; + CARD32 currentOptions = 0; + RRCrtcPtr randr_crtc; + RROutputPtr randr_output; + int nclone; + + for (o = 0; o < pI830->num_outputs; o++) { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - RRScreenSetSizeRange (pScreen, 320, 240, - randrp->virtualX, randrp->virtualY); - for (i = 0; i < pI830->num_outputs; i++) - { - output = &pI830->output[i]; + output = &pI830->output[o]; + randr_output = output->randr_output; /* * Valid crtcs */ @@ -625,7 +668,7 @@ I830RandRSetInfo12 (ScreenPtr pScreen) subpixel = SubPixelHorizontalRGB; break; case I830_OUTPUT_ANALOG: - crtc_types = (1 << 0); + crtc_types = ((1 << 0) | (1 << 1)); clone_types = ((1 << I830_OUTPUT_ANALOG) | (1 << I830_OUTPUT_DVO) | (1 << I830_OUTPUT_SDVO)); @@ -654,110 +697,58 @@ I830RandRSetInfo12 (ScreenPtr pScreen) } if (output->enabled) { - /* Can't flip outputs among crtcs yet */ - ncrtc = 1; - pipe = output->pipe; - crtc = randrp->crtcs[pipe]; - crtcs[0] = randrp->crtcs[pipe]; + ncrtc = 0; + for (p = 0; p < pI830->num_pipes; p++) + if (crtc_types & (1 << p)) + crtcs[ncrtc++] = pI830->pipes[p].randr_crtc; + randr_crtc = pI830->pipes[output->pipe].randr_crtc; } else { ncrtc = 0; - pipe = -1; - crtc = NULL; + randr_crtc = NULL; } - if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc)) + if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) return FALSE; - RROutputSetCrtc (randrp->outputs[i], crtc); - RROutputSetPhysicalSize(randrp->outputs[i], pI830->output[i].mm_width, - pI830->output[i].mm_height); - RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions); - RROutputSetCurrentOptions (randrp->outputs[i], currentOptions); - nmode = 0; - npreferred = 0; - rrmodes = NULL; + RROutputSetCrtc (output->randr_output, randr_crtc); + RROutputSetPhysicalSize(output->randr_output, + output->mm_width, + output->mm_height); + RROutputSetPossibleOptions (output->randr_output, possibleOptions); + RROutputSetCurrentOptions (output->randr_output, currentOptions); - modes = pI830->output[i].probed_modes; + I830xf86RROutputSetModes (output->randr_output, output->probed_modes); - for (mode = modes; mode; mode = mode->next) - nmode++; - - if (nmode) { - rrmodes = xalloc (nmode * sizeof (RRModePtr)); - if (!rrmodes) - return FALSE; - nmode = 0; - - for (p = 1; p >= 0; p--) { - for (mode = modes; mode; mode = mode->next) { - if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) { - modeInfo.nameLength = strlen (mode->name); - - modeInfo.width = mode->HDisplay; - modeInfo.dotClock = mode->Clock * 1000; - modeInfo.hSyncStart = mode->HSyncStart; - modeInfo.hSyncEnd = mode->HSyncEnd; - modeInfo.hTotal = mode->HTotal; - modeInfo.hSkew = mode->HSkew; - - modeInfo.height = mode->VDisplay; - modeInfo.vSyncStart = mode->VSyncStart; - modeInfo.vSyncEnd = mode->VSyncEnd; - modeInfo.vTotal = mode->VTotal; - modeInfo.modeFlags = mode->Flags; - - rrmode = RRModeGet (&modeInfo, mode->name); - rrmode->devPrivate = mode; - if (rrmode) { - rrmodes[nmode++] = rrmode; - npreferred += p; - } - } - } - } - } - - if (!RROutputSetModes (randrp->outputs[i], rrmodes, nmode, npreferred)) - { - xfree (rrmodes); - return FALSE; - } - - xfree (rrmodes); - - switch (pI830->output[i].detect(pScrn, &pI830->output[i])) { + switch (output->detect(pScrn, output)) { case OUTPUT_STATUS_CONNECTED: - RROutputSetConnection (randrp->outputs[i], RR_Connected); + RROutputSetConnection (output->randr_output, RR_Connected); break; case OUTPUT_STATUS_DISCONNECTED: - RROutputSetConnection (randrp->outputs[i], RR_Disconnected); + RROutputSetConnection (output->randr_output, RR_Disconnected); break; case OUTPUT_STATUS_UNKNOWN: - RROutputSetConnection (randrp->outputs[i], RR_UnknownConnection); + RROutputSetConnection (output->randr_output, RR_UnknownConnection); break; } - RROutputSetSubpixelOrder (randrp->outputs[i], subpixel); + RROutputSetSubpixelOrder (output->randr_output, subpixel); /* * Valid clones */ nclone = 0; - for (j = 0; j < pI830->num_outputs; j++) + for (c = 0; c < pI830->num_outputs; c++) { - if (i != j && ((1 << pI830->output[j].type) & clone_types)) - clones[nclone++] = randrp->outputs[j]; + if (o != c && ((1 << pI830->output[c].type) & clone_types)) + clones[nclone++] = pI830->output[c].randr_output; } - if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) + if (!RROutputSetClones (output->randr_output, clones, nclone)) return FALSE; } - for (i = 0; i < pI830->num_pipes; i++) - I830RandRCrtcNotify (randrp->crtcs[i]); return TRUE; } - /* * Query the hardware for the current state, then mirror * that to RandR @@ -768,7 +759,49 @@ I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; i830_reprobe_output_modes(pScrn); - return I830RandRSetInfo12 (pScreen); + return I830RandRSetInfo12 (pScrn); +} + +static Bool +I830RandRCreateObjects12 (ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int p; + int o; + + if (!RRInit ()) + return FALSE; + + /* + * Create RandR resources, then probe them + */ + for (p = 0; p < pI830->num_pipes; p++) + { + I830PipePtr pipe = &pI830->pipes[p]; + RRCrtcPtr randr_crtc = RRCrtcCreate ((void *) p); + + if (!randr_crtc) + return FALSE; + RRCrtcGammaSetSize (randr_crtc, 256); + pipe->randr_crtc = randr_crtc; + } + + for (o = 0; o < pI830->num_outputs; o++) + { + I830OutputPtr output = &pI830->output[o]; + const char *name = i830_output_type_names[output->type]; + RROutputPtr randr_output = RROutputCreate (name, strlen (name), + (void *) o); + if (!randr_output) + return FALSE; + output->randr_output = randr_output; + } + /* + * Configure output modes + */ + if (!I830RandRSetInfo12 (pScrn)) + return FALSE; + return TRUE; } static Bool @@ -777,34 +810,19 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - struct _I830OutputRec *output; - const char *name; - int i; + int p, o; DisplayModePtr mode; /* - * Create RandR resources, then probe them + * Attach RandR objects to screen */ - for (i = 0; i < pI830->num_pipes; i++) - { - randrp->crtcs[i] = RRCrtcCreate ((void *) i); - if (!randrp->crtcs[i]) + for (p = 0; p < pI830->num_pipes; p++) + if (!RRCrtcAttachScreen (pI830->pipes[p].randr_crtc, pScreen)) return FALSE; - if (!RRCrtcAttachScreen (randrp->crtcs[i], pScreen)) - return FALSE; - RRCrtcGammaSetSize (randrp->crtcs[i], 256); - } - for (i = 0; i < pI830->num_outputs; i++) - { - output = &pI830->output[i]; - name = i830_output_type_names[output->type]; - randrp->outputs[i] = RROutputCreate (name, strlen (name), (void *) i); - if (!randrp->outputs[i]) + for (o = 0; o < pI830->num_outputs; o++) + if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen)) return FALSE; - if (!RROutputAttachScreen (randrp->outputs[i], pScreen)) - return FALSE; - } mode = pScrn->currentMode; if (mode) @@ -827,10 +845,22 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmHeight); } - for (i = 0; i < pI830->num_pipes; i++) - i830PipeSetBase(pScrn, i, 0, 0); + for (p = 0; p < pI830->num_pipes; p++) + { + i830PipeSetBase(pScrn, p, 0, 0); + I830RandRCrtcNotify (pI830->pipes[p].randr_crtc); + } - return I830RandRSetInfo12 (pScreen); + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + + RRScreenSetSizeRange (pScreen, 320, 240, + randrp->virtualX, randrp->virtualY); + return TRUE; } static void @@ -853,3 +883,18 @@ I830RandRInit12 (ScreenPtr pScreen) return TRUE; } #endif + +Bool +I830RandRPreInit (ScrnInfoPtr pScrn) +{ + int n; + + n = I830ValidateXF86ModeList(pScrn, TRUE); + if (n <= 0) + return FALSE; +#if RANDR_12_INTERFACE + if (!I830RandRCreateObjects12 (pScrn)) + return FALSE; +#endif + return TRUE; +} From 3955f044cfe1d592bcb36c43c539fb4a75840b8d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 9 Nov 2006 20:28:46 -0800 Subject: [PATCH 249/257] Expose the DDC-probed EDID data as the EDID_DATA output property. --- src/i830_modes.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/i830_modes.c b/src/i830_modes.c index b6867c3c..77db66cf 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -48,6 +48,7 @@ #include #include "xf86.h" +#include "X11/Xatom.h" #include "i830.h" #include "i830_display.h" #include "i830_xf86Modes.h" @@ -612,6 +613,29 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) return 1; /* XXX */ } +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID_DATA" + +static void +i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output, + void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} +#endif + /** * Generic get_modes function using DDC, used by many outputs. */ @@ -623,13 +647,27 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) int i; ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus); - if (ddc_mon == NULL) + if (ddc_mon == NULL) { +#ifdef RANDR_12_INTERFACE + i830_ddc_set_edid_property(pScrn, output, NULL, 0); +#endif return NULL; + } if (output->MonInfo != NULL) xfree(output->MonInfo); output->MonInfo = ddc_mon; +#ifdef RANDR_12_INTERFACE + if (output->MonInfo->ver.version == 1) { + i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 128); + } else if (output->MonInfo->ver.version == 2) { + i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 256); + } else { + i830_ddc_set_edid_property(pScrn, output, NULL, 0); + } +#endif + /* Debug info for now, at least */ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", i830_output_type_names[output->type]); From dd1dcfab0ab0f2d0c25077fa663209e2762f26e8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 10 Nov 2006 11:08:02 -0800 Subject: [PATCH 250/257] Fill in some of the high bits of mode timings for SDVO. --- src/i830_sdvo.c | 12 ++++++++---- src/i830_sdvo_regs.h | 34 ++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 4d4817a5..8d1f296c 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -555,16 +555,20 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, output_dtd.part2.h_sync_width = h_sync_len & 0xff; output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf); - output_dtd.part2.sync_off_width_high = 0; + output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | + ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | + ((v_sync_len & 0x30) >> 4); + output_dtd.part2.dtd_flags = 0x18; - output_dtd.part2.sdvo_flags = 0; - output_dtd.part2.v_sync_off_high = 0; - output_dtd.part2.reserved = 0; if (mode->Flags & V_PHSYNC) output_dtd.part2.dtd_flags |= 0x2; if (mode->Flags & V_PVSYNC) output_dtd.part2.dtd_flags |= 0x4; + output_dtd.part2.sdvo_flags = 0; + output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; + output_dtd.part2.reserved = 0; + /* Turn off the screens before adjusting timings */ i830_sdvo_set_active_outputs(output, &no_outputs); diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index c43e17a8..98aa7a6b 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -25,6 +25,10 @@ * */ +/** + * @file SDVO command definitions and structures. + */ + struct i830_sdvo_output_flags { unsigned int tmds0:1; unsigned int rgb0:1; @@ -60,22 +64,28 @@ struct i830_sdvo_caps { /** This matches the EDID DTD structure, more or less */ struct i830_sdvo_dtd { struct { - CARD16 clock; /**< pixel clock, in 10kHz units */ - CARD8 h_active; - CARD8 h_blank; - CARD8 h_high; - CARD8 v_active; - CARD8 v_blank; - CARD8 v_high; + CARD16 clock; /**< pixel clock, in 10kHz units */ + CARD8 h_active; /**< lower 8 bits (pixels) */ + CARD8 h_blank; /**< lower 8 bits (pixels) */ + CARD8 h_high; /**< upper 4 bits each h_active, h_blank */ + CARD8 v_active; /**< lower 8 bits (lines) */ + CARD8 v_blank; /**< lower 8 bits (lines) */ + CARD8 v_high; /**< upper 4 bits each v_active, v_blank */ } part1; struct { - CARD8 h_sync_off; - CARD8 h_sync_width; + CARD8 h_sync_off; /**< lower 8 bits, from hblank start */ + CARD8 h_sync_width; /**< lower 8 bits (pixels) */ + /** lower 4 bits each vsync offset, vsync width */ CARD8 v_sync_off_width; + /** + * 2 high bits of hsync offset, 2 high bits of hsync width, + * bits 4-5 of vsync offset, and 2 high bits of vsync width. + */ CARD8 sync_off_width_high; CARD8 dtd_flags; CARD8 sdvo_flags; + /** bits 6-7 of vsync offset at bits 6-7 */ CARD8 v_sync_off_high; CARD8 reserved; } part2; @@ -250,8 +260,12 @@ struct i830_sdvo_set_target_input_args { # define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) # define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 # define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) -# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED (1 << 6) +# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) +# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) # define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) +# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) # define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 /** From d51555fba4e57c059fd184c1e54822d7e5b62a2f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 10 Nov 2006 14:40:40 -0800 Subject: [PATCH 251/257] Fix clock range for single-channel LVDS. --- src/i830_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i830_display.c b/src/i830_display.c index 36036603..f661c4ed 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -189,7 +189,10 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, min_p1 = 1; max_p1 = 8; if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { - if (target < 200000) /* XXX: Is this the right cutoff? */ + /* The single-channel range is 25-112Mhz, and dual-channel + * is 80-224Mhz. Prefer single channel as much as possible. + */ + if (target < 112000) p2 = 14; else p2 = 7; From 854ff826c0031a44e874239c0b0a3533f4d9e14b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 14 Nov 2006 09:14:24 -0800 Subject: [PATCH 252/257] Disable setup of the second SDVO device until we fix it. --- src/i830_driver.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 1f3ff0a7..344f4c0d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -651,7 +651,13 @@ I830SetupOutputs(ScrnInfoPtr pScrn) if (IS_I9XX(pI830)) { i830_sdvo_init(pScrn, SDVOB); - i830_sdvo_init(pScrn, SDVOC); + + /* Don't initialize the second SDVO port for now. We have issues with + * dealing with two ports, where we stomp both SDVO channels' registers + * when interacting with each, channel, and commands to one SDVO + * device appear to be affecting the other. + */ + /* i830_sdvo_init(pScrn, SDVOC); */ } else { i830_dvo_init(pScrn); } From 4889b9f33336c92f07aac86d75f50316db6ef81a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 15 Nov 2006 15:26:31 -0800 Subject: [PATCH 253/257] Enable the LVDS if we find it and assign it to a pipe (oops). --- src/i830_driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i830_driver.c b/src/i830_driver.c index 344f4c0d..0ea20e4c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1349,6 +1349,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) case I830_OUTPUT_LVDS: /* LVDS must live on pipe B for two-pipe devices */ pI830->output[i].pipe = pI830->num_pipes - 1; + pI830->output[i].enabled = TRUE; break; case I830_OUTPUT_ANALOG: case I830_OUTPUT_DVO: From 9aea79d1e954fe4fb5c101edcb7c2d0f706a5c4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 Nov 2006 11:40:26 -0800 Subject: [PATCH 254/257] Inverted boolean sense when selecting pipe for CRT detection. Pipes are available when they are not in use. --- src/i830_display.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/i830_display.c b/src/i830_display.c index f661c4ed..a0809eb0 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -904,7 +904,6 @@ int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) { I830Ptr pI830 = I830PTR(pScrn); - Bool pipe_available[MAX_DISPLAY_PIPES]; int i; /* VESA 640x480x72Hz mode to set on the pipe */ DisplayModeRec mode = { @@ -944,16 +943,12 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) } for (i = 0; i < pI830->num_pipes; i++) - pipe_available[i] = i830PipeInUse(pScrn, i); - - for (i = 0; i < pI830->num_pipes; i++) { - if (pipe_available[i]) + if (!i830PipeInUse(pScrn, i)) break; - } - if (i == pI830->num_pipes) { + if (i == pI830->num_pipes) return -1; - } + output->load_detect_temp = TRUE; output->pipe = i; output->enabled = TRUE; From 45a27f80e1c783627f570c309e7a853dcc9af0c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 Nov 2006 13:38:35 -0800 Subject: [PATCH 255/257] Remove output options. Let outputs be connected to other crtcs. Output options will be replaced by properties. Permits outputs to be connected to arbitrary CRTCs (within hardware limits). No cloning yet. --- src/i830_randr.c | 112 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 87864f29..f579f411 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -527,8 +527,8 @@ I830RandRCrtcSet (ScreenPtr pScreen, int x, int y, Rotation rotation, - int numOutputs, - RROutputConfigPtr outputs) + int num_randr_outputs, + RROutputPtr *randr_outputs) { XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -536,29 +536,85 @@ I830RandRCrtcSet (ScreenPtr pScreen, int pipe = (int) (crtc->devPrivate); I830PipePtr pI830Pipe = &pI830->pipes[pipe]; DisplayModePtr display_mode = mode ? mode->devPrivate : NULL; - - /* Sync the engine before adjust mode */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } + Bool changed = FALSE; + Bool disable = FALSE; + int o, ro; + struct { + int pipe; + int enabled; + } save_output[MAX_OUTPUTS]; + Bool save_enabled = pI830Pipe->enabled; if (display_mode != randrp->modes[pipe]) { - pI830Pipe->enabled = mode != NULL; - if (display_mode) + changed = TRUE; + if (!display_mode) + disable = TRUE; + } + + for (o = 0; o < pI830->num_outputs; o++) + { + I830OutputPtr output = &pI830->output[o]; + RROutputPtr randr_output = NULL; + + save_output[o].enabled = output->enabled; + save_output[o].pipe = output->pipe; + for (ro = 0; ro < num_randr_outputs; ro++) { - if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE)) - return FALSE; - /* XXX need I830SDVOPostSetMode here */ + if (output->randr_output == randr_outputs[ro]) + { + randr_output = randr_outputs[ro]; + break; + } + } + if (randr_output) + { + if (output->pipe != pipe || !output->enabled) + { + output->pipe = pipe; + output->enabled = TRUE; + changed = TRUE; + } } else { - i830DisableUnusedFunctions (pScrn); + /* Disable outputs which were on this pipe */ + if (output->enabled && output->pipe == pipe) + { + output->enabled = FALSE; + changed = TRUE; + disable = TRUE; + } + } + } + if (changed) + { + pI830Pipe->enabled = mode != NULL; + /* Sync the engine before adjust mode */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + + if (display_mode) + { + if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE)) + { + pI830Pipe->enabled = save_enabled; + for (o = 0; o < pI830->num_outputs; o++) + { + I830OutputPtr output = &pI830->output[o]; + output->enabled = save_output[o].enabled; + output->pipe = save_output[o].pipe; + } + return FALSE; + } + i830PipeSetBase(pScrn, pipe, x, y); } randrp->modes[pipe] = display_mode; + if (disable) + i830DisableUnusedFunctions (pScrn); } - i830PipeSetBase(pScrn, pipe, x, y); return I830RandRCrtcNotify (crtc); } @@ -644,8 +700,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) int clone_types; int crtc_types; int subpixel; - CARD32 possibleOptions = 0; - CARD32 currentOptions = 0; RRCrtcPtr randr_crtc; RROutputPtr randr_output; int nclone; @@ -678,10 +732,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) crtc_types = (1 << 1); clone_types = (1 << I830_OUTPUT_LVDS); subpixel = SubPixelHorizontalRGB; - possibleOptions = (RROutputOptionScaleNone| - RROutputOptionScaleMaxAspect | - RROutputOptionScaleMax); - currentOptions = RROutputOptionScaleMax; break; case I830_OUTPUT_TVOUT: crtc_types = ((1 << 0) | @@ -695,19 +745,16 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) subpixel = SubPixelUnknown; break; } + ncrtc = 0; + for (p = 0; p < pI830->num_pipes; p++) + if (crtc_types & (1 << p)) + crtcs[ncrtc++] = pI830->pipes[p].randr_crtc; + if (output->enabled) - { - ncrtc = 0; - for (p = 0; p < pI830->num_pipes; p++) - if (crtc_types & (1 << p)) - crtcs[ncrtc++] = pI830->pipes[p].randr_crtc; randr_crtc = pI830->pipes[output->pipe].randr_crtc; - } else - { - ncrtc = 0; randr_crtc = NULL; - } + if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) return FALSE; @@ -715,9 +762,6 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) RROutputSetPhysicalSize(output->randr_output, output->mm_width, output->mm_height); - RROutputSetPossibleOptions (output->randr_output, possibleOptions); - RROutputSetCurrentOptions (output->randr_output, currentOptions); - I830xf86RROutputSetModes (output->randr_output, output->probed_modes); switch (output->detect(pScrn, output)) { @@ -833,7 +877,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) mmHeight = pScreen->mmHeight; if (mode->HDisplay != pScreen->width) mmWidth = mmWidth * mode->HDisplay / pScreen->width; - if (mode->VDisplay == pScreen->height) + if (mode->VDisplay != pScreen->height) mmHeight = mmHeight * mode->VDisplay / pScreen->height; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Setting screen physical size to %d x %d\n", From c4508c1cadf323e9ef1d0e69dd77d5e841a6a978 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 Nov 2006 21:09:23 -0800 Subject: [PATCH 256/257] RandR-based initial output configuration. Using pre-init computed RandR information, make reasonable default choices for the output configuration at startup time. Either some preferred size or a size which yields 96dpi is chosen, from which other monitors are set to a similar size. The largest size sets the screen size. This needs to be extended to respect config file settings, but those have not been defined yet. --- src/i830.h | 3 + src/i830_display.c | 2 +- src/i830_display.h | 2 + src/i830_driver.c | 25 ++- src/i830_modes.c | 4 +- src/i830_randr.c | 377 ++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 387 insertions(+), 26 deletions(-) diff --git a/src/i830.h b/src/i830.h index 96f0c29c..f22be408 100644 --- a/src/i830.h +++ b/src/i830.h @@ -283,6 +283,7 @@ typedef struct _I830PipeRec { Bool cursorInRange; Bool cursorShown; DisplayModeRec curMode; + DisplayModeRec desiredMode; #ifdef RANDR_12_INTERFACE RRCrtcPtr randr_crtc; #endif @@ -673,6 +674,8 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, /* i830_modes.c */ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); void i830_reprobe_output_modes(ScrnInfoPtr pScrn); +void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn); +void i830_set_default_screen_size(ScrnInfoPtr pScrn); DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output); /* i830_randr.c */ diff --git a/src/i830_display.c b/src/i830_display.c index a0809eb0..bd40e4ee 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -290,7 +290,7 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) * - Closer in size to the requested mode, but no larger * - Closer in refresh rate to the requested mode. */ -static DisplayModePtr +DisplayModePtr i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); diff --git a/src/i830_display.h b/src/i830_display.h index 67f3c7b8..361a3c67 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -26,6 +26,8 @@ */ /* i830_display.c */ +DisplayModePtr +i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode); Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, Bool plane_enable); void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index 0ea20e4c..5da47424 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3304,12 +3304,33 @@ I830EnterVT(int scrnIndex, int flags) ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); - /* Mark that we'll need to re-set the mode for sure */ for (i = 0; i < pI830->num_pipes; i++) - memset(&pI830->pipes[i].curMode, 0, sizeof(pI830->pipes[i].curMode)); + { + I830PipePtr pipe = &pI830->pipes[i]; + /* Mark that we'll need to re-set the mode for sure */ + memset(&pipe->curMode, 0, sizeof(pipe->curMode)); + if (!pipe->desiredMode.CrtcHDisplay) + { + pipe->desiredMode = *i830PipeFindClosestMode (pScrn, i, + pScrn->currentMode); + } + if (!i830PipeSetMode (pScrn, &pipe->desiredMode, i, TRUE)) + return FALSE; + i830PipeSetBase(pScrn, i, pipe->x, pipe->y); + } + i830DisableUnusedFunctions(pScrn); + + i830DescribeOutputConfiguration(pScrn); + +#ifdef XF86DRI + I830DRISetVBlankInterrupt (pScrn, TRUE); +#endif + +#if 0 if (!i830SetMode(pScrn, pScrn->currentMode)) return FALSE; +#endif #ifdef I830_XV I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); diff --git a/src/i830_modes.c b/src/i830_modes.c index 77db66cf..7fdd40ed 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -490,7 +490,7 @@ i830_reprobe_output_modes(ScrnInfoPtr pScrn) * * This should be obsoleted by RandR 1.2 hopefully. */ -static void +void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); @@ -557,7 +557,7 @@ i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) * Takes the output mode lists and decides the default root window size * and framebuffer pitch. */ -static void +void i830_set_default_screen_size(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); diff --git a/src/i830_randr.c b/src/i830_randr.c index f579f411..e01ac1e1 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -609,6 +609,7 @@ I830RandRCrtcSet (ScreenPtr pScreen, } return FALSE; } + pI830Pipe->desiredMode = *display_mode; i830PipeSetBase(pScrn, pipe, x, y); } randrp->modes[pipe] = display_mode; @@ -840,11 +841,6 @@ I830RandRCreateObjects12 (ScrnInfoPtr pScrn) return FALSE; output->randr_output = randr_output; } - /* - * Configure output modes - */ - if (!I830RandRSetInfo12 (pScrn)) - return FALSE; return TRUE; } @@ -855,7 +851,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int p, o; - DisplayModePtr mode; + int width, height; /* * Attach RandR objects to screen @@ -868,33 +864,43 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen)) return FALSE; - mode = pScrn->currentMode; - if (mode) + /* + * Compute width of screen + */ + width = 0; height = 0; + for (p = 0; p < pI830->num_pipes; p++) + { + I830PipePtr pipe = &pI830->pipes[p]; + int pipe_width = pipe->x + pipe->curMode.HDisplay; + int pipe_height = pipe->y + pipe->curMode.VDisplay; + if (pipe->enabled && pipe_width > width) + width = pipe_width; + if (pipe->enabled && pipe_height > height) + height = pipe_height; + } + + if (width && height) { int mmWidth, mmHeight; mmWidth = pScreen->mmWidth; mmHeight = pScreen->mmHeight; - if (mode->HDisplay != pScreen->width) - mmWidth = mmWidth * mode->HDisplay / pScreen->width; - if (mode->VDisplay != pScreen->height) - mmHeight = mmHeight * mode->VDisplay / pScreen->height; + if (width != pScreen->width) + mmWidth = mmWidth * width / pScreen->width; + if (height != pScreen->height) + mmHeight = mmHeight * height / pScreen->height; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Setting screen physical size to %d x %d\n", mmWidth, mmHeight); I830RandRScreenSetSize (pScreen, - mode->HDisplay, - mode->VDisplay, + width, + height, mmWidth, mmHeight); } for (p = 0; p < pI830->num_pipes; p++) - { - i830PipeSetBase(pScrn, p, 0, 0); I830RandRCrtcNotify (pI830->pipes[p].randr_crtc); - } - if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -926,19 +932,348 @@ I830RandRInit12 (ScreenPtr pScreen) pScrn->PointerMoved = I830RandRPointerMoved; return TRUE; } + +static RRModePtr +I830RRDefaultMode (RROutputPtr output) +{ + RRModePtr target_mode = NULL; + int target_diff = 0; + int mmHeight; + int num_modes; + int m; + + num_modes = output->numPreferred ? output->numPreferred : output->numModes; + mmHeight = output->mmHeight; + if (!mmHeight) + mmHeight = 203; /* 768 pixels at 96dpi */ + /* + * Pick a mode closest to 96dpi + */ + for (m = 0; m < num_modes; m++) + { + RRModePtr mode = output->modes[m]; + int dpi; + int diff; + + dpi = (mode->mode.height * 254) / (mmHeight * 10); + diff = dpi - 96; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static RRModePtr +I830ClosestMode (RROutputPtr output, RRModePtr match) +{ + RRModePtr target_mode = NULL; + int target_diff = 0; + int m; + + /* + * Pick a mode closest to the specified mode + */ + for (m = 0; m < output->numModes; m++) + { + RRModePtr mode = output->modes[m]; + int dx, dy; + int diff; + + /* exact matches are preferred */ + if (mode == match) + return mode; + + dx = match->mode.width - mode->mode.width; + dy = match->mode.height - mode->mode.height; + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static int +I830RRPickCrtcs (RROutputPtr *outputs, + RRCrtcPtr *best_crtcs, + RRModePtr *modes, + int num_outputs, + int n) +{ + int c, o, l; + RROutputPtr output; + RRCrtcPtr crtc; + RRCrtcPtr *crtcs; + RRCrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == num_outputs) + return 0; + output = outputs[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_outputs, n+1); + if (modes[n] == NULL) + return best_score; + + crtcs = xalloc (num_outputs * sizeof (RRCrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->connection == RR_Connected) + my_score++; + /* Score outputs with preferred modes higher */ + if (output->numPreferred) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < output->numCrtcs; c++) + { + crtc = output->crtcs[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (modes[o] == modes[n]) + { + for (l = 0; l < output->numClones; l++) + if (output->clones[l] == outputs[o]) + break; + if (l == output->numClones) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr)); + score = my_score + I830RRPickCrtcs (outputs, crtcs, modes, + num_outputs, n+1); + if (score >= best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, num_outputs * sizeof (RRCrtcPtr)); + } + } + xfree (crtcs); + return best_score; +} + +static Bool +I830RRInitialConfiguration (RROutputPtr *outputs, + RRCrtcPtr *crtcs, + RRModePtr *modes, + int num_outputs) +{ + int o; + RRModePtr target_mode = NULL; + + for (o = 0; o < num_outputs; o++) + modes[o] = NULL; + + /* + * Let outputs with preferred modes drive screen size + */ + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + if (output->connection != RR_Disconnected && output->numPreferred) + { + target_mode = I830RRDefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + break; + } + } + } + if (!target_mode) + { + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + if (output->connection != RR_Disconnected) + { + target_mode = I830RRDefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + break; + } + } + } + } + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + if (output->connection != RR_Disconnected && !modes[o]) + modes[o] = I830ClosestMode (output, target_mode); + } + + if (!I830RRPickCrtcs (outputs, crtcs, modes, num_outputs, 0)) + return FALSE; + + return TRUE; +} + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in a panorama configuration + */ + +static void +I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs, + RRCrtcPtr *crtcs, int num_crtc, + int *widthp, int *heightp) +{ + int width = 0, height = 0; + int o; + int c; + int m; + int s; + + for (c = 0; c < num_crtc; c++) + { + RRCrtcPtr crtc = crtcs[c]; + int crtc_width = 1600, crtc_height = 1200; + + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + for (s = 0; s < output->numCrtcs; s++) + if (output->crtcs[s] == crtc) + break; + if (s == output->numCrtcs) + continue; + for (m = 0; m < output->numModes; m++) + { + RRModePtr mode = output->modes[m]; + if (mode->mode.width > crtc_width) + crtc_width = mode->mode.width; + if (mode->mode.height > crtc_width) + crtc_height = mode->mode.height; + } + } + width += crtc_width; + if (crtc_height > height) + height = crtc_height; + } + *widthp = width; + *heightp = height; +} + #endif Bool I830RandRPreInit (ScrnInfoPtr pScrn) { - int n; + I830Ptr pI830 = I830PTR(pScrn); +#if RANDR_12_INTERFACE + RROutputPtr outputs[MAX_OUTPUTS]; + RRCrtcPtr output_crtcs[MAX_OUTPUTS]; + RRModePtr output_modes[MAX_OUTPUTS]; + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + int width, height; + int o; + int c; +#endif - n = I830ValidateXF86ModeList(pScrn, TRUE); - if (n <= 0) + if (pI830->num_outputs <= 0) return FALSE; + + i830_reprobe_output_modes(pScrn); + #if RANDR_12_INTERFACE if (!I830RandRCreateObjects12 (pScrn)) return FALSE; + + /* + * Configure output modes + */ + if (!I830RandRSetInfo12 (pScrn)) + return FALSE; + /* + * With RandR info set up, let RandR choose + * the initial configuration + */ + for (o = 0; o < pI830->num_outputs; o++) + outputs[o] = pI830->output[o].randr_output; + for (c = 0; c < pI830->num_pipes; c++) + crtcs[c] = pI830->pipes[c].randr_crtc; + + if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes, + pI830->num_outputs)) + return FALSE; + + I830RRDefaultScreenLimits (outputs, pI830->num_outputs, + crtcs, pI830->num_pipes, + &width, &height); + + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + + for (o = 0; o < pI830->num_outputs; o++) + { + RRModePtr randr_mode = output_modes[o]; + DisplayModePtr mode; + RRCrtcPtr randr_crtc = output_crtcs[o]; + int pipe; + Bool enabled; + + if (randr_mode) + mode = (DisplayModePtr) randr_mode->devPrivate; + else + mode = NULL; + if (randr_crtc) + { + pipe = (int) randr_crtc->devPrivate; + enabled = TRUE; + } + else + { + pipe = 0; + enabled = FALSE; + } + pI830->pipes[pipe].desiredMode = *mode; + pI830->output[o].pipe = pipe; + pI830->output[o].enabled = enabled; + } #endif + i830_set_xf86_modes_from_outputs (pScrn); + + i830_set_default_screen_size(pScrn); + return TRUE; } From 7a7bb331e10498e5b8ccec58130bb23334d36562 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 Nov 2006 21:19:20 -0800 Subject: [PATCH 257/257] Don't dereference null DisplayModePtr on disabled output. During initial configuration, outputs which are disabled have null modes. --- src/i830_randr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index e01ac1e1..d27125f4 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -1266,7 +1266,8 @@ I830RandRPreInit (ScrnInfoPtr pScrn) pipe = 0; enabled = FALSE; } - pI830->pipes[pipe].desiredMode = *mode; + if (mode) + pI830->pipes[pipe].desiredMode = *mode; pI830->output[o].pipe = pipe; pI830->output[o].enabled = enabled; }