1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3209ff23fSmrg * VA Linux Systems Inc., Fremont, California. 4209ff23fSmrg * 5209ff23fSmrg * All Rights Reserved. 6209ff23fSmrg * 7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining 8209ff23fSmrg * a copy of this software and associated documentation files (the 9209ff23fSmrg * "Software"), to deal in the Software without restriction, including 10209ff23fSmrg * without limitation on the rights to use, copy, modify, merge, 11209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software, 12209ff23fSmrg * and to permit persons to whom the Software is furnished to do so, 13209ff23fSmrg * subject to the following conditions: 14209ff23fSmrg * 15209ff23fSmrg * The above copyright notice and this permission notice (including the 16209ff23fSmrg * next paragraph) shall be included in all copies or substantial 17209ff23fSmrg * portions of the Software. 18209ff23fSmrg * 19209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22209ff23fSmrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26209ff23fSmrg * DEALINGS IN THE SOFTWARE. 27209ff23fSmrg */ 28209ff23fSmrg 29209ff23fSmrg#ifdef HAVE_CONFIG_H 30209ff23fSmrg#include "config.h" 31209ff23fSmrg#endif 32209ff23fSmrg 33209ff23fSmrg#define RADEONCTRACE(x) 34209ff23fSmrg/*#define RADEONCTRACE(x) RADEONTRACE(x) */ 35209ff23fSmrg 36209ff23fSmrg/* 37209ff23fSmrg * Authors: 38209ff23fSmrg * Kevin E. Martin <martin@xfree86.org> 39209ff23fSmrg * Rickard E. Faith <faith@valinux.com> 40209ff23fSmrg * 41209ff23fSmrg * References: 42209ff23fSmrg * 43209ff23fSmrg * !!!! FIXME !!!! 44209ff23fSmrg * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 45209ff23fSmrg * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 46209ff23fSmrg * 1999. 47209ff23fSmrg * 48209ff23fSmrg * RAGE 128 Software Development Manual (Technical Reference Manual P/N 49209ff23fSmrg * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 50209ff23fSmrg * 51209ff23fSmrg */ 52209ff23fSmrg 53209ff23fSmrg /* Driver data structures */ 54209ff23fSmrg#include "radeon.h" 55209ff23fSmrg#include "radeon_version.h" 56209ff23fSmrg#include "radeon_reg.h" 57209ff23fSmrg#include "radeon_macros.h" 58209ff23fSmrg 59209ff23fSmrg /* X and server generic header files */ 60209ff23fSmrg#include "xf86.h" 61209ff23fSmrg 62209ff23fSmrg#define CURSOR_WIDTH 64 63209ff23fSmrg#define CURSOR_HEIGHT 64 64209ff23fSmrg 65209ff23fSmrg/* 66209ff23fSmrg * The cursor bits are always 32bpp. On MSBFirst buses, 67209ff23fSmrg * configure byte swapping to swap 32 bit units when writing 68209ff23fSmrg * the cursor image. Byte swapping must always be returned 69209ff23fSmrg * to its previous value before returning. 70209ff23fSmrg */ 71209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 72209ff23fSmrg 73209ff23fSmrg#define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO; 74209ff23fSmrg#define CURSOR_SWAPPING_START() \ 75209ff23fSmrg do { \ 76486efd68Smrg if (info->ChipFamily < CHIP_FAMILY_R600) \ 77209ff23fSmrg OUTREG(RADEON_SURFACE_CNTL, \ 78209ff23fSmrg (info->ModeReg->surface_cntl | \ 79209ff23fSmrg RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \ 80209ff23fSmrg ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \ 81209ff23fSmrg } while (0) 82486efd68Smrg#define CURSOR_SWAPPING_END() \ 83486efd68Smrg do { \ 84486efd68Smrg if (info->ChipFamily < CHIP_FAMILY_R600) \ 85486efd68Smrg OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); \ 86486efd68Smrg } while (0) 87209ff23fSmrg#else 88209ff23fSmrg 89209ff23fSmrg#define CURSOR_SWAPPING_DECL_MMIO 90209ff23fSmrg#define CURSOR_SWAPPING_START() 91209ff23fSmrg#define CURSOR_SWAPPING_END() 92209ff23fSmrg 93209ff23fSmrg#endif 94209ff23fSmrg 95209ff23fSmrgstatic void 96209ff23fSmrgavivo_setup_cursor(xf86CrtcPtr crtc, Bool enable) 97209ff23fSmrg{ 98209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 99209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 100209ff23fSmrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 101209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 102209ff23fSmrg 103486efd68Smrg /* always use the same cursor mode even if the cursor is disabled, 104486efd68Smrg * otherwise you may end up with cursor curruption bands 105486efd68Smrg */ 106486efd68Smrg OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 107209ff23fSmrg 108209ff23fSmrg if (enable) { 10970cce690Smrg uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset; 110f1bc02b7Smrg if (info->ChipFamily >= CHIP_FAMILY_RV770) { 111f1bc02b7Smrg if (radeon_crtc->crtc_id) 11270cce690Smrg OUTREG(R700_D2CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf); 113f1bc02b7Smrg else 11470cce690Smrg OUTREG(R700_D1CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf); 115f1bc02b7Smrg } 116209ff23fSmrg OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 117209ff23fSmrg info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset); 118209ff23fSmrg OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 119209ff23fSmrg AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 120209ff23fSmrg } 121209ff23fSmrg} 122209ff23fSmrg 123209ff23fSmrgstatic void 124209ff23fSmrgavivo_lock_cursor(xf86CrtcPtr crtc, Bool lock) 125209ff23fSmrg{ 126209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 127209ff23fSmrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 128209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 129209ff23fSmrg uint32_t tmp; 130209ff23fSmrg 131209ff23fSmrg tmp = INREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); 132209ff23fSmrg 133209ff23fSmrg if (lock) 134209ff23fSmrg tmp |= AVIVO_D1CURSOR_UPDATE_LOCK; 135209ff23fSmrg else 136209ff23fSmrg tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK; 137209ff23fSmrg 138209ff23fSmrg OUTREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp); 139209ff23fSmrg} 140209ff23fSmrg 141f1bc02b7Smrgstatic void 142f1bc02b7Smrgevergreen_setup_cursor(xf86CrtcPtr crtc, Bool enable) 143f1bc02b7Smrg{ 144f1bc02b7Smrg ScrnInfoPtr pScrn = crtc->scrn; 145f1bc02b7Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 146f1bc02b7Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 147f1bc02b7Smrg unsigned char *RADEONMMIO = info->MMIO; 148f1bc02b7Smrg 149f1bc02b7Smrg /* always use the same cursor mode even if the cursor is disabled, 150f1bc02b7Smrg * otherwise you may end up with cursor curruption bands 151f1bc02b7Smrg */ 152f1bc02b7Smrg OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset, 153f1bc02b7Smrg EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); 154f1bc02b7Smrg 155f1bc02b7Smrg if (enable) { 15670cce690Smrg uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset; 15770cce690Smrg OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 15870cce690Smrg (location >> 32) & 0xf); 159f1bc02b7Smrg OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 16070cce690Smrg location & EVERGREEN_CUR_SURFACE_ADDRESS_MASK); 161f1bc02b7Smrg OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset, 162f1bc02b7Smrg EVERGREEN_CURSOR_EN | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); 163f1bc02b7Smrg } 164f1bc02b7Smrg} 165f1bc02b7Smrg 166f1bc02b7Smrgstatic void 167f1bc02b7Smrgevergreen_lock_cursor(xf86CrtcPtr crtc, Bool lock) 168f1bc02b7Smrg{ 169f1bc02b7Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 170f1bc02b7Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 171f1bc02b7Smrg unsigned char *RADEONMMIO = info->MMIO; 172f1bc02b7Smrg uint32_t tmp; 173f1bc02b7Smrg 174f1bc02b7Smrg tmp = INREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset); 175f1bc02b7Smrg 176f1bc02b7Smrg if (lock) 177f1bc02b7Smrg tmp |= EVERGREEN_CURSOR_UPDATE_LOCK; 178f1bc02b7Smrg else 179f1bc02b7Smrg tmp &= ~EVERGREEN_CURSOR_UPDATE_LOCK; 180f1bc02b7Smrg 181f1bc02b7Smrg OUTREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, tmp); 182f1bc02b7Smrg} 183f1bc02b7Smrg 184209ff23fSmrgvoid 185209ff23fSmrgradeon_crtc_show_cursor (xf86CrtcPtr crtc) 186209ff23fSmrg{ 187209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 188209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 189209ff23fSmrg int crtc_id = radeon_crtc->crtc_id; 190209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 191209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 192209ff23fSmrg 193f1bc02b7Smrg if (IS_DCE4_VARIANT) { 194f1bc02b7Smrg evergreen_lock_cursor(crtc, TRUE); 195f1bc02b7Smrg evergreen_setup_cursor(crtc, TRUE); 196f1bc02b7Smrg evergreen_lock_cursor(crtc, FALSE); 197f1bc02b7Smrg } else if (IS_AVIVO_VARIANT) { 198209ff23fSmrg avivo_lock_cursor(crtc, TRUE); 199209ff23fSmrg avivo_setup_cursor(crtc, TRUE); 200209ff23fSmrg avivo_lock_cursor(crtc, FALSE); 201209ff23fSmrg } else { 202209ff23fSmrg switch (crtc_id) { 203209ff23fSmrg case 0: 204209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); 205209ff23fSmrg break; 206209ff23fSmrg case 1: 207209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); 208209ff23fSmrg break; 209209ff23fSmrg default: 210209ff23fSmrg return; 211209ff23fSmrg } 212209ff23fSmrg 213f1bc02b7Smrg OUTREGP(RADEON_MM_DATA, RADEON_CRTC_CUR_EN | 2 << 20, 214209ff23fSmrg ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); 215209ff23fSmrg } 216209ff23fSmrg} 217209ff23fSmrg 218209ff23fSmrgvoid 219209ff23fSmrgradeon_crtc_hide_cursor (xf86CrtcPtr crtc) 220209ff23fSmrg{ 221209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 222209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 223209ff23fSmrg int crtc_id = radeon_crtc->crtc_id; 224209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 225209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 226209ff23fSmrg 227f1bc02b7Smrg if (IS_DCE4_VARIANT) { 228f1bc02b7Smrg evergreen_lock_cursor(crtc, TRUE); 229f1bc02b7Smrg evergreen_setup_cursor(crtc, FALSE); 23069d0ef43Smrg evergreen_lock_cursor(crtc, FALSE); 231f1bc02b7Smrg } else if (IS_AVIVO_VARIANT) { 232209ff23fSmrg avivo_lock_cursor(crtc, TRUE); 233209ff23fSmrg avivo_setup_cursor(crtc, FALSE); 234209ff23fSmrg avivo_lock_cursor(crtc, FALSE); 235209ff23fSmrg } else { 236209ff23fSmrg switch(crtc_id) { 237209ff23fSmrg case 0: 238209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); 239209ff23fSmrg break; 240209ff23fSmrg case 1: 241209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); 242209ff23fSmrg break; 243209ff23fSmrg default: 244209ff23fSmrg return; 245209ff23fSmrg } 246209ff23fSmrg 247209ff23fSmrg OUTREGP(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); 248209ff23fSmrg } 249209ff23fSmrg} 250209ff23fSmrg 251209ff23fSmrgvoid 252209ff23fSmrgradeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 253209ff23fSmrg{ 254209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 255486efd68Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 256209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 257209ff23fSmrg int crtc_id = radeon_crtc->crtc_id; 258209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 259209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 260209ff23fSmrg int xorigin = 0, yorigin = 0; 261209ff23fSmrg int stride = 256; 262209ff23fSmrg DisplayModePtr mode = &crtc->mode; 26370cce690Smrg int w = CURSOR_WIDTH; 264209ff23fSmrg 265209ff23fSmrg if (x < 0) xorigin = -x+1; 266209ff23fSmrg if (y < 0) yorigin = -y+1; 267209ff23fSmrg if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; 268209ff23fSmrg if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; 269209ff23fSmrg 27070cce690Smrg if (IS_AVIVO_VARIANT) { 271209ff23fSmrg /* avivo cursor spans the full fb width */ 272b7e1c893Smrg if (crtc->rotatedData == NULL) { 273b7e1c893Smrg x += crtc->x; 274b7e1c893Smrg y += crtc->y; 275b7e1c893Smrg } 276486efd68Smrg 277486efd68Smrg if (pRADEONEnt->Controller[0]->enabled && 278486efd68Smrg pRADEONEnt->Controller[1]->enabled) { 279486efd68Smrg int cursor_end, frame_end; 280486efd68Smrg 281486efd68Smrg cursor_end = x - xorigin + w; 282486efd68Smrg frame_end = crtc->x + mode->CrtcHDisplay; 283486efd68Smrg 284486efd68Smrg if (cursor_end >= frame_end) { 285486efd68Smrg w = w - (cursor_end - frame_end); 286486efd68Smrg if (!(frame_end & 0x7f)) 287486efd68Smrg w--; 288486efd68Smrg } else { 289486efd68Smrg if (!(cursor_end & 0x7f)) 290486efd68Smrg w--; 291486efd68Smrg } 292486efd68Smrg if (w <= 0) 293486efd68Smrg w = 1; 294486efd68Smrg } 29570cce690Smrg } 296486efd68Smrg 29770cce690Smrg if (IS_DCE4_VARIANT) { 29870cce690Smrg evergreen_lock_cursor(crtc, TRUE); 29970cce690Smrg OUTREG(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16) 30070cce690Smrg | (yorigin ? 0 : y)); 30170cce690Smrg OUTREG(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); 30270cce690Smrg OUTREG(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, 30370cce690Smrg ((w - 1) << 16) | (CURSOR_HEIGHT - 1)); 30470cce690Smrg evergreen_lock_cursor(crtc, FALSE); 30570cce690Smrg } else if (IS_AVIVO_VARIANT) { 306209ff23fSmrg avivo_lock_cursor(crtc, TRUE); 307209ff23fSmrg OUTREG(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16) 308209ff23fSmrg | (yorigin ? 0 : y)); 309209ff23fSmrg OUTREG(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); 310486efd68Smrg OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((w - 1) << 16) | (CURSOR_HEIGHT - 1)); 311209ff23fSmrg avivo_lock_cursor(crtc, FALSE); 312209ff23fSmrg } else { 313b7e1c893Smrg if (mode->Flags & V_DBLSCAN) 314b7e1c893Smrg y *= 2; 315b7e1c893Smrg 316209ff23fSmrg if (crtc_id == 0) { 317209ff23fSmrg OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK 318209ff23fSmrg | (xorigin << 16) 319209ff23fSmrg | yorigin)); 320209ff23fSmrg OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK 321209ff23fSmrg | ((xorigin ? 0 : x) << 16) 322209ff23fSmrg | (yorigin ? 0 : y))); 323209ff23fSmrg RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", 324209ff23fSmrg radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); 325209ff23fSmrg OUTREG(RADEON_CUR_OFFSET, 326209ff23fSmrg radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); 327209ff23fSmrg } else if (crtc_id == 1) { 328209ff23fSmrg OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK 329209ff23fSmrg | (xorigin << 16) 330209ff23fSmrg | yorigin)); 331209ff23fSmrg OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK 332209ff23fSmrg | ((xorigin ? 0 : x) << 16) 333209ff23fSmrg | (yorigin ? 0 : y))); 334209ff23fSmrg RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", 335209ff23fSmrg radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); 336209ff23fSmrg OUTREG(RADEON_CUR2_OFFSET, 337209ff23fSmrg radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); 338209ff23fSmrg } 339209ff23fSmrg } 340209ff23fSmrg} 341209ff23fSmrg 342209ff23fSmrgvoid 343209ff23fSmrgradeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 344209ff23fSmrg{ 345209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 346209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 347209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 34851b40f85Smrg uint32_t *pixels = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset); 349209ff23fSmrg int pixel, i; 350209ff23fSmrg CURSOR_SWAPPING_DECL_MMIO 351209ff23fSmrg 352209ff23fSmrg RADEONCTRACE(("RADEONSetCursorColors\n")); 353209ff23fSmrg 354209ff23fSmrg#ifdef ARGB_CURSOR 355209ff23fSmrg /* Don't recolour cursors set with SetCursorARGB. */ 356209ff23fSmrg if (info->cursor_argb) 357209ff23fSmrg return; 358209ff23fSmrg#endif 359209ff23fSmrg 360209ff23fSmrg fg |= 0xff000000; 361209ff23fSmrg bg |= 0xff000000; 362209ff23fSmrg 363209ff23fSmrg /* Don't recolour the image if we don't have to. */ 364209ff23fSmrg if (fg == info->cursor_fg && bg == info->cursor_bg) 365209ff23fSmrg return; 366209ff23fSmrg 367209ff23fSmrg CURSOR_SWAPPING_START(); 368209ff23fSmrg 369209ff23fSmrg /* Note: We assume that the pixels are either fully opaque or fully 370209ff23fSmrg * transparent, so we won't premultiply them, and we can just 371209ff23fSmrg * check for non-zero pixel values; those are either fg or bg 372209ff23fSmrg */ 373209ff23fSmrg for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) 374209ff23fSmrg if ((pixel = *pixels)) 375209ff23fSmrg *pixels = (pixel == info->cursor_fg) ? fg : bg; 376209ff23fSmrg 377209ff23fSmrg CURSOR_SWAPPING_END(); 378209ff23fSmrg info->cursor_fg = fg; 379209ff23fSmrg info->cursor_bg = bg; 380209ff23fSmrg} 381209ff23fSmrg 382209ff23fSmrg#ifdef ARGB_CURSOR 383209ff23fSmrg 384209ff23fSmrgvoid 385209ff23fSmrgradeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 386209ff23fSmrg{ 387209ff23fSmrg ScrnInfoPtr pScrn = crtc->scrn; 388209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 389209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 390209ff23fSmrg CURSOR_SWAPPING_DECL_MMIO 39151b40f85Smrg uint32_t *d = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset); 392209ff23fSmrg 393209ff23fSmrg RADEONCTRACE(("RADEONLoadCursorARGB\n")); 394209ff23fSmrg 395209ff23fSmrg info->cursor_argb = TRUE; 396209ff23fSmrg 397209ff23fSmrg CURSOR_SWAPPING_START(); 398209ff23fSmrg 399209ff23fSmrg memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4); 400209ff23fSmrg 401209ff23fSmrg CURSOR_SWAPPING_END (); 402209ff23fSmrg} 403209ff23fSmrg 404209ff23fSmrg#endif 405209ff23fSmrg 406209ff23fSmrg 407209ff23fSmrg/* Initialize hardware cursor support. */ 408209ff23fSmrgBool RADEONCursorInit(ScreenPtr pScreen) 409209ff23fSmrg{ 410c135ecebSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 411209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 412486efd68Smrg unsigned char *RADEONMMIO = info->MMIO; 413209ff23fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 414209ff23fSmrg int c; 415209ff23fSmrg 416486efd68Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 417486efd68Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 418486efd68Smrg RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 419209ff23fSmrg 420486efd68Smrg if (!info->useEXA) { 421486efd68Smrg int size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; 422486efd68Smrg int align = IS_AVIVO_VARIANT ? 4096 : 256; 423209ff23fSmrg 424b7e1c893Smrg radeon_crtc->cursor_offset = 425f1bc02b7Smrg radeon_legacy_allocate_memory(pScrn, &radeon_crtc->cursor_mem, 426f1bc02b7Smrg size_bytes, align, RADEON_GEM_DOMAIN_VRAM); 427b7e1c893Smrg 428b7e1c893Smrg if (radeon_crtc->cursor_offset == 0) 429b7e1c893Smrg return FALSE; 430b7e1c893Smrg 431b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 432b7e1c893Smrg "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 433b7e1c893Smrg (size_bytes * xf86_config->num_crtc) / 1024, 434b7e1c893Smrg c, 435b7e1c893Smrg (unsigned int)radeon_crtc->cursor_offset); 436209ff23fSmrg } 437486efd68Smrg /* set the cursor mode the same on both crtcs to avoid corruption */ 438f1bc02b7Smrg /* XXX check if this is needed on evergreen */ 439486efd68Smrg if (IS_AVIVO_VARIANT) 440486efd68Smrg OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 441486efd68Smrg (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 442209ff23fSmrg } 443209ff23fSmrg 444209ff23fSmrg return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, 445209ff23fSmrg (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 446209ff23fSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 447209ff23fSmrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 448209ff23fSmrg HARDWARE_CURSOR_ARGB)); 449209ff23fSmrg} 450