diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2007-06-22 17:09:28 -0600 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2007-07-06 17:00:26 -0600 |
commit | 54ac7918b53a999a25185ff140cda001255596b3 (patch) | |
tree | 52eb1faf0615dc7b957c1131b90b1623cf43de81 | |
parent | ea11d99bc29086a8fa92c01dd22f195d626b33d2 (diff) |
Multiple fixes for the LX driver
* Fix VGA detection
* Restrict EXA implementations older then 2.0
* Fix crash when VT is switched while rotated
* Turn the shadow framebuffer into a true exa offscreen component
* Shut off video when we are rotated
Conflicts:
src/amd_lx_driver.c
src/amd_lx_rotate.c
-rw-r--r-- | src/amd.h | 4 | ||||
-rw-r--r-- | src/amd_lx_driver.c | 138 | ||||
-rw-r--r-- | src/amd_lx_exa.c | 2 | ||||
-rw-r--r-- | src/amd_lx_rotate.c | 110 | ||||
-rw-r--r-- | src/amd_lx_video.c | 67 |
5 files changed, 192 insertions, 129 deletions
@@ -258,7 +258,9 @@ typedef struct _geodeRec Bool tryHWCursor; unsigned int shadowSize; unsigned int shadowOffset; - + + ExaOffscreenArea *shadowArea; + DisplayModePtr curMode; VG_COMPRESSION_DATA CBData; diff --git a/src/amd_lx_driver.c b/src/amd_lx_driver.c index 5c38f71..e10e3c8 100644 --- a/src/amd_lx_driver.c +++ b/src/amd_lx_driver.c @@ -65,7 +65,6 @@ #include "cim_defs.h" #include "cim_regs.h" #include "amd.h" -#include "shadow.h" /* Bring in VGA functions */ #include "amd_lx_vga.c" @@ -316,27 +315,6 @@ LXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate) } } - pGeode->shadowSize = 0; - - if (rotate != RR_Rotate_0) { - if (rotate & (RR_Rotate_90 | RR_Rotate_270)) - size = pGeode->displayPitch * pScrni->virtualX; - else - size = pGeode->displayPitch * pScrni->virtualY; - - if (size <= fbavail) { - pGeode->shadowOffset = fboffset; - pGeode->shadowSize = size; - - fboffset += size; - fbavail -= size; - } else { - xf86DrvMsg(pScrni->scrnIndex, X_ERROR, - "Not enough memory for the shadow framebuffer\n"); - ret = FALSE; - } - } - /* Adjust the available EXA offscreen space to account for the buffer */ if (!pGeode->NoAccel && pGeode->pExa) { @@ -449,9 +427,6 @@ LXMapMem(ScrnInfoPtr pScrni) !cim_vip_ptr) return FALSE; - /* FIXME: Temporary */ - WRITE_GP32(GP3_BLT_STATUS, 0x690000); - gp_set_frame_buffer_base(pci->memBase[0], pGeode->FBAvail); gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize); @@ -475,20 +450,17 @@ LXMapMem(ScrnInfoPtr pScrni) static Bool LXCheckVGA(ScrnInfoPtr pScrni) { - char bfr[19]; - + unsigned char *ptr; const char *vgasig = "IBM VGA Compatible"; - vgaHWPtr pvgaHW = VGAHWPTR(pScrni); int ret; - if (!vgaHWMapMem(pScrni)) - return FALSE; + ptr = xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E, strlen(vgasig)); - ret = memcmp(pvgaHW->Base + 0x1E, vgasig, strlen(vgasig)); - memcpy(bfr, pvgaHW->Base + 0x1E, 18); - vgaHWUnmapMem(pScrni); + if (ptr == NULL) + return FALSE; - bfr[18] = 0; + ret = memcmp(ptr, vgasig, strlen(vgasig)); + xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig)); return ret ? FALSE : TRUE; } @@ -513,10 +485,8 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) pGeode->VGAActive = FALSE; if (xf86LoadSubModule(pScrni, "vgahw")) { - if (vgaHWGetHWRec(pScrni)) { - + if (vgaHWGetHWRec(pScrni)) pGeode->useVGA = LXCheckVGA(pScrni); - } } if (pGeode->useVGA) @@ -583,10 +553,20 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) pGeode->tryHWCursor = TRUE; pGeode->tryCompression = TRUE; + /* Protect against old versions of EXA */ + +#if (EXA_VERSION_MAJOR < 2) + pGeode->NoAccel = TRUE; + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "*** This driver was compiled with EXA version %d\n"); + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "*** we need version 2 or greater\n"); + xf86DrvMsg(pScrni->scrnIndex, X_ERROR, + "*** All accelerations are being turned off.\n"); +#else pGeode->NoAccel = FALSE; +#endif - pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS; - pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS; pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ; xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, @@ -695,7 +675,6 @@ LXPreInit(ScrnInfoPtr pScrni, int flags) pGeode->FBAvail = value << 20; } - pScrni->fbOffset = 0; if (pGeode->pEnt->device->videoRam == 0) @@ -807,13 +786,14 @@ static Bool LXUnmapMem(ScrnInfoPtr pScrni) { GeodeRec *pGeode = GEODEPTR(pScrni); - + xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE); xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE); xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE); xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE); xf86UnMapVidMem(pScrni->scrnIndex, cim_fb_ptr, pGeode->FBAvail); + xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000); return TRUE; } @@ -991,7 +971,8 @@ LXLeaveGraphics(ScrnInfoPtr pScrni) vg_set_cursor_position(pGeode->FBCursor.cursor_x, pGeode->FBCursor.cursor_y, &panning); - + LXRestore(pScrni); + if (pGeode->useVGA && pGeode->VGAActive) { pGeode->vesa->pInt->num = 0x10; pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; @@ -1000,7 +981,7 @@ LXLeaveGraphics(ScrnInfoPtr pScrni) vg_delay_milliseconds(3); } - LXRestore(pScrni); + lx_enable_dac_power(pScrni, 1); pScrni->vtSema = FALSE; } @@ -1040,8 +1021,7 @@ LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) int bpp; GeodeRec *pGeode = GEODEPTR(pScrni); - if (!LXMapMem(pScrni)) - return FALSE; + pGeode->curMode = NULL; pGeode->VGAActive = gu3_get_vga_active(); @@ -1058,7 +1038,7 @@ LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) pGeode->FBDisplayOffset = vg_get_display_offset(); - if (pGeode->useVGA) { + if (pGeode->useVGA && pGeode->VGAActive) { vgaHWPtr pvgaHW = VGAHWPTR(pScrni); pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); } @@ -1074,11 +1054,7 @@ LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) if (pGeode->useVGA) { unsigned short sequencer; vgaHWPtr pvgaHW = VGAHWPTR(pScrni); - - /* Map VGA aperture */ - if (!vgaHWMapMem(pScrni)) - return FALSE; - + /* Unlock VGA registers */ vgaHWUnlock(pvgaHW); @@ -1111,10 +1087,10 @@ LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) /* Clear the framebuffer */ memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize); - - /* Set up the video mode */ + /* Set the video mode */ LXSetVideoMode(pScrni, pScrni->currentMode); + pGeode->curMode = pScrni->currentMode; pScrni->vtSema = TRUE; @@ -1139,16 +1115,42 @@ LXLoadPalette(ScrnInfoPtr pScrni, #ifdef DPMSExtension +#include <stdio.h> +#include <unistd.h> + +#define DCON_SLEEP_FILE "/sys/devices/platform/dcon/sleep" + +/* Set up the OLPC DCON to sleep if so requested */ + +static void DCONSleep(int state) +{ + char val = (state) ? '1' : '0'; + FILE *stream = fopen(DCON_SLEEP_FILE, "w"); + if (stream == NULL) { + ErrorF("Couldn't open the DCON sleep file"); + return; + } + + fprintf(stream, "%c\n", val); + fclose(stream); +} + static void LXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags) { - GeodeRec *pGeode; - - pGeode = GEODEPTR(pScrni); + GeodeRec *pGeode = GEODEPTR(pScrni); - if (!pScrni->vtSema) + if (!pScrni->vtSema) return; + /* For now - we use the presence of the DCON sleep file as a positive + indicator that the DCON is attached. This should be transitioned to + the device tree. + */ + + if (dconAvail == -1) + dconAvail = (!access(DCON_SLEEP_FILE, R_OK | W_OK)) ? 1 : 0; + switch (mode) { case DPMSModeOn: lx_enable_dac_power(pScrni, 1); @@ -1245,6 +1247,11 @@ LXScreenInit(int scrnIndex, ScreenPtr pScrn, int argc, char **argv) } } + /* Map the memory here before doing anything else */ + + if (!LXMapMem(pScrni)) + return FALSE; + /* XXX FIXME - Take down any of the structures on failure? */ if (!LXEnterGraphics(pScrn, pScrni)) return FALSE; @@ -1435,7 +1442,15 @@ LXValidMode(int scrnIndex, DisplayModePtr pMode, Bool Verbose, int flags) static Bool LXEnterVT(int scrnIndex, int flags) { - return LXEnterGraphics(NULL, xf86Screens[scrnIndex]); + ScrnInfoPtr pScrni = xf86Screens[scrnIndex]; + Bool ret = LXEnterGraphics(NULL, pScrni); + + /* Reallocate a shadow area, if we need it */ + + if (ret == TRUE) + ret = LXAllocShadow(pScrni); + + return ret; } static void @@ -1446,6 +1461,13 @@ LXLeaveVT(int scrnIndex, int flags) pGeode->PrevDisplayOffset = vg_get_display_offset(); LXLeaveGraphics(xf86Screens[scrnIndex]); + + /* Destroy any shadow area, if we have it */ + + if (pGeode->shadowArea != NULL) { + exaOffscreenFree(pScrni->pScreen, pGeode->shadowArea); + pGeode->shadowArea = NULL; + } } void diff --git a/src/amd_lx_exa.c b/src/amd_lx_exa.c index 2f5ef85..702a4a1 100644 --- a/src/amd_lx_exa.c +++ b/src/amd_lx_exa.c @@ -771,8 +771,6 @@ lx_composite_convert(PixmapPtr pxDst, unsigned long dstOffset, { /* Step 1 - copy the destination into the scratch buffer */ - ErrorF("Convert\n"); - gp_declare_blt(0); gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); diff --git a/src/amd_lx_rotate.c b/src/amd_lx_rotate.c index b803b74..300e327 100644 --- a/src/amd_lx_rotate.c +++ b/src/amd_lx_rotate.c @@ -31,6 +31,16 @@ #include "shadow.h" #include "amd.h" +static void +LXShadowSave(ScreenPtr pScreen, ExaOffscreenArea *area) +{ + ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum]; + GeodeRec *pGeode = GEODEPTR(pScrni); + + if (area == pGeode->shadowArea) + pGeode->shadowArea = NULL; +} + static void * LXWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, CARD32 * size, void *closure) @@ -159,6 +169,60 @@ Bool LXSetRotatePitch(ScrnInfoPtr pScrni) return TRUE; } +Bool LXAllocShadow(ScrnInfoPtr pScrni) +{ + GeodeRec *pGeode = GEODEPTR(pScrni); + PixmapPtr pPixmap; + + int size; + + if (pGeode->rotation == RR_Rotate_0) { + + if (pGeode->shadowArea) { + exaOffscreenFree(pScrni->pScreen, pGeode->shadowArea); + pGeode->shadowArea = NULL; + } + + pScrni->fbOffset = pGeode->displayOffset; + } + else { + if (pGeode->rotation == RR_Rotate_90 || pGeode->rotation == RR_Rotate_270) + size = pGeode->displayPitch * pScrni->virtualX; + else + size = pGeode->displayPitch * pScrni->virtualY; + + if (pGeode->shadowArea) { + + if (pGeode->shadowArea->size < size) { + exaOffscreenFree(pScrni->pScreen,pGeode->shadowArea); + pGeode->shadowArea = NULL; + } + } + + if (pGeode->shadowArea == NULL) { + pGeode->shadowArea = exaOffscreenAlloc(pScrni->pScreen, size, 32, TRUE, + LXShadowSave, pGeode); + + if (pGeode->shadowArea == NULL) + return FALSE; + } + + pScrni->fbOffset = pGeode->shadowArea->offset; + } + + pPixmap = pScrni->pScreen->GetScreenPixmap(pScrni->pScreen); + + pScrni->pScreen->ModifyPixmapHeader(pPixmap, + pScrni->pScreen->width, + pScrni->pScreen->height, + pScrni->pScreen->rootDepth, + pScrni->bitsPerPixel, + PixmapBytePad(pScrni->displayWidth, pScrni->pScreen->rootDepth), + (pointer) (pGeode->FBBase + pScrni->fbOffset)); + + return TRUE; +} + Bool LXRotate(ScrnInfoPtr pScrni, DisplayModePtr mode) { @@ -182,50 +246,16 @@ LXRotate(ScrnInfoPtr pScrni, DisplayModePtr mode) LXSetRotatePitch(pScrni); if (pGeode->rotation != RR_Rotate_0) { - - - ret = shadowAdd(pScrni->pScreen, pPixmap, LXUpdateFunc, + + ret = shadowAdd(pScrni->pScreen, pPixmap, LXUpdateFunc, LXWindowLinear, pGeode->rotation, NULL); - if (!ret) { - ErrorF("shadowAdd failed\n"); - goto error; - } - } - - if (pGeode->rotation == RR_Rotate_0) - pScrni->fbOffset = pGeode->displayOffset; - else - pScrni->fbOffset = pGeode->shadowOffset; - - vg_set_display_offset(pScrni->fbOffset); - - pScrni->pScreen->ModifyPixmapHeader(pPixmap, - pScrni->pScreen->width, - pScrni->pScreen->height, - pScrni->pScreen->rootDepth, - pScrni->bitsPerPixel, - PixmapBytePad(pScrni->displayWidth, pScrni->pScreen->rootDepth), - (pointer) (pGeode->FBBase + pScrni->fbOffset)); - - /* Don't use XAA pixmap cache or offscreen pixmaps when rotated */ - - if (pGeode->AccelInfoRec) { - if (pGeode->rotation == RR_Rotate_0) { - pGeode->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; - pGeode->AccelInfoRec->UsingPixmapCache = TRUE; - pGeode->AccelInfoRec->maxOffPixWidth = 0; - pGeode->AccelInfoRec->maxOffPixHeight = 0; - } - else { - pGeode->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER; - pGeode->AccelInfoRec->UsingPixmapCache = FALSE; - pGeode->AccelInfoRec->maxOffPixWidth = 1; - pGeode->AccelInfoRec->maxOffPixHeight = 1; - } + if (!ret) + goto error; } - return TRUE; + if (LXAllocShadow(pScrni)) + return TRUE; error: /* Restore the old rotation */ diff --git a/src/amd_lx_video.c b/src/amd_lx_video.c index 13129c0..e1e51aa 100644 --- a/src/amd_lx_video.c +++ b/src/amd_lx_video.c @@ -110,7 +110,7 @@ LXCopyFromSys(GeodeRec *pGeode, unsigned char *src, unsigned int dst, gp_declare_blt(0); gp_set_bpp(16); - + gp_set_raster_operation(0xCC); gp_set_strides(dstPitch, srcPitch); gp_set_solid_pattern(0); @@ -127,6 +127,8 @@ LXVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) if (area == pPriv->area) pPriv->area = NULL; + + LXStopVideo(pScrni, (void *) pPriv, TRUE); } @@ -141,7 +143,7 @@ LXAllocateVidMem(ScrnInfoPtr pScrni, void **memp, int size) exaOffscreenFree(pScrni->pScreen, area); } - + area = exaOffscreenAlloc(pScrni->pScreen, size, 16, TRUE, LXVideoSave, NULL); @@ -229,13 +231,13 @@ LXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, UVSrcPitch = ((width >> 1) + 3) & ~3; UVDstPitch = ((width >> 1) + 15) & ~15; - if (id != FOURCC_I420) { - VSrcOffset = YSrcPitch * height; - USrcOffset = VSrcOffset + (UVSrcPitch * (height >> 1)); + USrcOffset = YSrcPitch * height; + VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); - VDstOffset = YDstPitch * height; - UDstOffset = VDstOffset + (UVDstPitch * (height >> 1)); - } + UDstOffset = YDstPitch * height; + VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); + +#if 0 else { USrcOffset = YSrcPitch * height; VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); @@ -243,6 +245,7 @@ LXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, UDstOffset = YDstPitch * height; VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); } +#endif size = YDstPitch * height; size += UVDstPitch * height; @@ -285,11 +288,6 @@ LXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, LXCopyFromSys(pGeode, buf + USrcOffset, pPriv->offset + UDstOffset, UVDstPitch, UVSrcPitch, lines, pixels >> 1); - /* Copy V */ - - //LXCopyFromSys(pGeode, buf + VSrcOffset, pPriv->offset + VDstOffset, - //UVDstPitch, UVSrcPitch, lines >> 1, pixels >> 1); - videoScratch.dstOffset = pPriv->offset + YDstOffset; videoScratch.dstPitch = YDstPitch; videoScratch.UVPitch = UVDstPitch; @@ -368,6 +366,8 @@ LXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, DF_VIDEO_POSITION vidPos; DF_VIDEO_SOURCE_PARAMS vSrcParams; + memset(&vSrcParams, 0, sizeof(vSrcParams)); + gp_wait_until_idle(); switch(id) { @@ -448,10 +448,13 @@ LXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, switch(id) { case FOURCC_Y800: case FOURCC_I420: - case FOURCC_YV12: vSrcParams.u_offset = videoScratch.UDstOffset + uvExtra; vSrcParams.v_offset = videoScratch.VDstOffset + uvExtra; break; + case FOURCC_YV12: + vSrcParams.v_offset = videoScratch.UDstOffset + uvExtra; + vSrcParams.u_offset = videoScratch.VDstOffset + uvExtra; + break; default: vSrcParams.u_offset = vSrcParams.v_offset = 0; @@ -476,19 +479,22 @@ LXPutImage(ScrnInfoPtr pScrni, INT32 x1,x2,y1,y2; BoxRec dstBox; + if (pGeode->rotation != RR_Rotate_0) + return Success; + if (srcW <= 0 || srcH <= 0) { - ErrorF("Nothing to draw!\n"); return Success; } if (drawW <= 0 || drawH <=0) { - ErrorF("Nothing to show!\n"); return Success; } if (drawW > 16384) drawW = 16384; + memset(&videoScratch, 0, sizeof(videoScratch)); + x1 = srcX; x2 = srcX + srcW; y1 = srcY; @@ -503,13 +509,13 @@ LXPutImage(ScrnInfoPtr pScrni, dstBox.x2 -= pScrni->frameX0; dstBox.y1 -= pScrni->frameY0; dstBox.y2 -= pScrni->frameY0; - + switch(id) { case FOURCC_YV12: - case FOURCC_I420: + case FOURCC_I420: LXCopyPlanar(pScrni, id, buf, x1, y1, x2, y2, width, height, data); break; - + case FOURCC_UYVY: case FOURCC_YUY2: case FOURCC_Y800: @@ -597,6 +603,9 @@ LXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; GeodeRec *pGeode = GEODEPTR(pScrni); + if (pPriv->videoStatus == 0) + return; + REGION_EMPTY(pScrni->pScreen, &pPriv->clip); gp_wait_until_idle(); @@ -605,20 +614,20 @@ LXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) df_set_video_enable(0,0); df_set_video_palette(NULL); } - - if (pPriv->area) + + if (pPriv->area) { exaOffscreenFree(pScrni->pScreen, pPriv->area); - + pPriv->area = NULL; + } + pPriv->videoStatus = 0; /* Eh? */ pGeode->OverlayON = FALSE; } - else { - if (pPriv->videoStatus & CLIENT_VIDEO_ON) { - pPriv->videoStatus |= OFF_TIMER; - pPriv->offTime = currentTime.milliseconds + OFF_DELAY; - } + else if (pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; } } @@ -881,8 +890,10 @@ LXFreeSurface(XF86SurfacePtr surface) if (pPriv->isOn) LXStopSurface(surface); - if (pPriv->area) + if (pPriv->area) { exaOffscreenFree(pScrni->pScreen, pPriv->area); + pPriv->area = NULL; + } xfree(surface->pitches); xfree(surface->offsets); |