#include "r128.h"
#include "r128_reg.h"
#include "xf86.h"
#if X_BYTE_ORDER == X_BIG_ENDIAN
#define P_SWAP32( a , b ) \
((char *)a)[0] = ((char *)b)[3]; \
((char *)a)[1] = ((char *)b)[2]; \
((char *)a)[2] = ((char *)b)[1]; \
((char *)a)[3] = ((char *)b)[0]
#define P_SWAP16( a , b ) \
((char *)a)[0] = ((char *)b)[1]; \
((char *)a)[1] = ((char *)b)[0]; \
((char *)a)[2] = ((char *)b)[3]; \
((char *)a)[3] = ((char *)b)[2]
#endif
static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
OUTREG(R128_CUR_CLR0, bg);
OUTREG(R128_CUR_CLR1, fg);
}
static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
xf86CursorInfoPtr cursor = info->cursor;
int xorigin = 0;
int yorigin = 0;
int total_y = pScrn->frameY1 - pScrn->frameY0;
if (x < 0) xorigin = -x;
if (y < 0) yorigin = -y;
if (y > total_y) y = total_y;
if (info->Flags & V_DBLSCAN) y *= 2;
if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin);
OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK
| ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y)));
OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16);
}
static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
{
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
CARD32 *s = (pointer)image;
CARD32 *d = (pointer)(info->FB + info->cursor_start);
int y;
CARD32 save;
save = INREG(R128_CRTC_GEN_CNTL);
OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN);
#if X_BYTE_ORDER == X_BIG_ENDIAN
switch(info->CurrentLayout.pixel_bytes) {
case 4:
case 3:
for (y = 0; y < 64; y++) {
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
}
break;
case 2:
for (y = 0; y < 64; y++) {
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
}
break;
default:
for (y = 0; y < 64; y++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
}
#else
for (y = 0; y < 64; y++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
#endif
for (y = 0; y < 64; y++) {
*d++ = 0xffffffff;
*d++ = 0xffffffff;
*d++ = 0x00000000;
*d++ = 0x00000000;
}
OUTREG(R128_CRTC_GEN_CNTL, save);
}
static void R128HideCursor(ScrnInfoPtr pScrn)
{
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN);
}
static void R128ShowCursor(ScrnInfoPtr pScrn)
{
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN);
}
static Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
return info->cursor_start ? TRUE : FALSE;
}
Bool R128CursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
xf86CursorInfoPtr cursor;
FBAreaPtr fbarea;
int width;
int height;
int size;
if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
cursor->MaxWidth = 64;
cursor->MaxHeight = 64;
cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
| HARDWARE_CURSOR_SHOW_TRANSPARENT
| HARDWARE_CURSOR_UPDATE_UNHIDDEN
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
| HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
#endif
| HARDWARE_CURSOR_INVERT_MASK
| HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
| HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
| HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
cursor->SetCursorColors = R128SetCursorColors;
cursor->SetCursorPosition = R128SetCursorPosition;
cursor->LoadCursorImage = R128LoadCursorImage;
cursor->HideCursor = R128HideCursor;
cursor->ShowCursor = R128ShowCursor;
cursor->UseHWCursor = R128UseHWCursor;
size = (cursor->MaxWidth/4) * cursor->MaxHeight;
width = pScrn->displayWidth;
height = (size*2 + 1023) / pScrn->displayWidth;
fbarea = xf86AllocateOffscreenArea(pScreen,
width,
height,
16,
NULL,
NULL,
NULL);
if (!fbarea) {
info->cursor_start = 0;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Hardware cursor disabled"
" due to insufficient offscreen memory\n");
} else {
info->cursor_start = R128_ALIGN((fbarea->box.x1
+ width * fbarea->box.y1)
* info->CurrentLayout.pixel_bytes, 16);
info->cursor_end = info->cursor_start + size;
}
R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n",
info->cursor_start, info->cursor_end));
return xf86InitCursor(pScreen, cursor);
}