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@valinux.com> 33 * Kevin E. Martin <martin@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 65void 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 85void 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 105void 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 127void 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 159void 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. */ 196Bool 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