1/*
2 * Copyright 1999 by Matthew Grossman, Seattle, USA.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of Matthew
9 * Grossman not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission.  Matthew Grossman makes no representations about the
12 * suitability of this software for any purpose.  It is provided "as
13 * is" without express or implied warranty.
14 *
15 * MATTHEW GROSSMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL MATTHEW GROSSMAN BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
21 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 * SOFTWARE.
23 *
24 * Author:  Matthew Grossman, mattg@oz.net
25 *
26 * DEC TGA hardware cursor using BT485 ramdac
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33/* tga_cursor.c */
34
35#include "xf86.h"
36#include "xf86PciInfo.h"
37#include "xf86Pci.h"
38#include "BT.h"
39
40#include "tga.h"
41#include "tga_regs.h"
42
43/* defines */
44/* BT485 also supports 32 bit cursor, but why use it? */
45#define CURSOR_SIZE 64
46
47/* protos */
48
49static void TGALoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
50static void TGAShowCursor(ScrnInfoPtr pScrn);
51static void TGAHideCursor(ScrnInfoPtr pScrn);
52static void TGASetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
53static void TGASetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
54
55static void
56TGALoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
57{
58  TGAPtr pTga = TGAPTR(pScrn);
59  int i;
60
61  /* set 64 bit cursor */
62  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_0, 0x7F, 0x80);
63  pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
64  pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0xF8, 0x04);
65
66  /* first write address reg @ 0x0, then write 0xb with the data (for 32 bit
67     cursor) */
68
69  pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00);
70
71  for(i = 0; i < ((CURSOR_SIZE * CURSOR_SIZE) / 8); i++)
72    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *src++);
73
74  for(i = 0; i < ((CURSOR_SIZE * CURSOR_SIZE) / 8); i++)
75    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *src++);
76
77/*    pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00); */
78
79  return;
80}
81
82
83static void
84TGAShowCursor(ScrnInfoPtr pScrn)
85{
86  TGAPtr pTga = TGAPTR(pScrn);
87
88  /* enable BT485 X11 cursor */
89  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x03);
90
91  return;
92}
93
94
95static void
96TGAHideCursor(ScrnInfoPtr pScrn)
97{
98  TGAPtr pTga = TGAPTR(pScrn);
99
100  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x00);
101
102  return;
103}
104
105static void
106TGASetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
107{
108   TGAPtr pTga = TGAPTR(pScrn);
109   unsigned int tmp_x, tmp_y;
110
111   /* translate x && y to BT485 cursor addresses */
112
113   tmp_x = x + CURSOR_SIZE;
114   tmp_x &= 0x0FFF;
115
116   tmp_y = y + CURSOR_SIZE;
117   tmp_y &= 0x0FFF;
118
119   /* write out the addresses */
120   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_LOW, 0x00, (tmp_x & 0xFF));
121   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_HIGH, 0xF0, (tmp_x >> 8));
122
123   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_LOW, 0x00, (tmp_y & 0xFF));
124   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_HIGH, 0xF0, (tmp_y >> 8));
125
126   return;
127}
128
129
130static void
131TGASetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
132     /* set pScrn->cursor_fg and pScrn->cursor_bg */
133{
134  TGAPtr pTga = TGAPTR(pScrn);
135
136    /* first, load address register at 0x4 with 0x1, then write 3 color
137       octets RGB to 0x5 (background), then write three octets to 0x5
138       (foreground), then write to address register 0xFC */
139
140  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x01);
141
142  /* we don't seem to support the 6 bit DAC option as of 4.0, and why
143     would we? */
144  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x00FF0000) >> 16);
145  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x0000FF00) >> 8);
146  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x000000FF));
147
148  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x00FF0000) >> 16);
149  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x0000FF00) >> 8);
150  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x000000FF));
151
152/*    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x00); */
153
154  return;
155}
156
157
158Bool
159TGAHWCursorInit(ScreenPtr pScreen)
160{
161    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
162    TGAPtr pTga;
163    xf86CursorInfoPtr infoPtr;
164
165    pTga = TGAPTR(pScrn);
166
167    infoPtr = xf86CreateCursorInfoRec();
168    if(!infoPtr) return FALSE;
169
170    pTga->CursorInfoRec = infoPtr;
171
172    infoPtr->MaxWidth = CURSOR_SIZE;
173    infoPtr->MaxHeight = CURSOR_SIZE;
174    infoPtr->Flags =  HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
175      HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
176      HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
177
178    infoPtr->SetCursorColors = TGASetCursorColors;
179    infoPtr->SetCursorPosition = TGASetCursorPosition;
180    infoPtr->LoadCursorImage = TGALoadCursorImage;
181    infoPtr->HideCursor = TGAHideCursor;
182    infoPtr->ShowCursor = TGAShowCursor;
183    infoPtr->UseHWCursor = NULL;
184
185    return(xf86InitCursor(pScreen, infoPtr));
186}
187
188