Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
      3  *                      Precision Insight, Inc., Cedar Park, Texas, and
      4  *                      VA Linux Systems Inc., Fremont, California.
      5  *
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining
      9  * a copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation on the rights to use, copy, modify, merge,
     12  * publish, distribute, sublicense, and/or sell copies of the Software,
     13  * and to permit persons to whom the Software is furnished to do so,
     14  * subject to the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial
     18  * portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     23  * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
     24  * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     25  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     27  * OTHER DEALINGS IN THE SOFTWARE.
     28  */
     29 
     30 /*
     31  * Authors:
     32  *   Rickard E. Faith <faith (at) valinux.com>
     33  *   Kevin E. Martin <martin (at) valinux.com>
     34  *
     35  * References:
     36  *
     37  *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
     38  *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
     39  *   1999.
     40  *
     41  *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
     42  *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
     43  *
     44  */
     45 
     46 #ifdef HAVE_CONFIG_H
     47 #include "config.h"
     48 #endif
     49 
     50 				/* Driver data structures */
     51 #include "r128.h"
     52 #include "r128_reg.h"
     53 
     54 				/* X and server generic header files */
     55 #include "xf86.h"
     56 
     57 				/* Because for EXA we need to use a different allocator */
     58 #ifdef USE_EXA
     59 #include "exa.h"
     60 #endif
     61 
     62 #define CURSOR_WIDTH    64
     63 #define CURSOR_HEIGHT   64
     64 
     65 void r128_crtc_show_cursor(xf86CrtcPtr crtc)
     66 {
     67     ScrnInfoPtr pScrn = crtc->scrn;
     68     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
     69     R128InfoPtr info = R128PTR(pScrn);
     70     unsigned char *R128MMIO = info->MMIO;
     71     int crtc_id = r128_crtc->crtc_id;
     72 
     73     switch (crtc_id) {
     74     case 0:
     75         OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN);
     76         break;
     77     case 1:
     78         OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, ~R128_CRTC2_CUR_EN);
     79         break;
     80     default:
     81         return;
     82     }
     83 }
     84 
     85 void r128_crtc_hide_cursor(xf86CrtcPtr crtc)
     86 {
     87     ScrnInfoPtr pScrn = crtc->scrn;
     88     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
     89     R128InfoPtr info = R128PTR(pScrn);
     90     unsigned char *R128MMIO = info->MMIO;
     91     int crtc_id = r128_crtc->crtc_id;
     92 
     93     switch (crtc_id) {
     94     case 0:
     95         OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN);
     96         break;
     97     case 1:
     98         OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN);
     99         break;
    100     default:
    101         return;
    102     }
    103 }
    104 
    105 void r128_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
    106 {
    107     ScrnInfoPtr pScrn = crtc->scrn;
    108     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    109     R128InfoPtr info = R128PTR(pScrn);
    110     unsigned char *R128MMIO = info->MMIO;
    111     int crtc_id = r128_crtc->crtc_id;
    112 
    113     switch (crtc_id) {
    114     case 0:
    115         OUTREG(R128_CUR_CLR0, bg);
    116         OUTREG(R128_CUR_CLR1, fg);
    117         break;
    118     case 1:
    119         OUTREG(R128_CUR2_CLR0, bg);
    120         OUTREG(R128_CUR2_CLR1, fg);
    121         break;
    122     default:
    123         return;
    124     }
    125 }
    126 
    127 void r128_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
    128 {
    129     ScrnInfoPtr           pScrn         = crtc->scrn;
    130     R128InfoPtr           info          = R128PTR(pScrn);
    131     R128CrtcPrivatePtr    r128_crtc     = crtc->driver_private;
    132     unsigned char         *R128MMIO     = info->MMIO;
    133     int                   crtc_id       = r128_crtc->crtc_id;
    134 
    135     int xorigin = 0, yorigin = 0;
    136     DisplayModePtr mode = &crtc->mode;
    137 
    138     if (x < 0) xorigin = -x + 1;
    139     if (y < 0) yorigin = -y + 1;
    140     if (xorigin >= CURSOR_WIDTH)  xorigin = CURSOR_WIDTH - 1;
    141     if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1;
    142 
    143     if (mode->Flags & V_INTERLACE)
    144         y /= 2;
    145     else if (mode->Flags & V_DBLSCAN)
    146         y *= 2;
    147 
    148     if(crtc_id == 0) {
    149         OUTREG(R128_CUR_HORZ_VERT_OFF, (R128_CUR_LOCK | (xorigin << 16) | yorigin));
    150         OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y)));
    151         OUTREG(R128_CUR_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16);
    152     } else if (crtc_id == 1) {
    153         OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK | (xorigin << 16) | yorigin));
    154         OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y)));
    155         OUTREG(R128_CUR2_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16);
    156     }
    157 }
    158 
    159 void r128_crtc_load_cursor_image(xf86CrtcPtr crtc, unsigned char *src)
    160 {
    161     ScrnInfoPtr pScrn = crtc->scrn;
    162     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    163     int crtc_id = r128_crtc->crtc_id;
    164 
    165     R128InfoPtr   info      = R128PTR(pScrn);
    166     unsigned char *R128MMIO = info->MMIO;
    167     uint32_t      save1     = 0;
    168     uint32_t      save2     = 0;
    169 
    170     if (crtc_id == 0) {
    171 	save1 = INREG(R128_CRTC_GEN_CNTL);
    172 	OUTREG(R128_CRTC_GEN_CNTL, save1 & (uint32_t)~R128_CRTC_CUR_EN);
    173     } else if (crtc_id == 1) {
    174 	save2 = INREG(R128_CRTC2_GEN_CNTL);
    175 	OUTREG(R128_CRTC2_GEN_CNTL, save2 & (uint32_t)~R128_CRTC2_CUR_EN);
    176     }
    177 
    178 #if X_BYTE_ORDER == X_BIG_ENDIAN
    179     if (info->CurrentLayout.pixel_bytes == 4 || info->CurrentLayout.pixel_bytes == 3)
    180         R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src,
    181                      CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_32BPP_SWAP);
    182     else if (info->CurrentLayout.pixel_bytes == 2)
    183         R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src,
    184                      CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_16BPP_SWAP);
    185     else
    186 #endif
    187     memcpy(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, CURSOR_WIDTH * CURSOR_HEIGHT / 4);
    188 
    189     if (crtc_id == 0)
    190 	OUTREG(R128_CRTC_GEN_CNTL, save1);
    191     else
    192         OUTREG(R128_CRTC2_GEN_CNTL, save2);
    193 }
    194 
    195 /* Initialize hardware cursor support. */
    196 Bool R128CursorInit(ScreenPtr pScreen)
    197 {
    198     ScrnInfoPtr           pScrn   = xf86ScreenToScrn(pScreen);
    199     R128InfoPtr           info    = R128PTR(pScrn);
    200     FBAreaPtr             fbarea  = NULL;
    201 #ifdef USE_EXA
    202     ExaOffscreenArea*	  osArea  = NULL;
    203 #else
    204     void*		  osArea  = NULL;
    205 #endif
    206     xf86CrtcConfigPtr     xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    207     uint32_t              cursor_offset = 0;
    208     int                   cpp = info->CurrentLayout.pixel_bytes;
    209     int                   width;
    210     int                   width_bytes;
    211     int                   height;
    212     int                   size;
    213     int                   size_bytes;
    214     int                   c;
    215 
    216     size                      = CURSOR_WIDTH * CURSOR_HEIGHT / 4;
    217     size_bytes                = size * 2;
    218     width                     = pScrn->displayWidth;
    219     width_bytes               = width * (pScrn->bitsPerPixel / 8);
    220     height                    = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes;
    221 
    222     if(!info->useEXA) {
    223 	fbarea = xf86AllocateOffscreenArea(pScreen, width, height,
    224 					   16, NULL, NULL, NULL);
    225 
    226 	if (fbarea)
    227 	    cursor_offset = R128_ALIGN((fbarea->box.x1 + width * fbarea->box.y1) * cpp, 16);
    228     }
    229 #ifdef USE_EXA
    230     else {
    231 	osArea = exaOffscreenAlloc(pScreen, width * height, 16,
    232 				   TRUE, NULL, NULL);
    233 
    234 	if (osArea)
    235 	    cursor_offset = osArea->offset;
    236     }
    237 #endif
    238 
    239     if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) {
    240 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    241 		   "Hardware cursor disabled"
    242 		   " due to insufficient offscreen memory\n");
    243         return FALSE;
    244     } else {
    245         for (c = 0; c < xf86_config->num_crtc; c++) {
    246             xf86CrtcPtr crtc = xf86_config->crtc[c];
    247 	    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    248 
    249             r128_crtc->cursor_offset = cursor_offset + (c * size);
    250             xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    251 		       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
    252 		       (size_bytes * xf86_config->num_crtc) / 1024, c,
    253 		       (unsigned int)r128_crtc->cursor_offset);
    254         }
    255     }
    256 
    257     return xf86_cursors_init(pScreen, CURSOR_WIDTH, CURSOR_HEIGHT,
    258 			     (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
    259 			      HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
    260 			      HARDWARE_CURSOR_SHOW_TRANSPARENT |
    261 			      HARDWARE_CURSOR_UPDATE_UNHIDDEN |
    262 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
    263 			      HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
    264 #endif
    265 			      HARDWARE_CURSOR_INVERT_MASK |
    266 			      HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
    267 			      HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64));
    268 }
    269