1ba0eab60Smacallan/*
2ba0eab60Smacallan * newport_cursor.c
3ba0eab60Smacallan */
4ba0eab60Smacallan/* $XFree86$ */
5ba0eab60Smacallan
6ba0eab60Smacallan#ifdef HAVE_CONFIG_H
7ba0eab60Smacallan#include "config.h"
8ba0eab60Smacallan#endif
9ba0eab60Smacallan
10ba0eab60Smacallan#include "newport.h"
11ba0eab60Smacallan#include "cursorstr.h"
12ba0eab60Smacallan
13ba0eab60Smacallan#include "servermd.h"
14ba0eab60Smacallan
15ba0eab60Smacallan#define MAX_CURS 32
16ba0eab60Smacallan
17ba0eab60Smacallanstatic void NewportShowCursor(ScrnInfoPtr pScrn);
18ba0eab60Smacallanstatic void NewportHideCursor(ScrnInfoPtr pScrn);
19ba0eab60Smacallanstatic void NewportSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
20ba0eab60Smacallanstatic void NewportSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
21ba0eab60Smacallan/* static void NewportLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits); */
22ba0eab60Smacallanstatic unsigned char* NewportRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs);
23ba0eab60Smacallan
24ba0eab60SmacallanBool
25ba0eab60SmacallanNewportHWCursorInit(ScreenPtr pScreen)
26ba0eab60Smacallan{
27ba0eab60Smacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
28ba0eab60Smacallan	NewportPtr pNewport = NEWPORTPTR(pScrn);
29ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
30ba0eab60Smacallan	xf86CursorInfoPtr infoPtr;
31ba0eab60Smacallan	CARD16 tmp;
32ba0eab60Smacallan
33ba0eab60Smacallan	infoPtr = xf86CreateCursorInfoRec();
34ba0eab60Smacallan	if(!infoPtr)
35ba0eab60Smacallan		return FALSE;
36ba0eab60Smacallan
37ba0eab60Smacallan	pNewport->CursorInfoRec = infoPtr;
38ba0eab60Smacallan	infoPtr->MaxWidth = MAX_CURS;
39ba0eab60Smacallan	infoPtr->MaxHeight = MAX_CURS;
40ba0eab60Smacallan	infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
41ba0eab60Smacallan
42ba0eab60Smacallan	infoPtr->SetCursorColors = NewportSetCursorColors;
43ba0eab60Smacallan	infoPtr->SetCursorPosition = NewportSetCursorPosition;
44ba0eab60Smacallan	infoPtr->LoadCursorImage = NewportLoadCursorImage;
45ba0eab60Smacallan	infoPtr->HideCursor = NewportHideCursor;
46ba0eab60Smacallan	infoPtr->ShowCursor = NewportShowCursor;
47ba0eab60Smacallan	infoPtr->RealizeCursor = NewportRealizeCursor;
48ba0eab60Smacallan	infoPtr->UseHWCursor = NULL;
49ba0eab60Smacallan
50ba0eab60Smacallan	/* enable cursor funtion in shadow register */
51ba0eab60Smacallan	pNewport->vc2ctrl |= VC2_CTRL_ECURS;
52ba0eab60Smacallan	/* enable glyph cursor, maximum size is 32x32x2 */
53ba0eab60Smacallan	pNewport->vc2ctrl &= ~( VC2_CTRL_ECG64 | VC2_CTRL_ECCURS);
54ba0eab60Smacallan	/* setup hw cursors cmap base address  */
55ba0eab60Smacallan	NewportBfwait(pNewportRegs);
56ba0eab60Smacallan	pNewportRegs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
57ba0eab60Smacallan			XM9_CRS_CURS_CMAP_MSB | NPORT_DMODE_W1 );
58ba0eab60Smacallan	tmp = pNewportRegs->set.dcbdata0.bytes.b3;
59ba0eab60Smacallan#if 0
60ba0eab60Smacallan	/* The docs say we can change base address of the cursors
61ba0eab60Smacallan	 * cmap entries, but it doesn't work. */
62ba0eab60Smacallan	tmp++;
63ba0eab60Smacallan#endif
64ba0eab60Smacallan	pNewportRegs->set.dcbmode = (DCB_XMAP0 | W_DCB_XMAP9_PROTOCOL |
65ba0eab60Smacallan			XM9_CRS_CURS_CMAP_MSB | NPORT_DMODE_W1 );
66ba0eab60Smacallan	pNewportRegs->set.dcbdata0.bytes.b3 = tmp;
67ba0eab60Smacallan	pNewport->curs_cmap_base = (tmp << 5) & 0xffe0;
68ba0eab60Smacallan
69ba0eab60Smacallan	return xf86InitCursor(pScreen, infoPtr);
70ba0eab60Smacallan}
71ba0eab60Smacallan
72ba0eab60Smacallan
73ba0eab60Smacallanstatic void NewportShowCursor(ScrnInfoPtr pScrn)
74ba0eab60Smacallan{
75ba0eab60Smacallan	NewportPtr pNewport = NEWPORTPTR(pScrn);
76ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
77ba0eab60Smacallan
78ba0eab60Smacallan	pNewport->vc2ctrl |= VC2_CTRL_ECDISP;
79ba0eab60Smacallan	NewportVc2Set( pNewportRegs, VC2_IREG_CONTROL, pNewport->vc2ctrl);
80ba0eab60Smacallan}
81ba0eab60Smacallan
82ba0eab60Smacallanstatic void NewportHideCursor(ScrnInfoPtr pScrn)
83ba0eab60Smacallan{
84ba0eab60Smacallan	NewportPtr pNewport = NEWPORTPTR(pScrn);
85ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
86ba0eab60Smacallan
87ba0eab60Smacallan	pNewport->vc2ctrl &= ~VC2_CTRL_ECDISP;
88ba0eab60Smacallan	NewportVc2Set( pNewportRegs, VC2_IREG_CONTROL, pNewport->vc2ctrl);
89ba0eab60Smacallan}
90ba0eab60Smacallan
91ba0eab60Smacallanstatic void NewportSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
92ba0eab60Smacallan{
93ba0eab60Smacallan	CARD16 x_off;
94ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
95ba0eab60Smacallan	NewportPtr pNewport = NEWPORTPTR(pScrn);
96ba0eab60Smacallan
97ba0eab60Smacallan	/* the docu says this should always be 31, but it isn't */
98ba0eab60Smacallan	x_off = 31;
99ba0eab60Smacallan	if ( pNewport->board_rev < 6 )
100ba0eab60Smacallan		x_off = 21;
101ba0eab60Smacallan	NewportVc2Set( pNewportRegs, VC2_IREG_CURSX, (CARD16) x + x_off);
102ba0eab60Smacallan	NewportVc2Set( pNewportRegs, VC2_IREG_CURSY, (CARD16) y + 31);
103ba0eab60Smacallan}
104ba0eab60Smacallan
105ba0eab60Smacallanstatic void NewportSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
106ba0eab60Smacallan{
107ba0eab60Smacallan	NewportPtr pNewport = NEWPORTPTR(pScrn);
108ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
109ba0eab60Smacallan	LOCO color;
110ba0eab60Smacallan
111ba0eab60Smacallan	color.blue = bg & 0xff;
112ba0eab60Smacallan	color.green = (bg & 0xff00) >> 8;
113ba0eab60Smacallan	color.red = (bg & 0xff0000) >> 16;
114ba0eab60Smacallan	NewportCmapSetRGB( pNewportRegs, pNewport->curs_cmap_base+2, color);
115ba0eab60Smacallan
116ba0eab60Smacallan	color.blue = fg & 0xff;
117ba0eab60Smacallan	color.green = (fg & 0xff00) >> 8;
118ba0eab60Smacallan	color.red = (fg & 0xff0000) >> 16;
119ba0eab60Smacallan	NewportCmapSetRGB( pNewportRegs, pNewport->curs_cmap_base+1, color);
120ba0eab60Smacallan}
121ba0eab60Smacallan
122ba0eab60Smacallanstatic unsigned char* NewportRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
123ba0eab60Smacallan{
124ba0eab60Smacallan	int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
125ba0eab60Smacallan	CARD32 *mem, *SrcS, *SrcM, *DstS;
126ba0eab60Smacallan	unsigned int i;
127ba0eab60Smacallan
128aee7dae4Smrg	if (!(mem = calloc(1, size)))
129ba0eab60Smacallan        	return NULL;
130ba0eab60Smacallan
131ba0eab60Smacallan	SrcS = (CARD32*)pCurs->bits->source;
132ba0eab60Smacallan    	SrcM = (CARD32*)pCurs->bits->mask;
133ba0eab60Smacallan    	DstS = mem;
134ba0eab60Smacallan	/* first color: maximum is 32*4 Bytes */
135ba0eab60Smacallan	for(i=0; i < pCurs->bits->height; i++) {
136ba0eab60Smacallan		*DstS = *SrcS & *SrcM;
137ba0eab60Smacallan		DstS++, SrcS++, SrcM++;
138ba0eab60Smacallan	}
139ba0eab60Smacallan	/* second color is the lower of mem: again 32*4 Bytes at most */
140ba0eab60Smacallan	DstS = mem + MAX_CURS;
141ba0eab60Smacallan	SrcS = (CARD32*)pCurs->bits->source;
142ba0eab60Smacallan    	SrcM = (CARD32*)pCurs->bits->mask;
143ba0eab60Smacallan	for(i=0; i < pCurs->bits->height; i++) {
144ba0eab60Smacallan		*DstS = (~*SrcS) & *SrcM;
145ba0eab60Smacallan		DstS++, SrcS++, SrcM++;
146ba0eab60Smacallan	}
147ba0eab60Smacallan	return (unsigned char*) mem;
148ba0eab60Smacallan}
149ba0eab60Smacallan
150ba0eab60Smacallanvoid NewportLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
151ba0eab60Smacallan{
152ba0eab60Smacallan	int i;
153ba0eab60Smacallan	CARD16 tmp;
154ba0eab60Smacallan	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
155ba0eab60Smacallan
156ba0eab60Smacallan	/* address of cursor data in vc2's ram */
157ba0eab60Smacallan        tmp = NewportVc2Get( pNewportRegs, VC2_IREG_CENTRY);
158ba0eab60Smacallan 	/* this is where we want to write to: */
159ba0eab60Smacallan        NewportVc2Set( pNewportRegs, VC2_IREG_RADDR, tmp);
160ba0eab60Smacallan        pNewportRegs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
161ba0eab60Smacallan                               		NPORT_DMODE_W2 | VC2_PROTOCOL);
162ba0eab60Smacallan	/* write cursor data */
163ba0eab60Smacallan        for (i = 0; i < ((MAX_CURS * MAX_CURS) >> 3); i++) {
164ba0eab60Smacallan		NewportBfwait(pNewportRegs);
165ba0eab60Smacallan		pNewportRegs->set.dcbdata0.hwords.s1 = *(unsigned short*)bits;
166ba0eab60Smacallan		bits += sizeof(unsigned short);
167ba0eab60Smacallan        }
168ba0eab60Smacallan}
169ba0eab60Smacallan
170