From 4d98e9c6a6e357ed736cd312a957c1e0a7b1d36b Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 4 Feb 2009 01:56:20 +0100 Subject: Dynamically switch virtual refresh mode. Probably this makes dualhead mode more useful because it makes possible displaying video on the LCD as long as the CRT output is disabled or cloned. --- src/smi_video.c | 12 +++--- src/smilynx_crtc.c | 112 ++++++++++++++++++++++++++++++++------------------- src/smilynx_hw.c | 8 +--- src/smilynx_output.c | 36 ++++++++--------- 4 files changed, 97 insertions(+), 71 deletions(-) diff --git a/src/smi_video.c b/src/smi_video.c index 3ae30f4..9bf0e1b 100644 --- a/src/smi_video.c +++ b/src/smi_video.c @@ -1057,10 +1057,10 @@ SMI_PutVideo( dstBox.x2 = drw_x + drw_w; dstBox.y2 = drw_y + drw_h; - if(!xf86_crtc_clip_video_helper(pScrn, &crtc, NULL, &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) + if(!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) LEAVE(Success); - if(pSmi->Dualhead && crtc == crtcConf->crtc[0]) + if(pSmi->Dualhead && crtc == crtcConf->crtc[1]) LEAVE(Success); /* Transform dstBox to the CRTC coordinates */ @@ -1516,7 +1516,7 @@ SMI_PutImage( LEAVE(Success); } else { - if (!xf86_crtc_clip_video_helper(pScrn, &crtc, NULL, &dstBox, + if (!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) LEAVE(Success); @@ -1629,7 +1629,7 @@ SMI_PutImage( drw_w, drw_h); } else{ - if(!pSmi->Dualhead || crtc == crtcConf->crtc[1]) + if(crtc == crtcConf->crtc[0]) SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); } @@ -2461,7 +2461,7 @@ SMI_DisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, NULL, &dstBox, + if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, surface->width, surface->height)) LEAVE(Success); @@ -2485,7 +2485,7 @@ SMI_DisplaySurface( surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h); else{ - if(!pSmi->Dualhead || crtc == crtcConf->crtc[1]) + if(crtc == crtcConf->crtc[0]) SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], surface->width, surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h); diff --git a/src/smilynx_crtc.c b/src/smilynx_crtc.c index e5963ff..72e0db2 100644 --- a/src/smilynx_crtc.c +++ b/src/smilynx_crtc.c @@ -194,7 +194,7 @@ SMILynx_CrtcAdjustFrame(xf86CrtcPtr crtc, int x, int y) WRITE_VPR(pSmi, 0x0C, Base); WRITE_FPR(pSmi, FPR0C, Base); }else{ - if(pSmi->Dualhead && crtc == crtcConf->crtc[0]){ + if(pSmi->Dualhead && crtc == crtcConf->crtc[1]){ /* LCD */ /* FIFO1 read start address */ @@ -857,6 +857,7 @@ SMILynx_CrtcDPMS_crt(xf86CrtcPtr crtc, int mode) ScrnInfoPtr pScrn = crtc->scrn; SMIPtr pSmi = SMIPTR(pScrn); SMIRegPtr reg = pSmi->mode; + vgaHWPtr hwp = VGAHWPTR(pScrn); ENTER(); @@ -867,6 +868,39 @@ SMILynx_CrtcDPMS_crt(xf86CrtcPtr crtc, int mode) VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, reg->SR21); + /* Wait for vertical retrace */ + while (hwp->readST01(hwp) & 0x8) ; + while (!(hwp->readST01(hwp) & 0x8)) ; + + if(mode == DPMSModeOn){ + /* Reload the LUT */ + SMILynx_CrtcLoadLUT_crt(crtc); + } + + LEAVE(); +} + +static void +SMILynx_CrtcDPMS_lcd(xf86CrtcPtr crtc, int mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + SMIPtr pSmi = SMIPTR(pScrn); + SMIRegPtr reg = pSmi->mode; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + ENTER(); + + if(mode == DPMSModeOff) + reg->SR31 &= ~0x80; /* Disable Virtual Refresh */ + else + reg->SR31 |= 0x80; /* Enable Virtual Refresh */ + + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, reg->SR31); + + /* Wait for vertical retrace */ + while (hwp->readST01(hwp) & 0x8) ; + while (!(hwp->readST01(hwp) & 0x8)) ; + LEAVE(); } @@ -912,56 +946,52 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn) LEAVE(FALSE); crtc->driver_private = crtcPriv; }else{ - if(pSmi->Dualhead){ - /* CRTC is LCD*/ - SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); - crtcFuncs->mode_set = SMILynx_CrtcModeSet_lcd; - crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; - crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; - crtcPriv->video_init = SMILynx_CrtcVideoInit_lcd; - crtcPriv->load_lut = SMILynx_CrtcLoadLUT_lcd; - - if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) - LEAVE(FALSE); - crtc->driver_private = crtcPriv; + /* CRTC0 can drive both outputs when virtual refresh is + disabled, and only the VGA output with virtual refresh + enabled. */ + SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); - /* CRTC1 is CRT */ - SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); + if(pSmi->useBIOS){ + crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; + }else{ crtcFuncs->dpms = SMILynx_CrtcDPMS_crt; - crtcFuncs->mode_set = SMILynx_CrtcModeSet_crt; - crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; - crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; - crtcPriv->video_init = SMILynx_CrtcVideoInit_crt; - crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; - if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) - LEAVE(FALSE); - crtc->driver_private = crtcPriv; + if(pSmi->Dualhead){ + /* The standard VGA CRTC registers get locked in + virtual refresh mode. */ + crtcFuncs->mode_set = SMILynx_CrtcModeSet_crt; - }else{ - /* CRTC0 is LCD, but in standard refresh mode - it is controlled through the primary VGA registers */ - SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); - - if(pSmi->useBIOS){ - crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; }else{ - crtcFuncs->dpms = SMILynx_CrtcDPMS_crt; crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; } + } + + crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; + crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; + crtcPriv->video_init = SMILynx_CrtcVideoInit_crt; + crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; + + if(pSmi->HwCursor){ + crtcFuncs->set_cursor_colors = SMILynx_CrtcSetCursorColors_crt; + crtcFuncs->set_cursor_position = SMILynx_CrtcSetCursorPosition_crt; + crtcFuncs->show_cursor = SMILynx_CrtcShowCursor_crt; + crtcFuncs->hide_cursor = SMILynx_CrtcHideCursor_crt; + crtcFuncs->load_cursor_image = SMILynx_CrtcLoadCursorImage_crt; + } + if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) + LEAVE(FALSE); + crtc->driver_private = crtcPriv; + + if(pSmi->Dualhead){ + /* CRTC1 drives LCD when enabled. */ + SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); + crtcFuncs->mode_set = SMILynx_CrtcModeSet_lcd; crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; + crtcFuncs->dpms = SMILynx_CrtcDPMS_lcd; crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; - crtcPriv->video_init = SMILynx_CrtcVideoInit_crt; - crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; - - if(pSmi->HwCursor){ - crtcFuncs->set_cursor_colors = SMILynx_CrtcSetCursorColors_crt; - crtcFuncs->set_cursor_position = SMILynx_CrtcSetCursorPosition_crt; - crtcFuncs->show_cursor = SMILynx_CrtcShowCursor_crt; - crtcFuncs->hide_cursor = SMILynx_CrtcHideCursor_crt; - crtcFuncs->load_cursor_image = SMILynx_CrtcLoadCursorImage_crt; - } + crtcPriv->video_init = SMILynx_CrtcVideoInit_lcd; + crtcPriv->load_lut = SMILynx_CrtcLoadLUT_lcd; if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) LEAVE(FALSE); diff --git a/src/smilynx_hw.c b/src/smilynx_hw.c index 8d2c523..158e20f 100644 --- a/src/smilynx_hw.c +++ b/src/smilynx_hw.c @@ -87,12 +87,8 @@ SMILynx_HWInit(ScrnInfoPtr pScrn) /* Select no displays */ mode->SR31 &= ~0x07; - /* Enable virtual refresh */ - if(pSmi->Dualhead){ - mode->SR31 |= 0x80; - }else{ - mode->SR31 &= ~0x80; - } + /* Disable virtual refresh */ + mode->SR31 &= ~0x80; /* Disable expansion */ mode->SR32 &= ~0x03; diff --git a/src/smilynx_output.c b/src/smilynx_output.c index aba6db5..fefa8c5 100644 --- a/src/smilynx_output.c +++ b/src/smilynx_output.c @@ -82,17 +82,25 @@ SMILynx_OutputDPMS_lcd(xf86OutputPtr output, int mode) ScrnInfoPtr pScrn = output->scrn; SMIPtr pSmi = SMIPTR(pScrn); SMIRegPtr reg = pSmi->mode; + xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); ENTER(); switch (mode) { case DPMSModeOn: - if(pSmi->lcd == 2 /* LCD is DSTN */ - || pSmi->Dualhead /* Virtual Refresh is enabled */) + if(pSmi->Dualhead && + output->crtc == crtcConf->crtc[1]){ + /* Virtual Refresh is enabled */ + reg->SR21 &= ~0x10; /* Enable LCD framebuffer read operation and DSTN dithering engine */ - if(pSmi->lcd == 2 /* LCD is DSTN */ - && !pSmi->Dualhead /* Virtual Refresh is disabled */) - reg->SR21 &= ~0x20; /* Enable LCD framebuffer write operation */ + }else{ + if(pSmi->lcd == 2){ + /* LCD is DSTN */ + + reg->SR21 &= ~0x10; /* Enable LCD framebuffer read operation and DSTN dithering engine */ + reg->SR21 &= ~0x20; /* Enable LCD framebuffer write operation */ + } + } reg->SR31 |= 0x01; /* Enable LCD display*/ break; @@ -269,13 +277,10 @@ SMILynx_OutputPreInit(ScrnInfoPtr pScrn) output->interlaceAllowed = FALSE; output->doubleScanAllowed = FALSE; - output->possible_crtcs = 1 << 0; - if(pSmi->Dualhead) - output->possible_clones = 0; - else - output->possible_clones = 1 << 1; + output->possible_crtcs = (1 << 0) | (1 << 1); + output->possible_clones = 1 << 1; - if(!pSmi->useBIOS){ + if(pSmi->Dualhead){ /* Output 1 is CRT */ SMI_OutputFuncsInit_base(&outputFuncs); outputFuncs->dpms = SMILynx_OutputDPMS_crt; @@ -288,13 +293,8 @@ SMILynx_OutputPreInit(ScrnInfoPtr pScrn) output->interlaceAllowed = FALSE; output->doubleScanAllowed = FALSE; - if(pSmi->Dualhead){ - output->possible_crtcs = 1 << 1; - output->possible_clones = 0; - }else{ - output->possible_crtcs = 1 << 0; - output->possible_clones = 1 << 0; - } + output->possible_crtcs = 1 << 0; + output->possible_clones = 1 << 0; } } -- cgit v1.2.3