17706df26Smrg/*
27706df26Smrg * Copyright 1999 by Matthew Grossman, Seattle, USA.
37706df26Smrg *
47706df26Smrg * Permission to use, copy, modify, distribute, and sell this software
57706df26Smrg * and its documentation for any purpose is hereby granted without
67706df26Smrg * fee, provided that the above copyright notice appear in all copies
77706df26Smrg * and that both that copyright notice and this permission notice
87706df26Smrg * appear in supporting documentation, and that the name of Matthew
97706df26Smrg * Grossman not be used in advertising or publicity pertaining to
107706df26Smrg * distribution of the software without specific, written prior
117706df26Smrg * permission.  Matthew Grossman makes no representations about the
127706df26Smrg * suitability of this software for any purpose.  It is provided "as
137706df26Smrg * is" without express or implied warranty.
147706df26Smrg *
157706df26Smrg * MATTHEW GROSSMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
167706df26Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
177706df26Smrg * FITNESS, IN NO EVENT SHALL MATTHEW GROSSMAN BE LIABLE FOR ANY
187706df26Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
197706df26Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
207706df26Smrg * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
217706df26Smrg * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
227706df26Smrg * SOFTWARE.
237706df26Smrg *
247706df26Smrg * Author:  Matthew Grossman, mattg@oz.net
257706df26Smrg *
267706df26Smrg * DEC TGA hardware cursor using BT485 ramdac
277706df26Smrg */
287706df26Smrg
297706df26Smrg#ifdef HAVE_CONFIG_H
307706df26Smrg#include "config.h"
317706df26Smrg#endif
327706df26Smrg
337706df26Smrg/* tga_cursor.c */
347706df26Smrg
357706df26Smrg#include "xf86.h"
367706df26Smrg#include "xf86PciInfo.h"
377706df26Smrg#include "xf86Pci.h"
387706df26Smrg#include "BT.h"
397706df26Smrg
407706df26Smrg#include "tga.h"
417706df26Smrg#include "tga_regs.h"
427706df26Smrg
437706df26Smrg/* defines */
447706df26Smrg/* BT485 also supports 32 bit cursor, but why use it? */
457706df26Smrg#define CURSOR_SIZE 64
467706df26Smrg
477706df26Smrg/* protos */
487706df26Smrg
497706df26Smrgstatic void TGALoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
507706df26Smrgstatic void TGAShowCursor(ScrnInfoPtr pScrn);
517706df26Smrgstatic void TGAHideCursor(ScrnInfoPtr pScrn);
527706df26Smrgstatic void TGASetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
537706df26Smrgstatic void TGASetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
547706df26Smrg
557706df26Smrgstatic void
567706df26SmrgTGALoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
577706df26Smrg{
587706df26Smrg  TGAPtr pTga = TGAPTR(pScrn);
597706df26Smrg  int i;
607706df26Smrg
617706df26Smrg  /* set 64 bit cursor */
627706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_0, 0x7F, 0x80);
637706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
647706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0xF8, 0x04);
657706df26Smrg
667706df26Smrg  /* first write address reg @ 0x0, then write 0xb with the data (for 32 bit
677706df26Smrg     cursor) */
687706df26Smrg
697706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00);
707706df26Smrg
717706df26Smrg  for(i = 0; i < ((CURSOR_SIZE * CURSOR_SIZE) / 8); i++)
727706df26Smrg    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *src++);
737706df26Smrg
747706df26Smrg  for(i = 0; i < ((CURSOR_SIZE * CURSOR_SIZE) / 8); i++)
757706df26Smrg    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *src++);
767706df26Smrg
777706df26Smrg/*    pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00); */
787706df26Smrg
797706df26Smrg  return;
807706df26Smrg}
817706df26Smrg
827706df26Smrg
837706df26Smrgstatic void
847706df26SmrgTGAShowCursor(ScrnInfoPtr pScrn)
857706df26Smrg{
867706df26Smrg  TGAPtr pTga = TGAPTR(pScrn);
877706df26Smrg
887706df26Smrg  /* enable BT485 X11 cursor */
897706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x03);
907706df26Smrg
917706df26Smrg  return;
927706df26Smrg}
937706df26Smrg
947706df26Smrg
957706df26Smrgstatic void
967706df26SmrgTGAHideCursor(ScrnInfoPtr pScrn)
977706df26Smrg{
987706df26Smrg  TGAPtr pTga = TGAPTR(pScrn);
997706df26Smrg
1007706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x00);
1017706df26Smrg
1027706df26Smrg  return;
1037706df26Smrg}
1047706df26Smrg
1057706df26Smrgstatic void
1067706df26SmrgTGASetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
1077706df26Smrg{
1087706df26Smrg   TGAPtr pTga = TGAPTR(pScrn);
1097706df26Smrg   unsigned int tmp_x, tmp_y;
1107706df26Smrg
1117706df26Smrg   /* translate x && y to BT485 cursor addresses */
1127706df26Smrg
1137706df26Smrg   tmp_x = x + CURSOR_SIZE;
1147706df26Smrg   tmp_x &= 0x0FFF;
1157706df26Smrg
1167706df26Smrg   tmp_y = y + CURSOR_SIZE;
1177706df26Smrg   tmp_y &= 0x0FFF;
1187706df26Smrg
1197706df26Smrg   /* write out the addresses */
1207706df26Smrg   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_LOW, 0x00, (tmp_x & 0xFF));
1217706df26Smrg   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_HIGH, 0xF0, (tmp_x >> 8));
1227706df26Smrg
1237706df26Smrg   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_LOW, 0x00, (tmp_y & 0xFF));
1247706df26Smrg   pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_HIGH, 0xF0, (tmp_y >> 8));
1257706df26Smrg
1267706df26Smrg   return;
1277706df26Smrg}
1287706df26Smrg
1297706df26Smrg
1307706df26Smrgstatic void
1317706df26SmrgTGASetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
1327706df26Smrg     /* set pScrn->cursor_fg and pScrn->cursor_bg */
1337706df26Smrg{
1347706df26Smrg  TGAPtr pTga = TGAPTR(pScrn);
1357706df26Smrg
1367706df26Smrg    /* first, load address register at 0x4 with 0x1, then write 3 color
1377706df26Smrg       octets RGB to 0x5 (background), then write three octets to 0x5
1387706df26Smrg       (foreground), then write to address register 0xFC */
1397706df26Smrg
1407706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x01);
1417706df26Smrg
1427706df26Smrg  /* we don't seem to support the 6 bit DAC option as of 4.0, and why
1437706df26Smrg     would we? */
1447706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x00FF0000) >> 16);
1457706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x0000FF00) >> 8);
1467706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (bg & 0x000000FF));
1477706df26Smrg
1487706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x00FF0000) >> 16);
1497706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x0000FF00) >> 8);
1507706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, (fg & 0x000000FF));
1517706df26Smrg
1527706df26Smrg/*    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x00); */
1537706df26Smrg
1547706df26Smrg  return;
1557706df26Smrg}
1567706df26Smrg
1577706df26Smrg
1587706df26SmrgBool
1597706df26SmrgTGAHWCursorInit(ScreenPtr pScreen)
1607706df26Smrg{
161b92e825aSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1627706df26Smrg    TGAPtr pTga;
1637706df26Smrg    xf86CursorInfoPtr infoPtr;
1647706df26Smrg
1657706df26Smrg    pTga = TGAPTR(pScrn);
1667706df26Smrg
1677706df26Smrg    infoPtr = xf86CreateCursorInfoRec();
1687706df26Smrg    if(!infoPtr) return FALSE;
1697706df26Smrg
1707706df26Smrg    pTga->CursorInfoRec = infoPtr;
1717706df26Smrg
1727706df26Smrg    infoPtr->MaxWidth = CURSOR_SIZE;
1737706df26Smrg    infoPtr->MaxHeight = CURSOR_SIZE;
1747706df26Smrg    infoPtr->Flags =  HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1757706df26Smrg      HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
1767706df26Smrg      HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
1777706df26Smrg
1787706df26Smrg    infoPtr->SetCursorColors = TGASetCursorColors;
1797706df26Smrg    infoPtr->SetCursorPosition = TGASetCursorPosition;
1807706df26Smrg    infoPtr->LoadCursorImage = TGALoadCursorImage;
1817706df26Smrg    infoPtr->HideCursor = TGAHideCursor;
1827706df26Smrg    infoPtr->ShowCursor = TGAShowCursor;
1837706df26Smrg    infoPtr->UseHWCursor = NULL;
1847706df26Smrg
1857706df26Smrg    return(xf86InitCursor(pScreen, infoPtr));
1867706df26Smrg}
1877706df26Smrg
188