radeon_cursor.c revision b7e1c893
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 OUTREG(RADEON_SURFACE_CNTL, \ 77 (info->ModeReg->surface_cntl | \ 78 RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \ 79 ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \ 80 } while (0) 81#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, \ 82 info->ModeReg->surface_cntl)) 83 84#else 85 86#define CURSOR_SWAPPING_DECL_MMIO 87#define CURSOR_SWAPPING_START() 88#define CURSOR_SWAPPING_END() 89 90#endif 91 92static void 93avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable) 94{ 95 ScrnInfoPtr pScrn = crtc->scrn; 96 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 97 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 98 unsigned char *RADEONMMIO = info->MMIO; 99 100 OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); 101 102 if (enable) { 103 OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 104 info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset); 105 OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, 106 ((CURSOR_WIDTH - 1) << 16) | (CURSOR_HEIGHT - 1)); 107 OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 108 AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 109 } 110} 111 112static void 113avivo_lock_cursor(xf86CrtcPtr crtc, Bool lock) 114{ 115 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 116 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 117 unsigned char *RADEONMMIO = info->MMIO; 118 uint32_t tmp; 119 120 tmp = INREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); 121 122 if (lock) 123 tmp |= AVIVO_D1CURSOR_UPDATE_LOCK; 124 else 125 tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK; 126 127 OUTREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp); 128} 129 130void 131radeon_crtc_show_cursor (xf86CrtcPtr crtc) 132{ 133 ScrnInfoPtr pScrn = crtc->scrn; 134 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 135 int crtc_id = radeon_crtc->crtc_id; 136 RADEONInfoPtr info = RADEONPTR(pScrn); 137 unsigned char *RADEONMMIO = info->MMIO; 138 139 if (IS_AVIVO_VARIANT) { 140 avivo_lock_cursor(crtc, TRUE); 141 OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 142 INREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset) 143 | AVIVO_D1CURSOR_EN); 144 avivo_setup_cursor(crtc, TRUE); 145 avivo_lock_cursor(crtc, FALSE); 146 } else { 147 switch (crtc_id) { 148 case 0: 149 OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); 150 break; 151 case 1: 152 OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); 153 break; 154 default: 155 return; 156 } 157 158 OUTREGP(RADEON_MM_DATA, RADEON_CRTC_CUR_EN | 2 << 20, 159 ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); 160 } 161} 162 163void 164radeon_crtc_hide_cursor (xf86CrtcPtr crtc) 165{ 166 ScrnInfoPtr pScrn = crtc->scrn; 167 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 168 int crtc_id = radeon_crtc->crtc_id; 169 RADEONInfoPtr info = RADEONPTR(pScrn); 170 unsigned char *RADEONMMIO = info->MMIO; 171 172 if (IS_AVIVO_VARIANT) { 173 avivo_lock_cursor(crtc, TRUE); 174 OUTREG(AVIVO_D1CUR_CONTROL+ radeon_crtc->crtc_offset, 175 INREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset) 176 & ~(AVIVO_D1CURSOR_EN)); 177 avivo_setup_cursor(crtc, FALSE); 178 avivo_lock_cursor(crtc, FALSE); 179 } else { 180 switch(crtc_id) { 181 case 0: 182 OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); 183 break; 184 case 1: 185 OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); 186 break; 187 default: 188 return; 189 } 190 191 OUTREGP(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); 192 } 193} 194 195void 196radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 197{ 198 ScrnInfoPtr pScrn = crtc->scrn; 199 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 200 int crtc_id = radeon_crtc->crtc_id; 201 RADEONInfoPtr info = RADEONPTR(pScrn); 202 unsigned char *RADEONMMIO = info->MMIO; 203 int xorigin = 0, yorigin = 0; 204 int stride = 256; 205 DisplayModePtr mode = &crtc->mode; 206 207 if (x < 0) xorigin = -x+1; 208 if (y < 0) yorigin = -y+1; 209 if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; 210 if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; 211 212 if (IS_AVIVO_VARIANT) { 213 /* avivo cursor spans the full fb width */ 214 if (crtc->rotatedData == NULL) { 215 x += crtc->x; 216 y += crtc->y; 217 } 218 avivo_lock_cursor(crtc, TRUE); 219 OUTREG(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16) 220 | (yorigin ? 0 : y)); 221 OUTREG(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); 222 avivo_lock_cursor(crtc, FALSE); 223 } else { 224 if (mode->Flags & V_DBLSCAN) 225 y *= 2; 226 227 if (crtc_id == 0) { 228 OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK 229 | (xorigin << 16) 230 | yorigin)); 231 OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK 232 | ((xorigin ? 0 : x) << 16) 233 | (yorigin ? 0 : y))); 234 RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", 235 radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); 236 OUTREG(RADEON_CUR_OFFSET, 237 radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); 238 } else if (crtc_id == 1) { 239 OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK 240 | (xorigin << 16) 241 | yorigin)); 242 OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK 243 | ((xorigin ? 0 : x) << 16) 244 | (yorigin ? 0 : y))); 245 RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", 246 radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); 247 OUTREG(RADEON_CUR2_OFFSET, 248 radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); 249 } 250 } 251} 252 253void 254radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 255{ 256 ScrnInfoPtr pScrn = crtc->scrn; 257 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 258 RADEONInfoPtr info = RADEONPTR(pScrn); 259 uint32_t *pixels = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); 260 int pixel, i; 261 CURSOR_SWAPPING_DECL_MMIO 262 263 RADEONCTRACE(("RADEONSetCursorColors\n")); 264 265#ifdef ARGB_CURSOR 266 /* Don't recolour cursors set with SetCursorARGB. */ 267 if (info->cursor_argb) 268 return; 269#endif 270 271 fg |= 0xff000000; 272 bg |= 0xff000000; 273 274 /* Don't recolour the image if we don't have to. */ 275 if (fg == info->cursor_fg && bg == info->cursor_bg) 276 return; 277 278 CURSOR_SWAPPING_START(); 279 280 /* Note: We assume that the pixels are either fully opaque or fully 281 * transparent, so we won't premultiply them, and we can just 282 * check for non-zero pixel values; those are either fg or bg 283 */ 284 for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) 285 if ((pixel = *pixels)) 286 *pixels = (pixel == info->cursor_fg) ? fg : bg; 287 288 CURSOR_SWAPPING_END(); 289 info->cursor_fg = fg; 290 info->cursor_bg = bg; 291} 292 293#ifdef ARGB_CURSOR 294 295void 296radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 297{ 298 ScrnInfoPtr pScrn = crtc->scrn; 299 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 300 RADEONInfoPtr info = RADEONPTR(pScrn); 301 CURSOR_SWAPPING_DECL_MMIO 302 uint32_t *d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); 303 304 RADEONCTRACE(("RADEONLoadCursorARGB\n")); 305 306 info->cursor_argb = TRUE; 307 308 CURSOR_SWAPPING_START(); 309 310 memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4); 311 312 CURSOR_SWAPPING_END (); 313} 314 315#endif 316 317 318/* Initialize hardware cursor support. */ 319Bool RADEONCursorInit(ScreenPtr pScreen) 320{ 321 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 322 RADEONInfoPtr info = RADEONPTR(pScrn); 323 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 324 int width; 325 int width_bytes; 326 int height; 327 int size_bytes; 328 int c; 329 330 size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; 331 width = pScrn->displayWidth; 332 width_bytes = width * (pScrn->bitsPerPixel / 8); 333 height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; 334 int align = IS_AVIVO_VARIANT ? 4096 : 256; 335 336 if (!info->useEXA) { 337 for (c = 0; c < xf86_config->num_crtc; c++) { 338 xf86CrtcPtr crtc = xf86_config->crtc[c]; 339 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 340 341 radeon_crtc->cursor_offset = 342 radeon_legacy_allocate_memory(pScrn, &radeon_crtc->cursor_mem, size_bytes, align); 343 344 if (radeon_crtc->cursor_offset == 0) 345 return FALSE; 346 347 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 348 "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 349 (size_bytes * xf86_config->num_crtc) / 1024, 350 c, 351 (unsigned int)radeon_crtc->cursor_offset); 352 } 353 } 354 355 return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, 356 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 357 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 358 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 359 HARDWARE_CURSOR_ARGB)); 360} 361