From 5b530c34e489fbb02baa367eae540a2066945156 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Tue, 10 Feb 2009 08:00:00 +0100 Subject: [coding style] Correct indentation. Signed-off-by: Paul Menzel Signed-off-by: Thomas Hilber --- src/i810_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i810_driver.c b/src/i810_driver.c index 4b716608..75cac8c7 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -263,7 +263,7 @@ static const OptionInfoRec I810Options[] = { {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, - {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ -- cgit v1.2.3 From d52e966afea55c361b59718b82e3f7d5fccf52ac Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Tue, 10 Feb 2009 09:00:00 +0100 Subject: Add frame rate control. - Full functionality of Radeon based original patch now ported to recent Intel graphics hardware. This includes support for i945G chipsets as found on EEE PCs and D945GCLF[2] boards. - Exploits some special features of i945G chipsets like vertical phase registers and fine tuning of vertical scaling. This enables us to compensate for interference effects observed when driving modern digital displays through a SCART interface. Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i810_driver.c | 12 +- src/i830.h | 5 + src/i830_crt.c | 8 +- src/i830_display.c | 17 ++- src/i830_driver.c | 63 +++++++++ src/i830_video.c | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 460 insertions(+), 22 deletions(-) diff --git a/src/i810_driver.c b/src/i810_driver.c index 75cac8c7..a6b87743 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -250,7 +250,11 @@ typedef enum { OPTION_NO_DDC, OPTION_SHOW_CACHE, OPTION_XVMC_SURFACES, - OPTION_PAGEFLIP + OPTION_PAGEFLIP, + OPTION_SYNC_FIELDS, + OPTION_YSCALE_FTUNE, + OPTION_YRGB_VPHASE, + OPTION_UV_VPHASE, } I810Opts; static const OptionInfoRec I810Options[] = { @@ -264,6 +268,10 @@ static const OptionInfoRec I810Options[] = { {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SYNC_FIELDS, "SyncFields", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_YSCALE_FTUNE, "YScaleFineTune",OPTV_INTEGER, {0}, FALSE}, + {OPTION_YRGB_VPHASE, "YRGB_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_UV_VPHASE, "UV_VPhase", OPTV_INTEGER, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -2845,7 +2853,9 @@ I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) xf86DrvMsg(scrnIndex, X_PROBED, "Removing interlaced mode \"%s\"\n", mode->name); } +#if 0 /* allow interlaced mode */ return MODE_BAD; +#endif } return MODE_OK; } diff --git a/src/i830.h b/src/i830.h index def693fb..7eded9d1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -523,6 +523,11 @@ typedef struct _I830Rec { Bool *overlayOn; #endif + Bool sync_fields; + int YScale_ftune; + int YRGB_vphase; + int UV_vphase; + /* EXA render state */ float scale_units[2][2]; /** Transform pointers for src/mask, or NULL if identity */ diff --git a/src/i830_crt.c b/src/i830_crt.c index 2a99f9c7..c6e016ee 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -87,7 +87,7 @@ i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) if (pMode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; - if (pMode->Clock > 400000 || pMode->Clock < 25000) + if (pMode->Clock > 400000 || pMode->Clock < 12000) /* lower minimum dotclk */ return MODE_CLOCK_RANGE; return MODE_OK; @@ -381,6 +381,12 @@ i830_crt_detect(xf86OutputPtr output) out: i830ReleaseLoadDetectPipe (output, dpms_mode); +#if 0 /* not yet */ + /* + * we also want to boot the Xserver without a CRT connected + */ + status = XF86OutputStatusConnected; +#endif return status; } diff --git a/src/i830_display.c b/src/i830_display.c index df2f1a24..8e873dfd 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -95,9 +95,9 @@ typedef struct { #define I8XX_P2_LVDS_FAST 7 #define I8XX_P2_SLOW_LIMIT 165000 -#define I9XX_DOT_MIN 20000 +#define I9XX_DOT_MIN 12000 /* allow for PAL modes */ #define I9XX_DOT_MAX 400000 -#define I9XX_VCO_MIN 1400000 +#define I9XX_VCO_MIN 1000000 /* allow for PAL modes */ #define I9XX_VCO_MAX 2800000 /* Haven't found any reason to go this fast, but newer chips support it */ @@ -950,6 +950,14 @@ static Bool i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) { + if (mode->Flags & V_INTERLACE) { + mode->CrtcVDisplay = adjusted_mode->CrtcVDisplay = mode->VDisplay; + mode->CrtcVSyncStart = adjusted_mode->CrtcVSyncStart = mode->VSyncStart; + mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncEnd = mode->VSyncEnd; + mode->CrtcVBlankStart = adjusted_mode->CrtcVBlankStart = mode->CrtcVDisplay; + mode->CrtcVBlankEnd = adjusted_mode->CrtcVBlankEnd = mode->VTotal; + mode->CrtcVTotal = adjusted_mode->CrtcVTotal = mode->VTotal; + } return TRUE; } @@ -1341,6 +1349,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* Wait for the clocks to stabilize. */ usleep(150); + if (adjusted_mode->Flags & V_INTERLACE) { + pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; + } else { + pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; + } OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) | ((adjusted_mode->CrtcHTotal - 1) << 16)); OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) | diff --git a/src/i830_driver.c b/src/i830_driver.c index 563d167f..56fbe968 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -311,6 +311,10 @@ typedef enum { #ifdef INTEL_XVMC OPTION_XVMC, #endif + OPTION_SYNC_FIELDS, + OPTION_YSCALE_FTUNE, + OPTION_YRGB_VPHASE, + OPTION_UV_VPHASE, } I830Opts; static OptionInfoRec I830Options[] = { @@ -339,6 +343,10 @@ static OptionInfoRec I830Options[] = { #ifdef INTEL_XVMC {OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, TRUE}, #endif + {OPTION_SYNC_FIELDS, "SyncFields", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_YSCALE_FTUNE,"YScaleFineTune",OPTV_INTEGER, {0}, FALSE}, + {OPTION_YRGB_VPHASE, "YRGB_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_UV_VPHASE, "UV_VPhase", OPTV_INTEGER, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -1652,6 +1660,43 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->colorKey); #endif + if (xf86GetOptValInteger(pI830->Options, OPTION_SYNC_FIELDS, + &(pI830->sync_fields))) { + from = X_CONFIG; + } else { + pI830->sync_fields = TRUE; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "sync fields %sactivated\n", + pI830->sync_fields ? "" : "de"); + if (xf86GetOptValInteger(pI830->Options, OPTION_YSCALE_FTUNE, + &(pI830->YScale_ftune))) { + from = X_CONFIG; + } else { + pI830->YScale_ftune = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "vertical scale fine tuning set to %d\n", + pI830->YScale_ftune); + if (xf86GetOptValInteger(pI830->Options, OPTION_YRGB_VPHASE, + &(pI830->YRGB_vphase))) { + from = X_CONFIG; + } else { + pI830->YRGB_vphase = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Y/RGB vertical phase set to 0x%x\n", + pI830->YRGB_vphase); + if (xf86GetOptValInteger(pI830->Options, OPTION_UV_VPHASE, + &(pI830->UV_vphase))) { + from = X_CONFIG; + } else { + pI830->UV_vphase = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "UV vertical phase set to 0x%x\n", + pI830->UV_vphase); + #ifdef XF86DRI pI830->allowPageFlip = FALSE; from = (!pI830->directRenderingDisabled && @@ -1736,6 +1781,24 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Set display resolution */ xf86SetDpi(pScrn, 0, 0); + if (!(pScrn->currentMode->Flags & V_INTERLACE) + && pI830->sync_fields) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields on non interlaced displays, disabled\n"); + pI830->sync_fields = 0; + } + + /* + * sync_fields only works with + * ModeLine "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace + */ + if ((pScrn->currentMode->Clock != 27750 + || pScrn->currentMode->HDisplay != 1440 + || pScrn->currentMode->VDisplay != 576) + && pI830->sync_fields) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields with current timing, disabled\n"); + pI830->sync_fields = 0; + } + /* Load the required sub modules */ if (!xf86LoadSubModule(pScrn, "fb")) { PreInitCleanup(pScrn); diff --git a/src/i830_video.c b/src/i830_video.c index 91e0e009..e3eaf58c 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -94,6 +94,7 @@ #define TIMER_MASK (OFF_TIMER | FREE_TIMER) +static void vga_sync_fields(I830Ptr); static void I830InitOffscreenImages(ScreenPtr); static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr); @@ -603,19 +604,35 @@ I830InitVideo(ScreenPtr pScreen) xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); - /* Set up textured video if we can do it at this depth and we are on - * supported hardware. - */ - if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) && - !(!IS_I965G(pI830) && pScrn->displayWidth > 2048)) - { - texturedAdaptor = I830SetupImageVideoTextured(pScreen); - if (texturedAdaptor != NULL) { - adaptors[num_adaptors++] = texturedAdaptor; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to set up textured video\n"); +#if 0 /* always use overlay */ + if (pI830->sync_fields) { +#else + if (1) { +#endif + /* + * we deactivate textured XV method for compatibility with older xine-lib + * versions not providing a configuration parameter for this. + * for further information see: + * 'video.device.xv_preferred_method' in file 'config_xineliboutput' + */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGA_SYNC_FIELDS disabled textured video mode\n"); + } else { + + /* + * Set up textured video if we can do it at this depth and we are on + * supported hardware. + */ + if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) && + !(!IS_I965G(pI830) && pScrn->displayWidth > 2048)) + { + texturedAdaptor = I830SetupImageVideoTextured(pScreen); + if (texturedAdaptor != NULL) { + adaptors[num_adaptors++] = texturedAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up textured video\n"); + } } } @@ -2013,7 +2030,11 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, * Y down-scale factor as a multiple of 4096. */ xscaleFract = ((src_w - 1) << 12) / drw_w; - yscaleFract = ((src_h - 1) << 12) / drw_h; + if (pI830->sync_fields) { + yscaleFract = (((src_h >> 1) - 1 + pI830->YScale_ftune) << 12) / drw_h; + } else { + yscaleFract = ((src_h - 1) << 12) / drw_h; + } /* Calculate the UV scaling factor. */ xscaleFractUV = xscaleFract / uvratio; @@ -2113,9 +2134,15 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, } } } - - OCMD = OVERLAY_ENABLE; - + if (pI830->sync_fields) { + OCMD = OVERLAY_ENABLE | BUF_TYPE_FIELD | TVSYNC_FLIP_ENABLE; + overlay->YRGB_VPH = pI830->YRGB_vphase; + overlay->UV_VPH = pI830->UV_vphase; + overlay->HORZ_PH = 0; + overlay->INIT_PHS = 0; + } else { + OCMD = OVERLAY_ENABLE; + } switch (id) { case FOURCC_YV12: case FOURCC_I420: @@ -2145,7 +2172,6 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, OCMD |= Y_SWAP; break; } - OCMD &= ~(BUFFER_SELECT | FIELD_SELECT); if (pPriv->currentBuf == 0) OCMD |= BUFFER0; @@ -2525,6 +2551,9 @@ I830PutImage(ScrnInfoPtr pScrn, } if (!pPriv->textured) { + if (pI830->sync_fields) { + vga_sync_fields(RecPtr); + } i830_display_video(pScrn, crtc, destId, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); @@ -2964,3 +2993,315 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) pPriv->oneLineMode = FALSE; } } + +/* --- 8< --- */ +/* + * field cycle duration in usecs for PAL + */ +#define SYF_PAL_FIELD_CYCLE 20000 + +/* + * frame cycle duration in usecs for PAL + */ +#define SYF_PAL_FRAME_CYCLE (SYF_PAL_FIELD_CYCLE << 1) + +/* + * dependent on interlaced (progressive) input frame rate 25 (50) fps + * we set this to 0 (1). other params should adjust accordingly. + */ +#define SYF_INPUT_DOUBLE_RATE 0 + +/* + * prefilter to prevent stray updates. + * our software PLL will not try to lock for these. + */ +#define SYF_CATCH_RANGE (18000 >> SYF_INPUT_DOUBLE_RATE) + +/* + * updates outside time window defined by this + * value spawn warnings when in debug mode + */ +#define SYF_WARN_RANGE (15000 >> SYF_INPUT_DOUBLE_RATE) + +/* + * we average 25 (50) frames to yield a cycle time of + * about one second for analysis of frame rate data. + * this serves as frequency divider for our software PLL. + */ +#define SYF_PLL_DIVIDER (25 << SYF_INPUT_DOUBLE_RATE) + +/* + * input frame cycle duration in usecs for 25 (50) fps + */ +#define SYF_FRAME_CYCLE (SYF_PAL_FRAME_CYCLE >> SYF_INPUT_DOUBLE_RATE) + +/* + * offset in usecs from double buffer switch where we try to place double + * buffer updates. + * this minimizes sensivity to jitter of our software PLL phase comparator. + */ +#define SYF_SYNC_POINT (SYF_FRAME_CYCLE >> 1) + +/* + * one trim increment compensates drift speed for about 29usec/sec. + * this represents resolution of our VCO input. + */ +#define SYF_MIN_STEP_USEC 700 + +/* NOT CURRENTLY USED + * factor weighting drift against sync point displacement + * when calculating overall compensation + */ +#define SYF_DISP_DRIFT_FACTOR 1 + +/* NOT CURRENTLY USED + * to allow for smooth adaption also on slower devices we delimit maximum + * trim change per step size. + * this implements some kind of low pass filter for our VCO input. + */ +#define SYF_MAX_TRIM_REL 1000 + +/* + * maximum absolute trim values allowed due to current + * hardware/driver contraints. + * this delimits 'maximum voltage' controlling our VCO. + * currently allowed range is defined symmetrically around the center voltage. + */ +#define SYF_MAX_TRIM_ABS 2 + +#define DEBUG +#ifdef DEBUG +#define ERRORF ErrorF +#else +#define ERRORF(...) +#endif + +#define USE_METER +#ifdef USE_METER +#define OUT_GRAPHIC meter_out +extern void meter_out(int, int); +#else +#define OUT_GRAPHIC(...) +#endif + +#ifdef STANDALONE + +#define DOVSTA 0x30008 +#define HTOTAL_A 0x60000 +#define HBLANK_A 0x60004 +#define HSYNC_A 0x60008 +#define PIPEA_DSL 0x70000 +#define PIPEACONF 0x70008 + +#define ErrorF printf +#define B(a) (*(argv + (a)) ? *(argv + (a)) : 0) +#define INREG(reg) *(volatile unsigned *)(vptr + (reg)) +#define OUTREG(reg, val) INREG(reg) = (val) +#define min(a, b) ((a) <= (b) ? (a) : (b)) +#define max(a, b) ((a) >= (b) ? (a) : (b)) +#define abs(a) ((a) >= 0 ? (a) : -(a)) +#else +#define B(a) (a) +#endif +#define OC_FIELD (1 << 19) + +#include +#include + +typedef struct _syf { + int cnt; + int tsum; + int trim; + int drift; + int spoint; +} syf_t; + +typedef struct _drm_i945_syncf { + struct timeval tv_now; + struct timeval tv_vbl; + unsigned trim; +} drm_i945_syncf_t; + +#define VSF_SUB(a, b, c) \ + if ((a).tv_usec < (b).tv_usec) { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ + } else { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ + } + +#define VSF_TV2USEC(a, b) \ + (b) = (a).tv_sec * 1000000 + (a).tv_usec; + +/* + * following values are hardcoded at the moment. they only work with + * the modeline given below. though they appear to comply with + * various i945 based motherboard designs. + * + * ModeLine "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace + */ +#define HTOTAL_A_OPT 0x06e8059f +#define HSYNC_A_OPT 0x064805cf + +void +meter_out(val, symb) +{ + static char meter[81]; + static char headr[81] = "|<- -20ms 0 +20ms ->|"; + + if (!symb || symb == 1) { + if (!symb) ErrorF("%s", headr); + if (symb == 1) ErrorF("%s", meter); + memset(meter, '-', 80); + return; + } + val /= 500; + val = min(val, 39); + val = max(val, -40); + meter[40 + val] = symb; +} +/* --- 8< --- */ + +void +vga_sync_fields(RecPtr) + I830Ptr RecPtr; +{ + static syf_t syf, syf_clear; + static drm_i945_syncf_t syncf_prev; + static struct timeval skew2vbl_prev; + + drm_i945_syncf_t syncf; + struct timeval skew2vbl; + struct timeval tv_usecs; + int usecs; + int dovsta, pipea_dsl; + +/* --- 8< --- */ + syncf.trim = (INREG(HTOTAL_A) >> 16) - (HTOTAL_A_OPT >> 16); + gettimeofday(&syncf.tv_now, 0); + + /* + * DOVSTA 0x00104000 => PIPEA_DSL 0x0000011e + * DOVSTA 0x80085000 => PIPEA_DSL 0x0000011f + * [...] + * DOVSTA 0x80104000 => PIPEA_DSL 0x00000138 + * DOVSTA 0x80104000 => PIPEA_DSL 0x00000000 + * + * the chip does not provide current field status directly. + * but we can derive that from xor'ed dovsta and pipea_dsl contents. + * _______________ ________ + * ____| |_______________| dovsta + * ___ ___ ___ + * ____| |___________| |___________| |____ pipea_dsl + * _______________ ____ + * ________| |_______________| field status + * + * 0 286 312 + */ + +#define FIELD_SWITCH_THRESHOLD 287 + + /* field * 20000 + line * 64 == 39968 max. for field==1, line==312 */ + dovsta = INREG(DOVSTA); + pipea_dsl = INREG(PIPEA_DSL); + skew2vbl.tv_usec = + (pipea_dsl < FIELD_SWITCH_THRESHOLD ^ !(dovsta & OC_FIELD)) + * SYF_PAL_FIELD_CYCLE + (pipea_dsl << 6); + skew2vbl.tv_sec = 0; + VSF_SUB(syncf.tv_now, skew2vbl, syncf.tv_vbl); + VSF_SUB(syncf.tv_now, syncf_prev.tv_now, tv_usecs); + VSF_TV2USEC(tv_usecs, usecs); +#ifdef STANDALONE + if (syncf_prev.tv_now.tv_sec) { + usleepv += SYF_FRAME_CYCLE - usecs; + } +#endif + syncf_prev = syncf; + if (abs(usecs - SYF_FRAME_CYCLE) > SYF_CATCH_RANGE) { + + /* + * toss stray intervals and reset + */ + syf = syf_clear; + skew2vbl_prev.tv_sec = ~0; + OUT_GRAPHIC(0, 0); + ErrorF(" R %11d\n", usecs); +#ifdef STANDALONE + goto main_loop_end; +#else + return; +#endif + } + if (abs(usecs - SYF_FRAME_CYCLE) > SYF_WARN_RANGE) { + OUT_GRAPHIC(0, 0); + ErrorF(" W %11d\n", usecs); + } + +#ifndef STANDALONE + + /* + * we must delay the next double buffer update + * until even field has been processed. this occurs + * after scan line FIELD_SWITCH_THRESHOLD has been passed. + * on a sufficiently synchronized system running at a + * sync point of about 20000 usecs this imposes + * no additional sleep time. + * + * 0 even 20000 odd 40000 + * |-------------------|-------------------| + * ...---sleep--->| + * 18368 + */ + if (skew2vbl.tv_usec < FIELD_SWITCH_THRESHOLD << 6) { + usleep((FIELD_SWITCH_THRESHOLD << 6) - skew2vbl.tv_usec); + } +#endif + VSF_SUB(syncf.tv_now, syncf.tv_vbl, skew2vbl) + if (skew2vbl_prev.tv_sec != ~0) { + syf.tsum += usecs; + syf.spoint += skew2vbl.tv_usec - SYF_SYNC_POINT; + VSF_SUB(skew2vbl, skew2vbl_prev, tv_usecs); + VSF_TV2USEC(tv_usecs, usecs); + syf.drift += usecs; + ++syf.cnt; + } + if (skew2vbl_prev.tv_sec != ~0 && !(syf.cnt % SYF_PLL_DIVIDER)) { + syf.spoint /= SYF_PLL_DIVIDER; + OUT_GRAPHIC(0, '+'); + OUT_GRAPHIC(syf.spoint, '|'); + OUT_GRAPHIC(syf.drift, '*'); + OUT_GRAPHIC(0, 1); + + syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; + syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); + syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); + ERRORF("%7d %7d [%3d%+4d] %7d\n", syf.drift, syf.spoint, + (char)(syncf.trim & 0xff), syf.trim, syf.tsum); + syf.spoint = 0; + syf.drift = 0; + syf.tsum = 0; + } + if (B(1) && syf.trim) { + int t = (char)(syncf.trim & 0xff); + + if (syf.trim > 0) { + t = min(t + 1, SYF_MAX_TRIM_ABS); + --syf.trim; + } else { + t = max(t - 1, -SYF_MAX_TRIM_ABS); + ++syf.trim; + } + if (syncf.trim != t) { + t <<= 16; + OUTREG(HTOTAL_A, HTOTAL_A_OPT + t); + OUTREG(HBLANK_A, HTOTAL_A_OPT + t); + OUTREG(HSYNC_A, HSYNC_A_OPT + (t << 1)); + OUTREG(PIPEACONF, INREG(PIPEACONF)); + } + } + skew2vbl_prev = skew2vbl; +/* --- 8< --- */ + +} + -- cgit v1.2.3 From 963ebc32418f0afb6fb45ef0d707e2c704935962 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Thu, 19 Mar 2009 21:54:33 +0100 Subject: New options for xorg.conf and start with disconnected monitor. - introduced new xorg.conf options for both intel and radeon FRC patches - FRC (aka sync_fields) switch (default on) - process priority (default 0) - FRC debug output (default off) - intel Xserver now starts even with disconnected monitor Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i810_driver.c | 10 +++++++--- src/i830.h | 2 ++ src/i830_crt.c | 4 +--- src/i830_driver.c | 40 +++++++++++++++++++++++++++++++++++++--- src/i830_video.c | 24 ++++++++++++++---------- 5 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/i810_driver.c b/src/i810_driver.c index a6b87743..eb4c547e 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -255,6 +255,8 @@ typedef enum { OPTION_YSCALE_FTUNE, OPTION_YRGB_VPHASE, OPTION_UV_VPHASE, + OPTION_SCHED_PRIO, + OPTION_SYF_DEBUG, } I810Opts; static const OptionInfoRec I810Options[] = { @@ -269,9 +271,11 @@ static const OptionInfoRec I810Options[] = { {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SYNC_FIELDS, "SyncFields", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_YSCALE_FTUNE, "YScaleFineTune",OPTV_INTEGER, {0}, FALSE}, - {OPTION_YRGB_VPHASE, "YRGB_VPhase", OPTV_INTEGER, {0}, FALSE}, - {OPTION_UV_VPHASE, "UV_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_YSCALE_FTUNE, "SF_YScaleFineTune",OPTV_INTEGER,{0}, FALSE}, + {OPTION_YRGB_VPHASE, "SF_YRGB_VPhase",OPTV_INTEGER, {0}, FALSE}, + {OPTION_UV_VPHASE, "SF_UV_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_SCHED_PRIO, "SF_SchedPrio", OPTV_INTEGER, {0}, FALSE}, + {OPTION_SYF_DEBUG, "SF_Debug", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ diff --git a/src/i830.h b/src/i830.h index 7eded9d1..895a5c5a 100644 --- a/src/i830.h +++ b/src/i830.h @@ -527,6 +527,8 @@ typedef struct _I830Rec { int YScale_ftune; int YRGB_vphase; int UV_vphase; + int SchedPrio; + Bool SYF_debug; /* EXA render state */ float scale_units[2][2]; diff --git a/src/i830_crt.c b/src/i830_crt.c index c6e016ee..653e2c83 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -381,12 +381,10 @@ i830_crt_detect(xf86OutputPtr output) out: i830ReleaseLoadDetectPipe (output, dpms_mode); -#if 0 /* not yet */ /* - * we also want to boot the Xserver without a CRT connected + * allow Xserver to run even without a CRT connected */ status = XF86OutputStatusConnected; -#endif return status; } diff --git a/src/i830_driver.c b/src/i830_driver.c index 56fbe968..3d880677 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -200,6 +200,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #if HAVE_SYS_MMAN_H && HAVE_MPROTECT #include #endif +#include "sys/resource.h" #ifdef INTEL_XVMC #define _INTEL_XVMC_SERVER_ @@ -315,6 +316,8 @@ typedef enum { OPTION_YSCALE_FTUNE, OPTION_YRGB_VPHASE, OPTION_UV_VPHASE, + OPTION_SCHED_PRIO, + OPTION_SYF_DEBUG, } I830Opts; static OptionInfoRec I830Options[] = { @@ -344,9 +347,11 @@ static OptionInfoRec I830Options[] = { {OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, TRUE}, #endif {OPTION_SYNC_FIELDS, "SyncFields", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_YSCALE_FTUNE,"YScaleFineTune",OPTV_INTEGER, {0}, FALSE}, - {OPTION_YRGB_VPHASE, "YRGB_VPhase", OPTV_INTEGER, {0}, FALSE}, - {OPTION_UV_VPHASE, "UV_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_YSCALE_FTUNE,"SF_YScaleFineTune",OPTV_INTEGER,{0}, FALSE}, + {OPTION_YRGB_VPHASE, "SF_YRGB_VPhase",OPTV_INTEGER, {0}, FALSE}, + {OPTION_UV_VPHASE, "SF_UV_VPhase", OPTV_INTEGER, {0}, FALSE}, + {OPTION_SCHED_PRIO, "SF_SchedPrio", OPTV_INTEGER, {0}, FALSE}, + {OPTION_SYF_DEBUG, "SF_Debug", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -1696,6 +1701,24 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } xf86DrvMsg(pScrn->scrnIndex, from, "UV vertical phase set to 0x%x\n", pI830->UV_vphase); + if (xf86GetOptValInteger(pI830->Options, OPTION_SCHED_PRIO, + &(pI830->SchedPrio))) { + from = X_CONFIG; + } else { + pI830->SchedPrio = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "scheduling priority requested %d\n", + pI830->SchedPrio); + if (xf86GetOptValInteger(pI830->Options, OPTION_SYF_DEBUG, + &(pI830->SYF_debug))) { + from = X_CONFIG; + } else { + pI830->SYF_debug = FALSE; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "sync fields debug %sactivated\n", + pI830->SYF_debug ? "" : "de"); #ifdef XF86DRI pI830->allowPageFlip = FALSE; @@ -1798,6 +1821,17 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields with current timing, disabled\n"); pI830->sync_fields = 0; } + if (pI830->sync_fields) { + if (pI830->SchedPrio) { + if (setpriority(PRIO_PROCESS, 0, pI830->SchedPrio)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to setpriority as requested: %s\n", strerror(errno)); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "set scheduling priority to %d\n", getpriority(PRIO_PROCESS, 0)); + } + } + } /* Load the required sub modules */ if (!xf86LoadSubModule(pScrn, "fb")) { diff --git a/src/i830_video.c b/src/i830_video.c index e3eaf58c..ba3242e9 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2172,6 +2172,7 @@ i830_display_video(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, OCMD |= Y_SWAP; break; } + OCMD &= ~(BUFFER_SELECT | FIELD_SELECT); if (pPriv->currentBuf == 0) OCMD |= BUFFER0; @@ -2552,7 +2553,7 @@ I830PutImage(ScrnInfoPtr pScrn, if (!pPriv->textured) { if (pI830->sync_fields) { - vga_sync_fields(RecPtr); + vga_sync_fields(pI830); } i830_display_video(pScrn, crtc, destId, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, @@ -3164,8 +3165,8 @@ meter_out(val, symb) /* --- 8< --- */ void -vga_sync_fields(RecPtr) - I830Ptr RecPtr; +vga_sync_fields(pI830) + I830Ptr pI830; { static syf_t syf, syf_clear; static drm_i945_syncf_t syncf_prev; @@ -3268,16 +3269,19 @@ vga_sync_fields(RecPtr) } if (skew2vbl_prev.tv_sec != ~0 && !(syf.cnt % SYF_PLL_DIVIDER)) { syf.spoint /= SYF_PLL_DIVIDER; - OUT_GRAPHIC(0, '+'); - OUT_GRAPHIC(syf.spoint, '|'); - OUT_GRAPHIC(syf.drift, '*'); - OUT_GRAPHIC(0, 1); - + if (pI830->SYF_debug) { + OUT_GRAPHIC(0, '+'); + OUT_GRAPHIC(syf.spoint, '|'); + OUT_GRAPHIC(syf.drift, '*'); + OUT_GRAPHIC(0, 1); + } syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); - ERRORF("%7d %7d [%3d%+4d] %7d\n", syf.drift, syf.spoint, - (char)(syncf.trim & 0xff), syf.trim, syf.tsum); + if (pI830->SYF_debug) { + ERRORF("%7d %7d [%3d%+4d] %7d\n", syf.drift, syf.spoint, + (char)(syncf.trim & 0xff), syf.trim, syf.tsum); + } syf.spoint = 0; syf.drift = 0; syf.tsum = 0; -- cgit v1.2.3 From e41d86277c99debca34a0754c878902c597ac105 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Mon, 23 Mar 2009 12:43:00 +0100 Subject: now automatically raises Xserver sched prio for single processor systems (affects radeon + intel systems) Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_driver.c | 140 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 51 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 3d880677..c7244b55 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1665,6 +1665,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->colorKey); #endif +/* --- SYNC FIELDS setup --- */ if (xf86GetOptValInteger(pI830->Options, OPTION_SYNC_FIELDS, &(pI830->sync_fields))) { from = X_CONFIG; @@ -1674,51 +1675,58 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } xf86DrvMsg(pScrn->scrnIndex, from, "sync fields %sactivated\n", pI830->sync_fields ? "" : "de"); - if (xf86GetOptValInteger(pI830->Options, OPTION_YSCALE_FTUNE, - &(pI830->YScale_ftune))) { - from = X_CONFIG; - } else { - pI830->YScale_ftune = 0; - from = X_DEFAULT; - } - xf86DrvMsg(pScrn->scrnIndex, from, "vertical scale fine tuning set to %d\n", - pI830->YScale_ftune); - if (xf86GetOptValInteger(pI830->Options, OPTION_YRGB_VPHASE, - &(pI830->YRGB_vphase))) { - from = X_CONFIG; - } else { - pI830->YRGB_vphase = 0; - from = X_DEFAULT; - } - xf86DrvMsg(pScrn->scrnIndex, from, "Y/RGB vertical phase set to 0x%x\n", - pI830->YRGB_vphase); - if (xf86GetOptValInteger(pI830->Options, OPTION_UV_VPHASE, - &(pI830->UV_vphase))) { - from = X_CONFIG; - } else { - pI830->UV_vphase = 0; - from = X_DEFAULT; - } - xf86DrvMsg(pScrn->scrnIndex, from, "UV vertical phase set to 0x%x\n", - pI830->UV_vphase); - if (xf86GetOptValInteger(pI830->Options, OPTION_SCHED_PRIO, - &(pI830->SchedPrio))) { - from = X_CONFIG; - } else { - pI830->SchedPrio = 0; - from = X_DEFAULT; - } - xf86DrvMsg(pScrn->scrnIndex, from, "scheduling priority requested %d\n", - pI830->SchedPrio); - if (xf86GetOptValInteger(pI830->Options, OPTION_SYF_DEBUG, - &(pI830->SYF_debug))) { - from = X_CONFIG; - } else { - pI830->SYF_debug = FALSE; - from = X_DEFAULT; + if (pI830->sync_fields) { + if (xf86GetOptValInteger(pI830->Options, OPTION_YSCALE_FTUNE, + &(pI830->YScale_ftune))) { + from = X_CONFIG; + } else { + pI830->YScale_ftune = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "vertical scale fine tuning set to %d\n", + pI830->YScale_ftune); + if (xf86GetOptValInteger(pI830->Options, OPTION_YRGB_VPHASE, + &(pI830->YRGB_vphase))) { + from = X_CONFIG; + } else { + pI830->YRGB_vphase = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Y/RGB vertical phase set to 0x%x\n", + pI830->YRGB_vphase); + if (xf86GetOptValInteger(pI830->Options, OPTION_UV_VPHASE, + &(pI830->UV_vphase))) { + from = X_CONFIG; + } else { + pI830->UV_vphase = 0; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "UV vertical phase set to 0x%x\n", + pI830->UV_vphase); + if (xf86GetOptValInteger(pI830->Options, OPTION_SCHED_PRIO, + &(pI830->SchedPrio))) { + from = X_CONFIG; + } else { + pI830->SchedPrio = ~0; + from = X_DEFAULT; + } + if (pI830->SchedPrio == ~0) { + xf86DrvMsg(pScrn->scrnIndex, from, "scheduling priority not set explicitly\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, from, "scheduling priority requested %d\n", + pI830->SchedPrio); + } + if (xf86GetOptValInteger(pI830->Options, OPTION_SYF_DEBUG, + &(pI830->SYF_debug))) { + from = X_CONFIG; + } else { + pI830->SYF_debug = FALSE; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, "sync fields debug %sactivated\n", + pI830->SYF_debug ? "" : "de"); } - xf86DrvMsg(pScrn->scrnIndex, from, "sync fields debug %sactivated\n", - pI830->SYF_debug ? "" : "de"); +/* --- SYNC FIELDS setup --- */ #ifdef XF86DRI pI830->allowPageFlip = FALSE; @@ -1804,6 +1812,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Set display resolution */ xf86SetDpi(pScrn, 0, 0); +/* --- SYNC FIELDS check --- */ if (!(pScrn->currentMode->Flags & V_INTERLACE) && pI830->sync_fields) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields on non interlaced displays, disabled\n"); @@ -1822,16 +1831,45 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->sync_fields = 0; } if (pI830->sync_fields) { - if (pI830->SchedPrio) { - if (setpriority(PRIO_PROCESS, 0, pI830->SchedPrio)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "failed to setpriority as requested: %s\n", strerror(errno)); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "set scheduling priority to %d\n", getpriority(PRIO_PROCESS, 0)); + if (pI830->SchedPrio != ~0) { + if (pI830->SchedPrio) { + if (setpriority(PRIO_PROCESS, 0, pI830->SchedPrio)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to set scheduling priority as requested: %s\n", strerror(errno)); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "set scheduling priority to %d as requested\n", getpriority(PRIO_PROCESS, 0)); + } + } + } else { + FILE *f; + int cores = ~0; + + /* + * on single core systems enable higher prio per default + */ + if (f = fopen("/proc/cpuinfo", "r")) { + char buf[256]; + while (fgets(buf, 255, f)) { + sscanf(buf, "processor : %d", &cores); + } + fclose(f); + } + +#define DFLT_SCHEDPRIO_1CORE -20 + + if (!cores) { + if (setpriority(PRIO_PROCESS, 0, DFLT_SCHEDPRIO_1CORE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to set scheduling priority (single core system): %s\n", strerror(errno)); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "set scheduling priority to %d (single core system)\n", getpriority(PRIO_PROCESS, 0)); + } } } } +/* --- SYNC FIELDS check --- */ /* Load the required sub modules */ if (!xf86LoadSubModule(pScrn, "fb")) { -- cgit v1.2.3 From 924ad01f62dfd58a1364fed62739487fb60cc394 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Sat, 16 May 2009 18:10:26 +0200 Subject: Include support for Intel D945GSEJT (Johnstown) and ASUS Eee PC 701 4G. - support for Intel D945GSEJT (Johnstown) included - support for Asus Eee PC 701 included Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_video.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index ba3242e9..7f2c8e32 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3121,6 +3121,8 @@ typedef struct _drm_i945_syncf { struct timeval tv_now; struct timeval tv_vbl; unsigned trim; + unsigned htotal_a; + unsigned hsync_a; } drm_i945_syncf_t; #define VSF_SUB(a, b, c) \ @@ -3135,16 +3137,6 @@ typedef struct _drm_i945_syncf { #define VSF_TV2USEC(a, b) \ (b) = (a).tv_sec * 1000000 + (a).tv_usec; -/* - * following values are hardcoded at the moment. they only work with - * the modeline given below. though they appear to comply with - * various i945 based motherboard designs. - * - * ModeLine "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace - */ -#define HTOTAL_A_OPT 0x06e8059f -#define HSYNC_A_OPT 0x064805cf - void meter_out(val, symb) { @@ -3179,7 +3171,11 @@ vga_sync_fields(pI830) int dovsta, pipea_dsl; /* --- 8< --- */ - syncf.trim = (INREG(HTOTAL_A) >> 16) - (HTOTAL_A_OPT >> 16); + if (!syncf_prev.htotal_a) { + syncf_prev.htotal_a = INREG(HTOTAL_A); + syncf_prev.hsync_a = INREG(HSYNC_A); + } + syncf.trim = (INREG(HTOTAL_A) >> 16) - (syncf_prev.htotal_a >> 16); gettimeofday(&syncf.tv_now, 0); /* @@ -3218,7 +3214,7 @@ vga_sync_fields(pI830) usleepv += SYF_FRAME_CYCLE - usecs; } #endif - syncf_prev = syncf; + syncf_prev.tv_now = syncf.tv_now; if (abs(usecs - SYF_FRAME_CYCLE) > SYF_CATCH_RANGE) { /* @@ -3298,9 +3294,9 @@ vga_sync_fields(pI830) } if (syncf.trim != t) { t <<= 16; - OUTREG(HTOTAL_A, HTOTAL_A_OPT + t); - OUTREG(HBLANK_A, HTOTAL_A_OPT + t); - OUTREG(HSYNC_A, HSYNC_A_OPT + (t << 1)); + OUTREG(HTOTAL_A, syncf_prev.htotal_a + t); + OUTREG(HBLANK_A, syncf_prev.htotal_a + t); + OUTREG(HSYNC_A, syncf_prev.hsync_a + (t << 1)); OUTREG(PIPEACONF, INREG(PIPEACONF)); } } -- cgit v1.2.3 From 867bab0b77999d999ca3d3f6bc8c5ec540fa6001 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Fri, 22 May 2009 18:08:00 +0200 Subject: Rewrite for improved D945GSEJT support. - the intel part of the patch did undergo a major rewrite for improved D945GSEJT support - full compatibility to prior intel hardware maintained - in the course of that the debug facility has been improved Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_video.c | 264 +++++++++++++++++++++++++++---------------------------- 1 file changed, 130 insertions(+), 134 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 7f2c8e32..81da67ba 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3012,17 +3012,17 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) */ #define SYF_INPUT_DOUBLE_RATE 0 -/* +/* NOT CURRENTLY USED * prefilter to prevent stray updates. * our software PLL will not try to lock for these. */ -#define SYF_CATCH_RANGE (18000 >> SYF_INPUT_DOUBLE_RATE) +#define SYF_CATCH_RANGE (SYF_PAL_FRAME_CYCLE - 500 >> SYF_INPUT_DOUBLE_RATE) /* * updates outside time window defined by this * value spawn warnings when in debug mode */ -#define SYF_WARN_RANGE (15000 >> SYF_INPUT_DOUBLE_RATE) +#define SYF_WARN_RANGE (5000 >> SYF_INPUT_DOUBLE_RATE) /* * we average 25 (50) frames to yield a cycle time of @@ -3036,12 +3036,18 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) */ #define SYF_FRAME_CYCLE (SYF_PAL_FRAME_CYCLE >> SYF_INPUT_DOUBLE_RATE) +/* NOT CURRENTLY USED + * we slightly displace sync point from center position. this makes the + * system less susceptible to temporary field delivery irregularities. + */ +#define SYF_SYNC_POINT_OFFSET 0 + /* - * offset in usecs from double buffer switch where we try to place double + * offset in usecs from double buffer switch where we preferredly try to place double * buffer updates. * this minimizes sensivity to jitter of our software PLL phase comparator. */ -#define SYF_SYNC_POINT (SYF_FRAME_CYCLE >> 1) +#define SYF_SYNC_POINT (SYF_PAL_FIELD_CYCLE - SYF_SYNC_POINT_OFFSET) /* * one trim increment compensates drift speed for about 29usec/sec. @@ -3070,21 +3076,6 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) */ #define SYF_MAX_TRIM_ABS 2 -#define DEBUG -#ifdef DEBUG -#define ERRORF ErrorF -#else -#define ERRORF(...) -#endif - -#define USE_METER -#ifdef USE_METER -#define OUT_GRAPHIC meter_out -extern void meter_out(int, int); -#else -#define OUT_GRAPHIC(...) -#endif - #ifdef STANDALONE #define DOVSTA 0x30008 @@ -3101,58 +3092,68 @@ extern void meter_out(int, int); #define min(a, b) ((a) <= (b) ? (a) : (b)) #define max(a, b) ((a) >= (b) ? (a) : (b)) #define abs(a) ((a) >= 0 ? (a) : -(a)) + +#define VSF_SUB(a, b, c) \ + if ((a).tv_usec < (b).tv_usec) { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ + } else { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ + } + +#define VSF_TV2USEC(a, b) \ + (b) = (a).tv_sec * 1000000 + (a).tv_usec; + +struct _I830_s { + int SYF_debug; +} I830 = { + 1, +}, *pI830 = &I830; + #else + #define B(a) (a) + #endif -#define OC_FIELD (1 << 19) -#include #include +#define OC_FIELD (1 << 19) + typedef struct _syf { int cnt; - int tsum; int trim; int drift; int spoint; } syf_t; -typedef struct _drm_i945_syncf { - struct timeval tv_now; - struct timeval tv_vbl; - unsigned trim; - unsigned htotal_a; - unsigned hsync_a; -} drm_i945_syncf_t; - -#define VSF_SUB(a, b, c) \ - if ((a).tv_usec < (b).tv_usec) { \ - (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ - (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ - } else { \ - (c).tv_sec = (a).tv_sec - (b).tv_sec; \ - (c).tv_usec = (a).tv_usec - (b).tv_usec; \ - } - -#define VSF_TV2USEC(a, b) \ - (b) = (a).tv_sec * 1000000 + (a).tv_usec; +extern void log_graph(int, int); void -meter_out(val, symb) +log_graph(val, symb) { - static char meter[81]; - static char headr[81] = "|<- -20ms 0 +20ms ->|"; + static char headr[] = "|<- -20ms 0 +20ms ->|"; + static char meter[sizeof(headr)]; if (!symb || symb == 1) { if (!symb) ErrorF("%s", headr); if (symb == 1) ErrorF("%s", meter); - memset(meter, '-', 80); + memset(meter, '-', sizeof(headr) - 1); return; } - val /= 500; - val = min(val, 39); - val = max(val, -40); - meter[40 + val] = symb; + val = (SYF_SYNC_POINT + val) / 500; + val = min(val, (int)sizeof(headr) - 2); + val = max(val, 0); + if (symb == ':') { + meter[val] = meter[val] == '%' ? '#' : symb; + } else if (symb == '*') { + meter[val] = meter[val] == '%' ? '1' : + meter[val] == ':' ? '2' : + meter[val] == '#' ? '3' : symb; + } else { + meter[val] = symb; + } } /* --- 8< --- */ @@ -3160,79 +3161,84 @@ void vga_sync_fields(pI830) I830Ptr pI830; { - static syf_t syf, syf_clear; - static drm_i945_syncf_t syncf_prev; - static struct timeval skew2vbl_prev; - - drm_i945_syncf_t syncf; - struct timeval skew2vbl; - struct timeval tv_usecs; - int usecs; - int dovsta, pipea_dsl; + static int vbl_usec_prev = ~0; + static int htotal_a, hsync_a; + static syf_t syf; + int dovsta, dovsta_1, pipea_dsl, pipea_dsl_1, trim, vbl_usec; /* --- 8< --- */ - if (!syncf_prev.htotal_a) { - syncf_prev.htotal_a = INREG(HTOTAL_A); - syncf_prev.hsync_a = INREG(HSYNC_A); + if (!htotal_a) { + htotal_a = INREG(HTOTAL_A); + hsync_a = INREG(HSYNC_A); } - syncf.trim = (INREG(HTOTAL_A) >> 16) - (syncf_prev.htotal_a >> 16); - gettimeofday(&syncf.tv_now, 0); + trim = (INREG(HTOTAL_A) >> 16) - (htotal_a >> 16); /* - * DOVSTA 0x00104000 => PIPEA_DSL 0x0000011e - * DOVSTA 0x80085000 => PIPEA_DSL 0x0000011f - * [...] - * DOVSTA 0x80104000 => PIPEA_DSL 0x00000138 - * DOVSTA 0x80104000 => PIPEA_DSL 0x00000000 - * * the chip does not provide current field status directly. * but we can derive that from xor'ed dovsta and pipea_dsl contents. - * _______________ ________ - * ____| |_______________| dovsta - * ___ ___ ___ - * ____| |___________| |___________| |____ pipea_dsl - * _______________ ____ - * ________| |_______________| field status + * + * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 + * [...] + * DOVSTA 0x00104000 PIPEA_DSL 0x0000011e 286 286 18304 + * DOVSTA 0x80085000 PIPEA_DSL 0x0000011f 287 287 18368 + * [...] + * DOVSTA 0x80184000 PIPEA_DSL 0x00000138 312 312 19968 + * DOVSTA 0x80184000 PIPEA_DSL 0x00000000 0 313 20032 + * [...] + * DOVSTA 0x80184000 PIPEA_DSL 0x0000011e 286 599 38336 + * DOVSTA 0x80105000 PIPEA_DSL 0x0000011f 287 600 38400 + * [...] + * DOVSTA 0x80104000 PIPEA_DSL 0x00000138 312 625 40000 + * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 + * _______________ ________ + * ____| |_______________| !(dovsta & OC_FIELD) + * ____ ___________ ___________ ____ + * |___| |___| |___| pipea_dsl < DEADLN + * ________ _______________ + * |_______________| |____ field status * - * 0 286 312 + * 0 287 313 */ -#define FIELD_SWITCH_THRESHOLD 287 +#define LFIELD 313 +#define DEADLN 287 +#define SHIFTV (LFIELD - DEADLN) +#define LFRAME (LFIELD << 1) - /* field * 20000 + line * 64 == 39968 max. for field==1, line==312 */ + /* + * the next few lines implement a simple glitch detection/correction + */ dovsta = INREG(DOVSTA); pipea_dsl = INREG(PIPEA_DSL); - skew2vbl.tv_usec = - (pipea_dsl < FIELD_SWITCH_THRESHOLD ^ !(dovsta & OC_FIELD)) - * SYF_PAL_FIELD_CYCLE + (pipea_dsl << 6); - skew2vbl.tv_sec = 0; - VSF_SUB(syncf.tv_now, skew2vbl, syncf.tv_vbl); - VSF_SUB(syncf.tv_now, syncf_prev.tv_now, tv_usecs); - VSF_TV2USEC(tv_usecs, usecs); -#ifdef STANDALONE - if (syncf_prev.tv_now.tv_sec) { - usleepv += SYF_FRAME_CYCLE - usecs; + dovsta_1 = INREG(DOVSTA); + pipea_dsl_1 = INREG(PIPEA_DSL); + + if ((dovsta ^ dovsta_1) & OC_FIELD && pipea_dsl == pipea_dsl_1) { + dovsta = ~dovsta; } -#endif - syncf_prev.tv_now = syncf.tv_now; - if (abs(usecs - SYF_FRAME_CYCLE) > SYF_CATCH_RANGE) { - - /* - * toss stray intervals and reset - */ - syf = syf_clear; - skew2vbl_prev.tv_sec = ~0; - OUT_GRAPHIC(0, 0); - ErrorF(" R %11d\n", usecs); + dovsta &= OC_FIELD; + + /* 287 + 26 (+ 313) == 313 (626) */ + vbl_usec = (pipea_dsl < DEADLN ^ !dovsta) * LFIELD + pipea_dsl; + vbl_usec = (vbl_usec + SHIFTV) % LFRAME << 6; + + if (vbl_usec_prev == ~0) { + vbl_usec_prev = vbl_usec; + log_graph(0, 0); + ErrorF(" R\n"); #ifdef STANDALONE - goto main_loop_end; + goto main_loop_end; #else - return; + return; #endif - } - if (abs(usecs - SYF_FRAME_CYCLE) > SYF_WARN_RANGE) { - OUT_GRAPHIC(0, 0); - ErrorF(" W %11d\n", usecs); + } + if (pI830->SYF_debug) { + if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { + log_graph(vbl_usec - vbl_usec_prev, '%'); + } + if (abs(vbl_usec - SYF_PAL_FIELD_CYCLE) > SYF_WARN_RANGE) { + log_graph(vbl_usec - SYF_SYNC_POINT, ':'); + } } #ifndef STANDALONE @@ -3240,7 +3246,7 @@ vga_sync_fields(pI830) /* * we must delay the next double buffer update * until even field has been processed. this occurs - * after scan line FIELD_SWITCH_THRESHOLD has been passed. + * after scan line 286 has been passed. * on a sufficiently synchronized system running at a * sync point of about 20000 usecs this imposes * no additional sleep time. @@ -3250,40 +3256,31 @@ vga_sync_fields(pI830) * ...---sleep--->| * 18368 */ - if (skew2vbl.tv_usec < FIELD_SWITCH_THRESHOLD << 6) { - usleep((FIELD_SWITCH_THRESHOLD << 6) - skew2vbl.tv_usec); + if (vbl_usec < SYF_PAL_FIELD_CYCLE) { + usleep(SYF_PAL_FIELD_CYCLE - vbl_usec); } #endif - VSF_SUB(syncf.tv_now, syncf.tv_vbl, skew2vbl) - if (skew2vbl_prev.tv_sec != ~0) { - syf.tsum += usecs; - syf.spoint += skew2vbl.tv_usec - SYF_SYNC_POINT; - VSF_SUB(skew2vbl, skew2vbl_prev, tv_usecs); - VSF_TV2USEC(tv_usecs, usecs); - syf.drift += usecs; - ++syf.cnt; - } - if (skew2vbl_prev.tv_sec != ~0 && !(syf.cnt % SYF_PLL_DIVIDER)) { + syf.spoint += vbl_usec - SYF_SYNC_POINT; + syf.drift += vbl_usec - vbl_usec_prev; + vbl_usec_prev = vbl_usec; + ++syf.cnt; + if (!(syf.cnt % SYF_PLL_DIVIDER)) { syf.spoint /= SYF_PLL_DIVIDER; - if (pI830->SYF_debug) { - OUT_GRAPHIC(0, '+'); - OUT_GRAPHIC(syf.spoint, '|'); - OUT_GRAPHIC(syf.drift, '*'); - OUT_GRAPHIC(0, 1); - } syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); if (pI830->SYF_debug) { - ERRORF("%7d %7d [%3d%+4d] %7d\n", syf.drift, syf.spoint, - (char)(syncf.trim & 0xff), syf.trim, syf.tsum); + log_graph(0, '+'); + log_graph(syf.spoint, '|'); + log_graph(syf.drift, '*'); + log_graph(0, 1); + ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); } syf.spoint = 0; syf.drift = 0; - syf.tsum = 0; } if (B(1) && syf.trim) { - int t = (char)(syncf.trim & 0xff); + int t = (char)(trim & 0xff); if (syf.trim > 0) { t = min(t + 1, SYF_MAX_TRIM_ABS); @@ -3292,15 +3289,14 @@ vga_sync_fields(pI830) t = max(t - 1, -SYF_MAX_TRIM_ABS); ++syf.trim; } - if (syncf.trim != t) { + if (trim != t) { t <<= 16; - OUTREG(HTOTAL_A, syncf_prev.htotal_a + t); - OUTREG(HBLANK_A, syncf_prev.htotal_a + t); - OUTREG(HSYNC_A, syncf_prev.hsync_a + (t << 1)); + OUTREG(HTOTAL_A, htotal_a + t); + OUTREG(HBLANK_A, htotal_a + t); + OUTREG(HSYNC_A, hsync_a + (t << 1)); OUTREG(PIPEACONF, INREG(PIPEACONF)); } } - skew2vbl_prev = skew2vbl; /* --- 8< --- */ } -- cgit v1.2.3 From 42f17b803e31bbb94bc2a9fe34b0672eaa649697 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Sun, 24 May 2009 21:08:43 +0200 Subject: [BUG FIX] delay until field update deadline must be delayed further by SHIFTV Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_video.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 81da67ba..4a6024a8 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3216,11 +3216,9 @@ vga_sync_fields(pI830) if ((dovsta ^ dovsta_1) & OC_FIELD && pipea_dsl == pipea_dsl_1) { dovsta = ~dovsta; } - dovsta &= OC_FIELD; /* 287 + 26 (+ 313) == 313 (626) */ - vbl_usec = (pipea_dsl < DEADLN ^ !dovsta) * LFIELD + pipea_dsl; - vbl_usec = (vbl_usec + SHIFTV) % LFRAME << 6; + vbl_usec = ((pipea_dsl < DEADLN ^ !(dovsta & OC_FIELD)) * LFIELD + pipea_dsl + SHIFTV) % LFRAME << 6; if (vbl_usec_prev == ~0) { vbl_usec_prev = vbl_usec; @@ -3256,8 +3254,8 @@ vga_sync_fields(pI830) * ...---sleep--->| * 18368 */ - if (vbl_usec < SYF_PAL_FIELD_CYCLE) { - usleep(SYF_PAL_FIELD_CYCLE - vbl_usec); + if (vbl_usec - SHIFTV < SYF_PAL_FIELD_CYCLE) { + usleep(SYF_PAL_FIELD_CYCLE - (vbl_usec - SHIFTV)); } #endif syf.spoint += vbl_usec - SYF_SYNC_POINT; -- cgit v1.2.3 From 2f19cf305166b5bf6051a4294a191e7aa2c90143 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Mon, 25 May 2009 20:28:51 +0200 Subject: fast processors require additional delay of 32usecs - fast processors require additional delay of 32usecs where we wait for even field to pass - white space fixes/indentation Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_video.c | 117 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 4a6024a8..474647c7 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3095,11 +3095,11 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) #define VSF_SUB(a, b, c) \ if ((a).tv_usec < (b).tv_usec) { \ - (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ - (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ } else { \ - (c).tv_sec = (a).tv_sec - (b).tv_sec; \ - (c).tv_usec = (a).tv_usec - (b).tv_usec; \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ } #define VSF_TV2USEC(a, b) \ @@ -3137,7 +3137,7 @@ log_graph(val, symb) static char meter[sizeof(headr)]; if (!symb || symb == 1) { - if (!symb) ErrorF("%s", headr); + if (!symb) ErrorF("%s", headr); if (symb == 1) ErrorF("%s", meter); memset(meter, '-', sizeof(headr) - 1); return; @@ -3146,13 +3146,13 @@ log_graph(val, symb) val = min(val, (int)sizeof(headr) - 2); val = max(val, 0); if (symb == ':') { - meter[val] = meter[val] == '%' ? '#' : symb; + meter[val] = meter[val] == '%' ? '#' : symb; } else if (symb == '*') { - meter[val] = meter[val] == '%' ? '1' : - meter[val] == ':' ? '2' : - meter[val] == '#' ? '3' : symb; + meter[val] = meter[val] == '%' ? '1' : + meter[val] == ':' ? '2' : + meter[val] == '#' ? '3' : symb; } else { - meter[val] = symb; + meter[val] = symb; } } /* --- 8< --- */ @@ -3167,16 +3167,16 @@ vga_sync_fields(pI830) int dovsta, dovsta_1, pipea_dsl, pipea_dsl_1, trim, vbl_usec; /* --- 8< --- */ - if (!htotal_a) { + if (!htotal_a) { htotal_a = INREG(HTOTAL_A); hsync_a = INREG(HSYNC_A); - } + } trim = (INREG(HTOTAL_A) >> 16) - (htotal_a >> 16); /* * the chip does not provide current field status directly. * but we can derive that from xor'ed dovsta and pipea_dsl contents. - * + * * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 * [...] * DOVSTA 0x00104000 PIPEA_DSL 0x0000011e 286 286 18304 @@ -3202,23 +3202,24 @@ vga_sync_fields(pI830) #define LFIELD 313 #define DEADLN 287 +#define DYZONE 32 #define SHIFTV (LFIELD - DEADLN) #define LFRAME (LFIELD << 1) - /* - * the next few lines implement a simple glitch detection/correction - */ - dovsta = INREG(DOVSTA); - pipea_dsl = INREG(PIPEA_DSL); - dovsta_1 = INREG(DOVSTA); - pipea_dsl_1 = INREG(PIPEA_DSL); + /* + * the next few lines implement a simple glitch detection/correction + */ + dovsta = INREG(DOVSTA); + pipea_dsl = INREG(PIPEA_DSL); + dovsta_1 = INREG(DOVSTA); + pipea_dsl_1 = INREG(PIPEA_DSL); - if ((dovsta ^ dovsta_1) & OC_FIELD && pipea_dsl == pipea_dsl_1) { - dovsta = ~dovsta; - } + if ((dovsta ^ dovsta_1) & OC_FIELD && pipea_dsl == pipea_dsl_1) { + dovsta = ~dovsta; + } - /* 287 + 26 (+ 313) == 313 (626) */ - vbl_usec = ((pipea_dsl < DEADLN ^ !(dovsta & OC_FIELD)) * LFIELD + pipea_dsl + SHIFTV) % LFRAME << 6; + /* 287 + 26 (+ 313) == 313 (626) */ + vbl_usec = ((pipea_dsl < DEADLN ^ !(dovsta & OC_FIELD)) * LFIELD + pipea_dsl + SHIFTV) % LFRAME << 6; if (vbl_usec_prev == ~0) { vbl_usec_prev = vbl_usec; @@ -3230,14 +3231,14 @@ vga_sync_fields(pI830) return; #endif } - if (pI830->SYF_debug) { - if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { - log_graph(vbl_usec - vbl_usec_prev, '%'); - } - if (abs(vbl_usec - SYF_PAL_FIELD_CYCLE) > SYF_WARN_RANGE) { - log_graph(vbl_usec - SYF_SYNC_POINT, ':'); - } - } + if (pI830->SYF_debug) { + if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { + log_graph(vbl_usec - vbl_usec_prev, '%'); + } + if (abs(vbl_usec - SYF_PAL_FIELD_CYCLE) > SYF_WARN_RANGE) { + log_graph(vbl_usec - SYF_SYNC_POINT, ':'); + } + } #ifndef STANDALONE @@ -3254,29 +3255,29 @@ vga_sync_fields(pI830) * ...---sleep--->| * 18368 */ - if (vbl_usec - SHIFTV < SYF_PAL_FIELD_CYCLE) { - usleep(SYF_PAL_FIELD_CYCLE - (vbl_usec - SHIFTV)); + if (SYF_PAL_FIELD_CYCLE - vbl_usec > 0) { + usleep(SYF_PAL_FIELD_CYCLE - vbl_usec + DYZONE); } #endif - syf.spoint += vbl_usec - SYF_SYNC_POINT; - syf.drift += vbl_usec - vbl_usec_prev; - vbl_usec_prev = vbl_usec; - ++syf.cnt; - if (!(syf.cnt % SYF_PLL_DIVIDER)) { - syf.spoint /= SYF_PLL_DIVIDER; - syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; - syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); - syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); - if (pI830->SYF_debug) { - log_graph(0, '+'); - log_graph(syf.spoint, '|'); - log_graph(syf.drift, '*'); - log_graph(0, 1); - ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); - } - syf.spoint = 0; - syf.drift = 0; - } + syf.spoint += vbl_usec - SYF_SYNC_POINT; + syf.drift += vbl_usec - vbl_usec_prev; + vbl_usec_prev = vbl_usec; + ++syf.cnt; + if (!(syf.cnt % SYF_PLL_DIVIDER)) { + syf.spoint /= SYF_PLL_DIVIDER; + syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; + syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); + syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); + if (pI830->SYF_debug) { + log_graph(0, '+'); + log_graph(syf.spoint, '|'); + log_graph(syf.drift, '*'); + log_graph(0, 1); + ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); + } + syf.spoint = 0; + syf.drift = 0; + } if (B(1) && syf.trim) { int t = (char)(trim & 0xff); @@ -3287,14 +3288,14 @@ vga_sync_fields(pI830) t = max(t - 1, -SYF_MAX_TRIM_ABS); ++syf.trim; } - if (trim != t) { - t <<= 16; + if (trim != t) { + t <<= 16; OUTREG(HTOTAL_A, htotal_a + t); OUTREG(HBLANK_A, htotal_a + t); OUTREG(HSYNC_A, hsync_a + (t << 1)); OUTREG(PIPEACONF, INREG(PIPEACONF)); - } - } + } + } /* --- 8< --- */ } -- cgit v1.2.3 From c6322b3e8d28cb5a6987e119f27eae70a73ca72f Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Wed, 27 May 2009 06:23:20 +0200 Subject: Add new scheduling option. - new scheduling option added Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_driver.c | 16 +++++++++++++++- src/i830_video.c | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index c7244b55..7de87691 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -201,6 +201,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include #endif #include "sys/resource.h" +#include #ifdef INTEL_XVMC #define _INTEL_XVMC_SERVER_ @@ -1832,7 +1833,20 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } if (pI830->sync_fields) { if (pI830->SchedPrio != ~0) { - if (pI830->SchedPrio) { + if (pI830->SchedPrio < -20) { + struct sched_param sched; + + sched.sched_priority = -pI830->SchedPrio; + if (sched_setscheduler(0, SCHED_FIFO, &sched)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to set SCHED_FIFO priority as requested: %s\n", strerror(errno)); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "set SCHED_FIFO priority to (policy %d/ priority %d) as requested\n", + sched_getscheduler(0), + sched_getparam(0, &sched) ? ~0 : sched.sched_priority); + } + } else if (pI830->SchedPrio) { if (setpriority(PRIO_PROCESS, 0, pI830->SchedPrio)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to set scheduling priority as requested: %s\n", strerror(errno)); diff --git a/src/i830_video.c b/src/i830_video.c index 474647c7..5d14c5d7 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3235,7 +3235,7 @@ vga_sync_fields(pI830) if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { log_graph(vbl_usec - vbl_usec_prev, '%'); } - if (abs(vbl_usec - SYF_PAL_FIELD_CYCLE) > SYF_WARN_RANGE) { + if (abs(vbl_usec - SYF_SYNC_POINT) > SYF_WARN_RANGE) { log_graph(vbl_usec - SYF_SYNC_POINT, ':'); } } -- cgit v1.2.3 From 9ed612b65e5590f5d82b6822f19b6881edff0e97 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Sat, 30 May 2009 06:34:42 +0200 Subject: Improved field timing debug support. Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i810_driver.c | 2 +- src/i830.h | 2 +- src/i830_driver.c | 20 +++++++++++--------- src/i830_video.c | 27 ++++++++++++++++++++------- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/i810_driver.c b/src/i810_driver.c index eb4c547e..76582992 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -275,7 +275,7 @@ static const OptionInfoRec I810Options[] = { {OPTION_YRGB_VPHASE, "SF_YRGB_VPhase",OPTV_INTEGER, {0}, FALSE}, {OPTION_UV_VPHASE, "SF_UV_VPhase", OPTV_INTEGER, {0}, FALSE}, {OPTION_SCHED_PRIO, "SF_SchedPrio", OPTV_INTEGER, {0}, FALSE}, - {OPTION_SYF_DEBUG, "SF_Debug", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SYF_DEBUG, "SF_Debug", OPTV_INTEGER, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ diff --git a/src/i830.h b/src/i830.h index 895a5c5a..56ef3041 100644 --- a/src/i830.h +++ b/src/i830.h @@ -528,7 +528,7 @@ typedef struct _I830Rec { int YRGB_vphase; int UV_vphase; int SchedPrio; - Bool SYF_debug; + int SYF_debug; /* EXA render state */ float scale_units[2][2]; diff --git a/src/i830_driver.c b/src/i830_driver.c index 7de87691..98723aa7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -352,7 +352,7 @@ static OptionInfoRec I830Options[] = { {OPTION_YRGB_VPHASE, "SF_YRGB_VPhase",OPTV_INTEGER, {0}, FALSE}, {OPTION_UV_VPHASE, "SF_UV_VPhase", OPTV_INTEGER, {0}, FALSE}, {OPTION_SCHED_PRIO, "SF_SchedPrio", OPTV_INTEGER, {0}, FALSE}, - {OPTION_SYF_DEBUG, "SF_Debug", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SYF_DEBUG, "SF_Debug", OPTV_INTEGER, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -1721,11 +1721,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) &(pI830->SYF_debug))) { from = X_CONFIG; } else { - pI830->SYF_debug = FALSE; + pI830->SYF_debug = 0; from = X_DEFAULT; } - xf86DrvMsg(pScrn->scrnIndex, from, "sync fields debug %sactivated\n", - pI830->SYF_debug ? "" : "de"); + xf86DrvMsg(pScrn->scrnIndex, from, "sync fields debug %sactivated: %d\n", + pI830->SYF_debug ? "" : "de", pI830->SYF_debug); } /* --- SYNC FIELDS setup --- */ @@ -1831,9 +1831,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields with current timing, disabled\n"); pI830->sync_fields = 0; } + +#define MAX_SCHEDPRIO_1CORE -20 + if (pI830->sync_fields) { if (pI830->SchedPrio != ~0) { - if (pI830->SchedPrio < -20) { + if (pI830->SchedPrio < MAX_SCHEDPRIO_1CORE) { struct sched_param sched; sched.sched_priority = -pI830->SchedPrio; @@ -1865,15 +1868,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (f = fopen("/proc/cpuinfo", "r")) { char buf[256]; while (fgets(buf, 255, f)) { +#if 0 /* do not change the default priority at the moment */ sscanf(buf, "processor : %d", &cores); +#endif } fclose(f); } - -#define DFLT_SCHEDPRIO_1CORE -20 - if (!cores) { - if (setpriority(PRIO_PROCESS, 0, DFLT_SCHEDPRIO_1CORE)) { + if (setpriority(PRIO_PROCESS, 0, MAX_SCHEDPRIO_1CORE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to set scheduling priority (single core system): %s\n", strerror(errno)); } else { diff --git a/src/i830_video.c b/src/i830_video.c index 5d14c5d7..deb16169 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3117,6 +3117,7 @@ struct _I830_s { #endif +#include #include #define OC_FIELD (1 << 19) @@ -3124,6 +3125,7 @@ struct _I830_s { typedef struct _syf { int cnt; int trim; + int warn; int drift; int spoint; } syf_t; @@ -3233,10 +3235,10 @@ vga_sync_fields(pI830) } if (pI830->SYF_debug) { if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { - log_graph(vbl_usec - vbl_usec_prev, '%'); + log_graph(vbl_usec - vbl_usec_prev, '%'); ++syf.warn; } if (abs(vbl_usec - SYF_SYNC_POINT) > SYF_WARN_RANGE) { - log_graph(vbl_usec - SYF_SYNC_POINT, ':'); + log_graph(vbl_usec - SYF_SYNC_POINT, ':'); ++syf.warn; } } @@ -3269,14 +3271,25 @@ vga_sync_fields(pI830) syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); if (pI830->SYF_debug) { - log_graph(0, '+'); - log_graph(syf.spoint, '|'); - log_graph(syf.drift, '*'); - log_graph(0, 1); - ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); + if (pI830->SYF_debug < 5 && syf.warn) { + time_t t; + struct tm *tm; + + time(&t); + tm = localtime(&t); + ErrorF("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); + } + if (pI830->SYF_debug < 5 && syf.warn || pI830->SYF_debug >= 5) { + log_graph(0, '+'); + log_graph(syf.spoint, '|'); + log_graph(syf.drift, '*'); + log_graph(0, 1); + ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); + } } syf.spoint = 0; syf.drift = 0; + syf.warn = 0; } if (B(1) && syf.trim) { int t = (char)(trim & 0xff); -- cgit v1.2.3 From 7639a29d6813f9cc80075f523058e44ee2366817 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Mon, 1 Jun 2009 17:09:21 +0200 Subject: Some cosmetics and option to configure field/frame timing log output. - field/frame timing log output now configurable per SF_Debug Xserver option - odd numbers will output a status line every second - even numbers will only spawn a line if a given value is exceeded either drift or by sync point or by both Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_video.c | 58 ++++++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index deb16169..dc637d83 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3018,12 +3018,6 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) */ #define SYF_CATCH_RANGE (SYF_PAL_FRAME_CYCLE - 500 >> SYF_INPUT_DOUBLE_RATE) -/* - * updates outside time window defined by this - * value spawn warnings when in debug mode - */ -#define SYF_WARN_RANGE (5000 >> SYF_INPUT_DOUBLE_RATE) - /* * we average 25 (50) frames to yield a cycle time of * about one second for analysis of frame rate data. @@ -3123,9 +3117,9 @@ struct _I830_s { #define OC_FIELD (1 << 19) typedef struct _syf { + int log; int cnt; int trim; - int warn; int drift; int spoint; } syf_t; @@ -3139,8 +3133,10 @@ log_graph(val, symb) static char meter[sizeof(headr)]; if (!symb || symb == 1) { - if (!symb) ErrorF("%s", headr); - if (symb == 1) ErrorF("%s", meter); + time_t t; struct tm *tm; + + time(&t); tm = localtime(&t); + ErrorF("%02d:%02d:%02d %s", tm->tm_hour, tm->tm_min, tm->tm_sec, symb ? meter : headr); memset(meter, '-', sizeof(headr) - 1); return; } @@ -3233,14 +3229,14 @@ vga_sync_fields(pI830) return; #endif } - if (pI830->SYF_debug) { - if (abs(vbl_usec - vbl_usec_prev) > SYF_WARN_RANGE) { - log_graph(vbl_usec - vbl_usec_prev, '%'); ++syf.warn; - } - if (abs(vbl_usec - SYF_SYNC_POINT) > SYF_WARN_RANGE) { - log_graph(vbl_usec - SYF_SYNC_POINT, ':'); ++syf.warn; - } - } + if (pI830->SYF_debug) { + if (abs(vbl_usec - vbl_usec_prev) > pI830->SYF_debug) { + log_graph(vbl_usec - vbl_usec_prev, '%'); ++syf.log; + } + if (abs(vbl_usec - SYF_SYNC_POINT) > pI830->SYF_debug) { + log_graph(vbl_usec - SYF_SYNC_POINT, ':'); ++syf.log; + } + } #ifndef STANDALONE @@ -3270,26 +3266,18 @@ vga_sync_fields(pI830) syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL); syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); - if (pI830->SYF_debug) { - if (pI830->SYF_debug < 5 && syf.warn) { - time_t t; - struct tm *tm; - - time(&t); - tm = localtime(&t); - ErrorF("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); - } - if (pI830->SYF_debug < 5 && syf.warn || pI830->SYF_debug >= 5) { - log_graph(0, '+'); - log_graph(syf.spoint, '|'); - log_graph(syf.drift, '*'); - log_graph(0, 1); - ErrorF("%7d %7d [%3d%+4d]\n", syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); - } - } + + if (pI830->SYF_debug & 1 || syf.log) { + log_graph(0, '+'); + log_graph(syf.spoint, '|'); + log_graph(syf.drift, '*'); + log_graph(0, 1); + ErrorF("%7d %7d [%3d%+4d]\n", + syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); + } syf.spoint = 0; syf.drift = 0; - syf.warn = 0; + syf.log = 0; } if (B(1) && syf.trim) { int t = (char)(trim & 0xff); -- cgit v1.2.3 From 9238ea9f919feda110af1725c3020d6199daac34 Mon Sep 17 00:00:00 2001 From: Thomas Hilber Date: Thu, 4 Jun 2009 21:28:56 +0200 Subject: Support for HDMI 1600x1200 50Hz interlaced resolution. - now supports HDMI 1600x1200 50Hz interlaced resolution - adjustment control now operates at lower speed which is still fairly sufficient Signed-off-by: Thomas Hilber Signed-off-by: Paul Menzel --- src/i830_driver.c | 13 +++--- src/i830_sdvo.c | 8 ++++ src/i830_video.c | 126 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 95 insertions(+), 52 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 98723aa7..f19eb4f4 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1821,13 +1821,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } /* - * sync_fields only works with - * ModeLine "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace + * sync_fields currently only works with these modelines + * ModeLine "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace + * Modeline "1600x1200_50i" 65.92 1600 1696 1864 2131 1200 1203 1207 1238 -hsync +vsync interlace */ - if ((pScrn->currentMode->Clock != 27750 - || pScrn->currentMode->HDisplay != 1440 - || pScrn->currentMode->VDisplay != 576) - && pI830->sync_fields) { + if (pI830->sync_fields && + ((pScrn->currentMode->Clock != 27750 || pScrn->currentMode->HDisplay != 1440 || pScrn->currentMode->VDisplay != 576) && + (pScrn->currentMode->Clock != 65920 || pScrn->currentMode->HDisplay != 1600 || pScrn->currentMode->VDisplay != 1200) + ) ) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields with current timing, disabled\n"); pI830->sync_fields = 0; } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 0dc6dca3..083f46af 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1096,7 +1096,15 @@ i830_sdvo_detect(xf86OutputPtr output) if (response[0] != 0 || response[1] != 0) return XF86OutputStatusConnected; else + + /* + * allow Xserver to run even without a CRT connected + */ +#if 0 return XF86OutputStatusDisconnected; +#else + return XF86OutputStatusConnected; +#endif } static DisplayModePtr diff --git a/src/i830_video.c b/src/i830_video.c index dc637d83..4ed4e9b0 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3055,12 +3055,12 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) */ #define SYF_DISP_DRIFT_FACTOR 1 -/* NOT CURRENTLY USED +/* * to allow for smooth adaption also on slower devices we delimit maximum * trim change per step size. * this implements some kind of low pass filter for our VCO input. */ -#define SYF_MAX_TRIM_REL 1000 +#define SYF_MAX_TRIM_REL 1 /* * maximum absolute trim values allowed due to current @@ -3102,7 +3102,7 @@ i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) struct _I830_s { int SYF_debug; } I830 = { - 1, + 801, }, *pI830 = &I830; #else @@ -3116,12 +3116,20 @@ struct _I830_s { #define OC_FIELD (1 << 19) -typedef struct _syf { +typedef struct _syf_t { int log; int cnt; int trim; int drift; int spoint; + + /* HW specific */ + int lfield; + int deadln; + int dyzone; + int tshift; + int hsync_a; + int htotal_a; } syf_t; extern void log_graph(int, int); @@ -3133,10 +3141,10 @@ log_graph(val, symb) static char meter[sizeof(headr)]; if (!symb || symb == 1) { - time_t t; struct tm *tm; + time_t t; struct tm *tm; - time(&t); tm = localtime(&t); - ErrorF("%02d:%02d:%02d %s", tm->tm_hour, tm->tm_min, tm->tm_sec, symb ? meter : headr); + time(&t); tm = localtime(&t); + ErrorF("%02d:%02d:%02d %s", tm->tm_hour, tm->tm_min, tm->tm_sec, symb ? meter : headr); memset(meter, '-', sizeof(headr) - 1); return; } @@ -3159,21 +3167,43 @@ void vga_sync_fields(pI830) I830Ptr pI830; { - static int vbl_usec_prev = ~0; - static int htotal_a, hsync_a; static syf_t syf; + static int vbl_usec_prev = ~0; int dovsta, dovsta_1, pipea_dsl, pipea_dsl_1, trim, vbl_usec; /* --- 8< --- */ - if (!htotal_a) { - htotal_a = INREG(HTOTAL_A); - hsync_a = INREG(HSYNC_A); + if (!syf.htotal_a) { + syf.htotal_a = INREG(HTOTAL_A); + syf.hsync_a = INREG(HSYNC_A); + switch (syf.htotal_a & 0x0000ffff) { + case 1439: + syf.lfield = 313; + syf.deadln = 287; + syf.dyzone = 32; + syf.tshift = 6; + break; + case 1599: + syf.lfield = 619; + syf.deadln = 599; + syf.dyzone = 0; + syf.tshift = 5; + break; + } } - trim = (INREG(HTOTAL_A) >> 16) - (htotal_a >> 16); + trim = (INREG(HTOTAL_A) >> 16) - (syf.htotal_a >> 16); /* * the chip does not provide current field status directly. * but we can derive that from xor'ed dovsta and pipea_dsl contents. + * _______________ ________ + * ____| |_______________| !(dovsta & OC_FIELD) + * ____ ___________ ___________ ____ + * |___| |___| |___| pipea_dsl < DEADLN + * ________ 287 _______________ + * |_______________| |____ field status + * 0 313 + * + * "1440x576_50i" 27.75 1440 1488 1609 1769 576 580 585 625 -hsync -vsync interlace * * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 * [...] @@ -3188,21 +3218,26 @@ vga_sync_fields(pI830) * [...] * DOVSTA 0x80104000 PIPEA_DSL 0x00000138 312 625 40000 * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 - * _______________ ________ - * ____| |_______________| !(dovsta & OC_FIELD) - * ____ ___________ ___________ ____ - * |___| |___| |___| pipea_dsl < DEADLN - * ________ _______________ - * |_______________| |____ field status * - * 0 287 313 + * "1600x1200_50i" 65.92 1600 1696 1864 2131 1200 1203 1207 1238 -hsync +vsync interlace + * + * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 + * [...] + * DOVSTA 0x80100000 PIPEA_DSL 0x00000256 598 598 19136 + * DOVSTA 0x80185000 PIPEA_DSL 0x00000257 599 599 19168 + * [...] + * DOVSTA 0x80184000 PIPEA_DSL 0x0000026a 618 618 19776 + * DOVSTA 0x80180000 PIPEA_DSL 0x00000000 0 619 19808 + * [...] + * DOVSTA 0x80184000 PIPEA_DSL 0x00000256 598 1217 38944 + * DOVSTA 0x80105000 PIPEA_DSL 0x00000257 599 1218 38976 + * [...] + * DOVSTA 0x80100000 PIPEA_DSL 0x0000026a 618 1237 39584 + * DOVSTA 0x80104000 PIPEA_DSL 0x00000000 0 0 0 */ -#define LFIELD 313 -#define DEADLN 287 -#define DYZONE 32 -#define SHIFTV (LFIELD - DEADLN) -#define LFRAME (LFIELD << 1) +#define SHIFTV (syf.lfield - syf.deadln) +#define LFRAME (syf.lfield << 1) /* * the next few lines implement a simple glitch detection/correction @@ -3211,13 +3246,12 @@ vga_sync_fields(pI830) pipea_dsl = INREG(PIPEA_DSL); dovsta_1 = INREG(DOVSTA); pipea_dsl_1 = INREG(PIPEA_DSL); - if ((dovsta ^ dovsta_1) & OC_FIELD && pipea_dsl == pipea_dsl_1) { dovsta = ~dovsta; } /* 287 + 26 (+ 313) == 313 (626) */ - vbl_usec = ((pipea_dsl < DEADLN ^ !(dovsta & OC_FIELD)) * LFIELD + pipea_dsl + SHIFTV) % LFRAME << 6; + vbl_usec = ((pipea_dsl < syf.deadln ^ !(dovsta & OC_FIELD)) * syf.lfield + pipea_dsl + SHIFTV) % LFRAME << syf.tshift; if (vbl_usec_prev == ~0) { vbl_usec_prev = vbl_usec; @@ -3229,14 +3263,14 @@ vga_sync_fields(pI830) return; #endif } - if (pI830->SYF_debug) { - if (abs(vbl_usec - vbl_usec_prev) > pI830->SYF_debug) { - log_graph(vbl_usec - vbl_usec_prev, '%'); ++syf.log; - } - if (abs(vbl_usec - SYF_SYNC_POINT) > pI830->SYF_debug) { - log_graph(vbl_usec - SYF_SYNC_POINT, ':'); ++syf.log; - } - } + if (pI830->SYF_debug) { + if (abs(vbl_usec - vbl_usec_prev) > pI830->SYF_debug) { + log_graph(vbl_usec - vbl_usec_prev, '%'); ++syf.log; + } + if (abs(vbl_usec - SYF_SYNC_POINT) > pI830->SYF_debug) { + log_graph(vbl_usec - SYF_SYNC_POINT, ':'); ++syf.log; + } + } #ifndef STANDALONE @@ -3254,7 +3288,7 @@ vga_sync_fields(pI830) * 18368 */ if (SYF_PAL_FIELD_CYCLE - vbl_usec > 0) { - usleep(SYF_PAL_FIELD_CYCLE - vbl_usec + DYZONE); + usleep(SYF_PAL_FIELD_CYCLE - vbl_usec + syf.dyzone); } #endif syf.spoint += vbl_usec - SYF_SYNC_POINT; @@ -3268,13 +3302,13 @@ vga_sync_fields(pI830) syf.trim = min(syf.trim, SYF_MAX_TRIM_REL); if (pI830->SYF_debug & 1 || syf.log) { - log_graph(0, '+'); - log_graph(syf.spoint, '|'); - log_graph(syf.drift, '*'); - log_graph(0, 1); - ErrorF("%7d %7d [%3d%+4d]\n", - syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); - } + log_graph(0, '+'); + log_graph(syf.spoint, '|'); + log_graph(syf.drift, '*'); + log_graph(0, 1); + ErrorF("%7d %7d [%3d%+4d]\n", + syf.drift, syf.spoint, (char)(trim & 0xff), syf.trim); + } syf.spoint = 0; syf.drift = 0; syf.log = 0; @@ -3291,9 +3325,9 @@ vga_sync_fields(pI830) } if (trim != t) { t <<= 16; - OUTREG(HTOTAL_A, htotal_a + t); - OUTREG(HBLANK_A, htotal_a + t); - OUTREG(HSYNC_A, hsync_a + (t << 1)); + OUTREG(HTOTAL_A, syf.htotal_a + t); + OUTREG(HBLANK_A, syf.htotal_a + t); + OUTREG(HSYNC_A, syf.hsync_a + (t << 1)); OUTREG(PIPEACONF, INREG(PIPEACONF)); } } -- cgit v1.2.3