summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amd.h4
-rw-r--r--src/amd_lx_driver.c138
-rw-r--r--src/amd_lx_exa.c2
-rw-r--r--src/amd_lx_rotate.c110
-rw-r--r--src/amd_lx_video.c67
5 files changed, 192 insertions, 129 deletions
diff --git a/src/amd.h b/src/amd.h
index 3eec3bc..dbf4a92 100644
--- a/src/amd.h
+++ b/src/amd.h
@@ -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);