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