Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
      3  *                VA Linux Systems Inc., Fremont, California.
      4  *
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation on the rights to use, copy, modify, merge,
     11  * publish, distribute, sublicense, and/or sell copies of the Software,
     12  * and to permit persons to whom the Software is furnished to do so,
     13  * subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial
     17  * portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     22  * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
     23  * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     24  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     26  * DEALINGS IN THE SOFTWARE.
     27  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #define RADEONCTRACE(x)
     34 /*#define RADEONCTRACE(x) RADEONTRACE(x) */
     35 
     36 /*
     37  * Authors:
     38  *   Kevin E. Martin <martin (at) xfree86.org>
     39  *   Rickard E. Faith <faith (at) valinux.com>
     40  *
     41  * References:
     42  *
     43  * !!!! FIXME !!!!
     44  *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
     45  *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
     46  *   1999.
     47  *
     48  *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
     49  *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
     50  *
     51  */
     52 
     53 				/* Driver data structures */
     54 #include "radeon.h"
     55 #include "radeon_version.h"
     56 #include "radeon_reg.h"
     57 #include "radeon_macros.h"
     58 
     59 				/* X and server generic header files */
     60 #include "xf86.h"
     61 
     62 #define CURSOR_WIDTH	64
     63 #define CURSOR_HEIGHT	64
     64 
     65 /*
     66  * The cursor bits are always 32bpp.  On MSBFirst buses,
     67  * configure byte swapping to swap 32 bit units when writing
     68  * the cursor image.  Byte swapping must always be returned
     69  * to its previous value before returning.
     70  */
     71 #if X_BYTE_ORDER == X_BIG_ENDIAN
     72 
     73 #define CURSOR_SWAPPING_DECL_MMIO   unsigned char *RADEONMMIO = info->MMIO;
     74 #define CURSOR_SWAPPING_START() \
     75   do { \
     76   if (info->ChipFamily < CHIP_FAMILY_R600) \
     77     OUTREG(RADEON_SURFACE_CNTL, \
     78 	   (info->ModeReg->surface_cntl | \
     79 	     RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \
     80 	   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \
     81   } while (0)
     82 #define CURSOR_SWAPPING_END()	\
     83   do { \
     84   if (info->ChipFamily < CHIP_FAMILY_R600) \
     85       OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); \
     86   } while (0)
     87 #else
     88 
     89 #define CURSOR_SWAPPING_DECL_MMIO
     90 #define CURSOR_SWAPPING_START()
     91 #define CURSOR_SWAPPING_END()
     92 
     93 #endif
     94 
     95 static void
     96 avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable)
     97 {
     98     ScrnInfoPtr pScrn = crtc->scrn;
     99     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    100     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
    101     unsigned char     *RADEONMMIO = info->MMIO;
    102 
    103     /* always use the same cursor mode even if the cursor is disabled,
    104      * otherwise you may end up with cursor curruption bands
    105      */
    106     OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
    107 
    108     if (enable) {
    109 	uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset;
    110 	if (info->ChipFamily >= CHIP_FAMILY_RV770) {
    111 	    if (radeon_crtc->crtc_id)
    112 		OUTREG(R700_D2CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf);
    113 	    else
    114 		OUTREG(R700_D1CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf);
    115 	}
    116 	OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
    117 	       info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset);
    118 	OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
    119 	       AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
    120     }
    121 }
    122 
    123 static void
    124 avivo_lock_cursor(xf86CrtcPtr crtc, Bool lock)
    125 {
    126     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    127     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
    128     unsigned char     *RADEONMMIO = info->MMIO;
    129     uint32_t tmp;
    130 
    131     tmp = INREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
    132 
    133     if (lock)
    134 	tmp |= AVIVO_D1CURSOR_UPDATE_LOCK;
    135     else
    136 	tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
    137 
    138     OUTREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp);
    139 }
    140 
    141 static void
    142 evergreen_setup_cursor(xf86CrtcPtr crtc, Bool enable)
    143 {
    144     ScrnInfoPtr pScrn = crtc->scrn;
    145     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    146     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
    147     unsigned char     *RADEONMMIO = info->MMIO;
    148 
    149     /* always use the same cursor mode even if the cursor is disabled,
    150      * otherwise you may end up with cursor curruption bands
    151      */
    152     OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
    153 	   EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
    154 
    155     if (enable) {
    156 	uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset;
    157 	OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
    158 	       (location >> 32) & 0xf);
    159 	OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
    160 	       location & EVERGREEN_CUR_SURFACE_ADDRESS_MASK);
    161 	OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
    162 	       EVERGREEN_CURSOR_EN | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
    163     }
    164 }
    165 
    166 static void
    167 evergreen_lock_cursor(xf86CrtcPtr crtc, Bool lock)
    168 {
    169     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    170     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
    171     unsigned char     *RADEONMMIO = info->MMIO;
    172     uint32_t tmp;
    173 
    174     tmp = INREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
    175 
    176     if (lock)
    177 	tmp |= EVERGREEN_CURSOR_UPDATE_LOCK;
    178     else
    179 	tmp &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
    180 
    181     OUTREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, tmp);
    182 }
    183 
    184 void
    185 radeon_crtc_show_cursor (xf86CrtcPtr crtc)
    186 {
    187     ScrnInfoPtr pScrn = crtc->scrn;
    188     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    189     int crtc_id = radeon_crtc->crtc_id;
    190     RADEONInfoPtr      info       = RADEONPTR(pScrn);
    191     unsigned char     *RADEONMMIO = info->MMIO;
    192 
    193     if (IS_DCE4_VARIANT) {
    194 	evergreen_lock_cursor(crtc, TRUE);
    195 	evergreen_setup_cursor(crtc, TRUE);
    196 	evergreen_lock_cursor(crtc, FALSE);
    197     } else if (IS_AVIVO_VARIANT) {
    198 	avivo_lock_cursor(crtc, TRUE);
    199 	avivo_setup_cursor(crtc, TRUE);
    200 	avivo_lock_cursor(crtc, FALSE);
    201     } else {
    202         switch (crtc_id) {
    203         case 0:
    204             OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
    205 	    break;
    206         case 1:
    207             OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
    208 	    break;
    209         default:
    210             return;
    211         }
    212 
    213         OUTREGP(RADEON_MM_DATA, RADEON_CRTC_CUR_EN | 2 << 20,
    214                 ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
    215     }
    216 }
    217 
    218 void
    219 radeon_crtc_hide_cursor (xf86CrtcPtr crtc)
    220 {
    221     ScrnInfoPtr pScrn = crtc->scrn;
    222     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    223     int crtc_id = radeon_crtc->crtc_id;
    224     RADEONInfoPtr      info       = RADEONPTR(pScrn);
    225     unsigned char     *RADEONMMIO = info->MMIO;
    226 
    227     if (IS_DCE4_VARIANT) {
    228 	evergreen_lock_cursor(crtc, TRUE);
    229 	evergreen_setup_cursor(crtc, FALSE);
    230 	evergreen_lock_cursor(crtc, FALSE);
    231     } else if (IS_AVIVO_VARIANT) {
    232 	avivo_lock_cursor(crtc, TRUE);
    233 	avivo_setup_cursor(crtc, FALSE);
    234 	avivo_lock_cursor(crtc, FALSE);
    235     } else {
    236 	switch(crtc_id) {
    237     	case 0:
    238             OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
    239             break;
    240     	case 1:
    241 	    OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
    242 	    break;
    243         default:
    244 	    return;
    245         }
    246 
    247         OUTREGP(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
    248    }
    249 }
    250 
    251 void
    252 radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
    253 {
    254     ScrnInfoPtr pScrn = crtc->scrn;
    255     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
    256     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    257     int crtc_id = radeon_crtc->crtc_id;
    258     RADEONInfoPtr      info       = RADEONPTR(pScrn);
    259     unsigned char     *RADEONMMIO = info->MMIO;
    260     int xorigin = 0, yorigin = 0;
    261     int stride = 256;
    262     DisplayModePtr mode = &crtc->mode;
    263     int w = CURSOR_WIDTH;
    264 
    265     if (x < 0)                        xorigin = -x+1;
    266     if (y < 0)                        yorigin = -y+1;
    267     if (xorigin >= CURSOR_WIDTH)  xorigin = CURSOR_WIDTH - 1;
    268     if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1;
    269 
    270     if (IS_AVIVO_VARIANT) {
    271 	/* avivo cursor spans the full fb width */
    272 	if (crtc->rotatedData == NULL) {
    273 	    x += crtc->x;
    274 	    y += crtc->y;
    275 	}
    276 
    277 	if (pRADEONEnt->Controller[0]->enabled &&
    278 	    pRADEONEnt->Controller[1]->enabled) {
    279 	    int cursor_end, frame_end;
    280 
    281 	    cursor_end = x - xorigin + w;
    282 	    frame_end = crtc->x + mode->CrtcHDisplay;
    283 
    284 	    if (cursor_end >= frame_end) {
    285 		w = w - (cursor_end - frame_end);
    286 		if (!(frame_end & 0x7f))
    287 		    w--;
    288 	    } else {
    289 		if (!(cursor_end & 0x7f))
    290 		    w--;
    291 	    }
    292 	    if (w <= 0)
    293 		w = 1;
    294 	}
    295     }
    296 
    297     if (IS_DCE4_VARIANT) {
    298 	evergreen_lock_cursor(crtc, TRUE);
    299 	OUTREG(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16)
    300 	       | (yorigin ? 0 : y));
    301 	OUTREG(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
    302 	OUTREG(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
    303 	       ((w - 1) << 16) | (CURSOR_HEIGHT - 1));
    304 	evergreen_lock_cursor(crtc, FALSE);
    305     } else if (IS_AVIVO_VARIANT) {
    306 	avivo_lock_cursor(crtc, TRUE);
    307 	OUTREG(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16)
    308 	       | (yorigin ? 0 : y));
    309 	OUTREG(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
    310 	OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((w - 1) << 16) | (CURSOR_HEIGHT - 1));
    311 	avivo_lock_cursor(crtc, FALSE);
    312     } else {
    313 	if (mode->Flags & V_DBLSCAN)
    314 	    y *= 2;
    315 
    316 	if (crtc_id == 0) {
    317 	    OUTREG(RADEON_CUR_HORZ_VERT_OFF,  (RADEON_CUR_LOCK
    318 					       | (xorigin << 16)
    319 					       | yorigin));
    320 	    OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
    321 					       | ((xorigin ? 0 : x) << 16)
    322 					       | (yorigin ? 0 : y)));
    323 	    RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
    324 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
    325 	    OUTREG(RADEON_CUR_OFFSET,
    326 		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
    327 	} else if (crtc_id == 1) {
    328 	    OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
    329 						| (xorigin << 16)
    330 						| yorigin));
    331 	    OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
    332 						| ((xorigin ? 0 : x) << 16)
    333 						| (yorigin ? 0 : y)));
    334 	    RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
    335 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
    336 	    OUTREG(RADEON_CUR2_OFFSET,
    337 		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
    338 	}
    339     }
    340 }
    341 
    342 void
    343 radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
    344 {
    345     ScrnInfoPtr pScrn = crtc->scrn;
    346     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    347     RADEONInfoPtr info = RADEONPTR(pScrn);
    348     uint32_t *pixels = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset);
    349     int            pixel, i;
    350     CURSOR_SWAPPING_DECL_MMIO
    351 
    352     RADEONCTRACE(("RADEONSetCursorColors\n"));
    353 
    354 #ifdef ARGB_CURSOR
    355     /* Don't recolour cursors set with SetCursorARGB. */
    356     if (info->cursor_argb)
    357        return;
    358 #endif
    359 
    360     fg |= 0xff000000;
    361     bg |= 0xff000000;
    362 
    363     /* Don't recolour the image if we don't have to. */
    364     if (fg == info->cursor_fg && bg == info->cursor_bg)
    365        return;
    366 
    367     CURSOR_SWAPPING_START();
    368 
    369     /* Note: We assume that the pixels are either fully opaque or fully
    370      * transparent, so we won't premultiply them, and we can just
    371      * check for non-zero pixel values; those are either fg or bg
    372      */
    373     for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++)
    374        if ((pixel = *pixels))
    375            *pixels = (pixel == info->cursor_fg) ? fg : bg;
    376 
    377     CURSOR_SWAPPING_END();
    378     info->cursor_fg = fg;
    379     info->cursor_bg = bg;
    380 }
    381 
    382 #ifdef ARGB_CURSOR
    383 
    384 void
    385 radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
    386 {
    387     ScrnInfoPtr pScrn = crtc->scrn;
    388     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    389     RADEONInfoPtr  info = RADEONPTR(pScrn);
    390     CURSOR_SWAPPING_DECL_MMIO
    391     uint32_t *d = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset);
    392 
    393     RADEONCTRACE(("RADEONLoadCursorARGB\n"));
    394 
    395     info->cursor_argb = TRUE;
    396 
    397     CURSOR_SWAPPING_START();
    398 
    399     memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4);
    400 
    401     CURSOR_SWAPPING_END ();
    402 }
    403 
    404 #endif
    405 
    406 
    407 /* Initialize hardware cursor support. */
    408 Bool RADEONCursorInit(ScreenPtr pScreen)
    409 {
    410     ScrnInfoPtr        pScrn   = xf86ScreenToScrn(pScreen);
    411     RADEONInfoPtr      info    = RADEONPTR(pScrn);
    412     unsigned char     *RADEONMMIO = info->MMIO;
    413     xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    414     int                c;
    415 
    416     for (c = 0; c < xf86_config->num_crtc; c++) {
    417 	xf86CrtcPtr crtc = xf86_config->crtc[c];
    418 	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    419 
    420 	if (!info->useEXA) {
    421 	    int size_bytes  = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
    422 	    int align = IS_AVIVO_VARIANT ? 4096 : 256;
    423 
    424 	    radeon_crtc->cursor_offset =
    425 		radeon_legacy_allocate_memory(pScrn, &radeon_crtc->cursor_mem,
    426 				size_bytes, align, RADEON_GEM_DOMAIN_VRAM);
    427 
    428 	    if (radeon_crtc->cursor_offset == 0)
    429 		return FALSE;
    430 
    431 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    432 		       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
    433 		       (size_bytes * xf86_config->num_crtc) / 1024,
    434 		       c,
    435 		       (unsigned int)radeon_crtc->cursor_offset);
    436 	}
    437 	/* set the cursor mode the same on both crtcs to avoid corruption */
    438 	/* XXX check if this is needed on evergreen */
    439 	if (IS_AVIVO_VARIANT)
    440 	    OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
    441 		   (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
    442     }
    443 
    444     return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT,
    445 			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
    446 			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
    447 			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
    448 			       HARDWARE_CURSOR_ARGB));
    449 }
    450