radeon_cursor.c revision 70cce690
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@xfree86.org> 39 * Rickard E. Faith <faith@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 95static void 96avivo_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 123static void 124avivo_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 141static void 142evergreen_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 166static void 167evergreen_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 184void 185radeon_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 218void 219radeon_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 251void 252radeon_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 342void 343radeon_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 384void 385radeon_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. */ 408Bool RADEONCursorInit(ScreenPtr pScreen) 409{ 410 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 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