Home | History | Annotate | Line # | Download | only in src
      1 
      2 #ifdef HAVE_CONFIG_H
      3 #include "config.h"
      4 #endif
      5 
      6 #include "tseng.h"
      7 
      8 /*
      9  *
     10  * ET4000 HWCursor is disabled currently: we need to find a way to set the
     11  * sprite colours.
     12  *
     13  */
     14 
     15 /*
     16  * ET4000W32 sprite engine.
     17  */
     18 static CARD8
     19 ET4000CursorRead(CARD8 Index)
     20 {
     21     outb(0x217A, Index);
     22     return inb(0x217B);
     23 }
     24 
     25 static void
     26 ET4000CursorWrite(CARD8 Index, CARD8 Value)
     27 {
     28     outb(0x217A, Index);
     29     outb(0x217B, Value);
     30 }
     31 
     32 /*
     33  *
     34  */
     35 static Bool
     36 TsengUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
     37 {
     38     /* have this return false for DoubleScan and Interlaced ? */
     39     return TRUE;
     40 }
     41 
     42 static void
     43 TsengShowCursor(ScrnInfoPtr pScrn)
     44 {
     45     unsigned char tmp;
     46     TsengPtr pTseng = TsengPTR(pScrn);
     47 
     48     /* Enable the hardware cursor. */
     49     if (pTseng->ChipType == ET6000) {
     50 	tmp = ET6000IORead(pTseng, 0x46);
     51 	ET6000IOWrite(pTseng, 0x46, (tmp | 0x01));
     52     } else {
     53 	tmp = ET4000CursorRead(0xF7);
     54         ET4000CursorWrite(0xF7, tmp | 0x80);
     55     }
     56 }
     57 
     58 static void
     59 TsengHideCursor(ScrnInfoPtr pScrn)
     60 {
     61     unsigned char tmp;
     62     TsengPtr pTseng = TsengPTR(pScrn);
     63 
     64     /* Disable the hardware cursor. */
     65     if (pTseng->ChipType == ET6000) {
     66 	tmp = ET6000IORead(pTseng, 0x46);
     67 	ET6000IOWrite(pTseng, 0x46, (tmp & 0xfe));
     68     } else {
     69 	tmp = ET4000CursorRead(0xF7);
     70         ET4000CursorWrite(0xF7, tmp & ~0x80);
     71     }
     72 }
     73 
     74 static void
     75 TsengSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
     76 {
     77     int xorigin, yorigin;
     78     TsengPtr pTseng = TsengPTR(pScrn);
     79 
     80     /*
     81      * If the cursor is partly out of screen at the left or top,
     82      * we need to modify the origin.
     83      */
     84     xorigin = 0;
     85     yorigin = 0;
     86     if (x < 0) {
     87 	xorigin = -x;
     88 	x = 0;
     89     }
     90     if (y < 0) {
     91 	yorigin = -y;
     92 	y = 0;
     93     }
     94 #ifdef TODO
     95     /* Correct cursor position in DoubleScan modes */
     96     if (XF86SCRNINFO(pScr)->modes->Flags & V_DBLSCAN)
     97 	y *= 2;
     98 #endif
     99 
    100     if (pTseng->ChipType == ET6000) {
    101 	ET6000IOWrite(pTseng, 0x82, xorigin);
    102 	ET6000IOWrite(pTseng, 0x83, yorigin);
    103 
    104 	ET6000IOWrite(pTseng, 0x84, (x & 0xff));
    105 	ET6000IOWrite(pTseng, 0x85, ((x >> 8) & 0x0f));
    106 
    107 	ET6000IOWrite(pTseng, 0x86, (y & 0xff));
    108 	ET6000IOWrite(pTseng, 0x87, ((y >> 8) & 0x0f));
    109     } else {
    110 	ET4000CursorWrite(0xE2, xorigin);
    111         ET4000CursorWrite(0xE6, yorigin);
    112 
    113 	ET4000CursorWrite(0xE0, x & 0xFF);
    114         ET4000CursorWrite(0xE1, (x >> 8) & 0x0F);
    115 
    116         ET4000CursorWrite(0xE4, y & 0xFF);
    117         ET4000CursorWrite(0xE5, (y >> 8) & 0x0F);
    118     }
    119 }
    120 
    121 /*
    122  * The ET6000 cursor color is only 6 bits, with 2 bits per color. This
    123  * is of course very inaccurate, but high-bit-depth color differences
    124  * are only visible on _large_ planes of equal color. i.e. small areas
    125  * of a certain color (like a cursor) don't need many bits per pixel at
    126  * all, because the difference will not be seen.
    127  *
    128  * So it won't be as bad, but should still be documented nonetheless.
    129  */
    130 static void
    131 TsengSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
    132 {
    133     TsengPtr pTseng = TsengPTR(pScrn);
    134     unsigned char et6k_fg, et6k_bg;
    135 
    136     if (pTseng->ChipType == ET6000) {
    137 	et6k_fg = (fg & 0x00000003)
    138 	    | ((fg & 0x00000300) >> 6)
    139 	    | ((fg & 0x00030000) >> 12);
    140 	et6k_bg = (bg & 0x00000003)
    141 	    | ((bg & 0x00000300) >> 6)
    142 	    | ((bg & 0x00030000) >> 12);
    143 
    144 	ET6000IOWrite(pTseng, 0x67, 0x09);	/* prepare for colour data */
    145 	ET6000IOWrite(pTseng, 0x69, et6k_bg);
    146 	ET6000IOWrite(pTseng, 0x69, et6k_fg);
    147     } else {
    148 	/*
    149 	 * The ET4000 uses color 0 as sprite color "0", and color 0xFF as
    150 	 * sprite color "1". Changing colors implies changing colors 0 and
    151 	 * 255. This is currently not implemented.
    152 	 *
    153 	 * In non-8bpp modes, this would result in always black and white
    154 	 * colors (since the colormap isn't there to translate 0 and 255 to
    155 	 * other colors). And besides, in non-8bpp, there seem to be TWO
    156 	 * cursor images on the screen...
    157 	 */
    158 	xf86Msg(X_ERROR, "Internal error: ET4000 hardware cursor color changes not implemented\n");
    159     }
    160 }
    161 
    162 static void
    163 TsengLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
    164 {
    165     vgaHWPtr hwp = VGAHWPTR(pScrn);
    166     TsengPtr pTseng = TsengPTR(pScrn);
    167     CARD8 tmp;
    168 
    169 #ifdef DEBUG_HWC
    170     int i;
    171     int d;
    172 
    173     for (i = 0; i < 1024; i++) {
    174 	d = *(bits + i);
    175 	ErrorF("%d%d%d%d", d & 0x03, (d >> 2) & 0x03, (d >> 4) & 0x03, (d >> 6) & 0x03);
    176 	if ((i & 15) == 15)
    177 	    ErrorF("\n");
    178     }
    179 #endif
    180 
    181     /*
    182      * Program the cursor image address in video memory.
    183      * We need to set it here or we might loose it on mode/vt switches.
    184      */
    185 
    186     if (pTseng->ChipType == ET6000) {
    187 	/* bits 19:16 */
    188 	tmp = hwp->readCrtc(hwp, 0x0E) & 0xF0;
    189 	tmp |= ((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F;
    190         hwp->writeCrtc(hwp, 0x0E, tmp);
    191 
    192 	/* bits 15:8 */
    193 	hwp->writeCrtc(hwp, 0x0F, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF);
    194 	/* on the ET6000, bits (7:0) are always 0 */
    195     } else {
    196 	/* bits 19:16 */
    197 	tmp = ET4000CursorRead(0xEA) & 0xF0;
    198 	ET4000CursorWrite(0xEA, tmp | (((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F));
    199 	/* bits 15:8 */
    200         ET4000CursorWrite(0xE9, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF);
    201 	/* bits 7:0 */
    202         ET4000CursorWrite(0xE8, (pTseng->HWCursorBufferOffset / 4) & 0xFF);
    203 
    204 	/* this needs to be set for the sprite */
    205 	ET4000CursorWrite(0xEB, 0x02);
    206 
    207         tmp = ET4000CursorRead(0xEC);
    208         ET4000CursorWrite(0xEC, tmp & 0xFE);
    209 
    210         tmp = ET4000CursorRead(0xEF) & 0xF8;
    211         ET4000CursorWrite(0xEF, tmp | 0x02);
    212 
    213         ET4000CursorWrite(0xEE, 0x01);
    214     }
    215     /* this assumes the apertures have been set up correctly for banked mode */
    216     memcpy(pTseng->HWCursorBuffer, bits, 1024);
    217 }
    218 
    219 /*
    220   *
    221   *
    222   */
    223 Bool
    224 TsengHWCursorInit(ScreenPtr pScreen)
    225 {
    226     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    227     TsengPtr pTseng = TsengPTR(pScrn);
    228     xf86CursorInfoPtr infoPtr;
    229 
    230     PDEBUG("	TsengHWCursorInit\n");
    231 
    232     if (!pTseng->HWCursor)
    233 	return FALSE;
    234 
    235     infoPtr = xf86CreateCursorInfoRec();
    236     if (!infoPtr)
    237 	return FALSE;
    238 
    239     pTseng->CursorInfoRec = infoPtr;
    240 
    241     /* calculate memory addres from video memory offsets */
    242     pTseng->HWCursorBuffer =
    243 	pTseng->FbBase + pTseng->HWCursorBufferOffset;
    244 
    245     /* set up the XAA HW cursor structure */
    246     infoPtr->MaxWidth = 64;
    247     infoPtr->MaxHeight = 64;
    248     infoPtr->Flags =
    249 	HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
    250 	HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
    251 	HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
    252 	HARDWARE_CURSOR_INVERT_MASK;
    253     infoPtr->SetCursorColors = TsengSetCursorColors;
    254     infoPtr->SetCursorPosition = TsengSetCursorPosition;
    255     infoPtr->LoadCursorImage = TsengLoadCursorImage;
    256     infoPtr->HideCursor = TsengHideCursor;
    257     infoPtr->ShowCursor = TsengShowCursor;
    258     infoPtr->UseHWCursor = TsengUseHWCursor;
    259 
    260     return (xf86InitCursor(pScreen, infoPtr));
    261 }
    262 
    263 /*
    264  *
    265  */
    266 void
    267 TsengCursorStore(ScrnInfoPtr pScrn, TsengRegPtr Reg)
    268 {
    269     TsengPtr pTseng = TsengPTR(pScrn);
    270 
    271     if (pTseng->ChipType == ET4000)
    272         Reg->CursorCtrl = ET4000CursorRead(0xF7);
    273 }
    274 
    275 /*
    276  *
    277  */
    278 void
    279 TsengCursorRestore(ScrnInfoPtr pScrn, TsengRegPtr Reg)
    280 {
    281     TsengPtr pTseng = TsengPTR(pScrn);
    282 
    283     if (pTseng->ChipType == ET4000)
    284         ET4000CursorWrite(0xF7, Reg->CursorCtrl);
    285 }
    286