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