r128_cursor.c revision e3d74329
1c582b7e3Smrg/* 2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 3c582b7e3Smrg * Precision Insight, Inc., Cedar Park, Texas, and 4c582b7e3Smrg * VA Linux Systems Inc., Fremont, California. 5c582b7e3Smrg * 6c582b7e3Smrg * All Rights Reserved. 7c582b7e3Smrg * 8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining 9c582b7e3Smrg * a copy of this software and associated documentation files (the 10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including 11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge, 12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so, 14c582b7e3Smrg * subject to the following conditions: 15c582b7e3Smrg * 16c582b7e3Smrg * The above copyright notice and this permission notice (including the 17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial 18c582b7e3Smrg * portions of the Software. 19c582b7e3Smrg * 20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23c582b7e3Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX 24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE. 28c582b7e3Smrg */ 29c582b7e3Smrg 30c582b7e3Smrg/* 31c582b7e3Smrg * Authors: 32c582b7e3Smrg * Rickard E. Faith <faith@valinux.com> 33c582b7e3Smrg * Kevin E. Martin <martin@valinux.com> 34c582b7e3Smrg * 35c582b7e3Smrg * References: 36c582b7e3Smrg * 37c582b7e3Smrg * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 38c582b7e3Smrg * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 39c582b7e3Smrg * 1999. 40c582b7e3Smrg * 41c582b7e3Smrg * RAGE 128 Software Development Manual (Technical Reference Manual P/N 42c582b7e3Smrg * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 43c582b7e3Smrg * 44c582b7e3Smrg */ 45c582b7e3Smrg 46c582b7e3Smrg#ifdef HAVE_CONFIG_H 47c582b7e3Smrg#include "config.h" 48c582b7e3Smrg#endif 49c582b7e3Smrg 50c582b7e3Smrg /* Driver data structures */ 51c582b7e3Smrg#include "r128.h" 52c582b7e3Smrg#include "r128_reg.h" 53c582b7e3Smrg 54c582b7e3Smrg /* X and server generic header files */ 55c582b7e3Smrg#include "xf86.h" 56c582b7e3Smrg 5742a55b46Smrg /* Because for EXA we need to use a different allocator */ 5842a55b46Smrg#ifdef USE_EXA 5942a55b46Smrg#include "exa.h" 6042a55b46Smrg#endif 6142a55b46Smrg 62e3d74329Smrg#define CURSOR_WIDTH 64 63e3d74329Smrg#define CURSOR_HEIGHT 64 64c582b7e3Smrg 65e3d74329Smrgvoid r128_crtc_show_cursor(xf86CrtcPtr crtc) 66c582b7e3Smrg{ 67e3d74329Smrg ScrnInfoPtr pScrn = crtc->scrn; 68e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 69e3d74329Smrg R128InfoPtr info = R128PTR(pScrn); 70c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 71e3d74329Smrg int crtc_id = r128_crtc->crtc_id; 72e3d74329Smrg 73e3d74329Smrg switch (crtc_id) { 74e3d74329Smrg case 0: 75e3d74329Smrg OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); 76e3d74329Smrg break; 77e3d74329Smrg case 1: 78e3d74329Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, ~R128_CRTC2_CUR_EN); 79e3d74329Smrg break; 80e3d74329Smrg default: 81e3d74329Smrg return; 82c582b7e3Smrg } 83c582b7e3Smrg} 84c582b7e3Smrg 85e3d74329Smrgvoid r128_crtc_hide_cursor(xf86CrtcPtr crtc) 86c582b7e3Smrg{ 87e3d74329Smrg ScrnInfoPtr pScrn = crtc->scrn; 88e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 89e3d74329Smrg R128InfoPtr info = R128PTR(pScrn); 90e3d74329Smrg unsigned char *R128MMIO = info->MMIO; 91e3d74329Smrg int crtc_id = r128_crtc->crtc_id; 92c582b7e3Smrg 93e3d74329Smrg switch (crtc_id) { 94e3d74329Smrg case 0: 95e3d74329Smrg OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); 96e3d74329Smrg break; 97e3d74329Smrg case 1: 98e3d74329Smrg OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); 99e3d74329Smrg break; 100e3d74329Smrg default: 101e3d74329Smrg return; 102c582b7e3Smrg } 103c582b7e3Smrg} 104c582b7e3Smrg 105e3d74329Smrgvoid r128_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 106c582b7e3Smrg{ 107e3d74329Smrg ScrnInfoPtr pScrn = crtc->scrn; 108e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 109e3d74329Smrg R128InfoPtr info = R128PTR(pScrn); 110c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 111e3d74329Smrg int crtc_id = r128_crtc->crtc_id; 112e3d74329Smrg 113e3d74329Smrg switch (crtc_id) { 114e3d74329Smrg case 0: 115e3d74329Smrg OUTREG(R128_CUR_CLR0, bg); 116e3d74329Smrg OUTREG(R128_CUR_CLR1, fg); 117e3d74329Smrg break; 118e3d74329Smrg case 1: 119e3d74329Smrg OUTREG(R128_CUR2_CLR0, bg); 120e3d74329Smrg OUTREG(R128_CUR2_CLR1, fg); 121e3d74329Smrg break; 122c582b7e3Smrg default: 123e3d74329Smrg return; 124c582b7e3Smrg } 125c582b7e3Smrg} 126c582b7e3Smrg 127e3d74329Smrgvoid r128_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 128c582b7e3Smrg{ 129e3d74329Smrg ScrnInfoPtr pScrn = crtc->scrn; 130e3d74329Smrg R128InfoPtr info = R128PTR(pScrn); 131e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 132e3d74329Smrg unsigned char *R128MMIO = info->MMIO; 133e3d74329Smrg int crtc_id = r128_crtc->crtc_id; 134e3d74329Smrg 135e3d74329Smrg int xorigin = 0, yorigin = 0; 136e3d74329Smrg DisplayModePtr mode = &crtc->mode; 137e3d74329Smrg 138e3d74329Smrg if (x < 0) xorigin = -x + 1; 139e3d74329Smrg if (y < 0) yorigin = -y + 1; 140e3d74329Smrg if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; 141e3d74329Smrg if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; 142e3d74329Smrg 143e3d74329Smrg if (mode->Flags & V_INTERLACE) 144e3d74329Smrg y /= 2; 145e3d74329Smrg else if (mode->Flags & V_DBLSCAN) 146e3d74329Smrg y *= 2; 147e3d74329Smrg 148e3d74329Smrg if(crtc_id == 0) { 149e3d74329Smrg OUTREG(R128_CUR_HORZ_VERT_OFF, (R128_CUR_LOCK | (xorigin << 16) | yorigin)); 150e3d74329Smrg OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); 151e3d74329Smrg OUTREG(R128_CUR_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); 152e3d74329Smrg } else if (crtc_id == 1) { 153e3d74329Smrg OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK | (xorigin << 16) | yorigin)); 154e3d74329Smrg OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); 155e3d74329Smrg OUTREG(R128_CUR2_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); 156e3d74329Smrg } 157c582b7e3Smrg} 158c582b7e3Smrg 159e3d74329Smrgvoid r128_crtc_load_cursor_image(xf86CrtcPtr crtc, unsigned char *src) 160c582b7e3Smrg{ 161e3d74329Smrg ScrnInfoPtr pScrn = crtc->scrn; 162e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 163e3d74329Smrg int crtc_id = r128_crtc->crtc_id; 164e3d74329Smrg 165c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 166c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 167e3d74329Smrg uint32_t save1 = 0; 168e3d74329Smrg uint32_t save2 = 0; 169e3d74329Smrg 170e3d74329Smrg if (crtc_id == 0) { 171e3d74329Smrg save1 = INREG(R128_CRTC_GEN_CNTL); 172e3d74329Smrg OUTREG(R128_CRTC_GEN_CNTL, save1 & (uint32_t)~R128_CRTC_CUR_EN); 173e3d74329Smrg } else if (crtc_id == 1) { 174e3d74329Smrg save2 = INREG(R128_CRTC2_GEN_CNTL); 175e3d74329Smrg OUTREG(R128_CRTC2_GEN_CNTL, save2 & (uint32_t)~R128_CRTC2_CUR_EN); 176c582b7e3Smrg } 177c582b7e3Smrg 178e3d74329Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 179e3d74329Smrg if (info->CurrentLayout.pixel_bytes == 4 || info->CurrentLayout.pixel_bytes == 3) 180e3d74329Smrg R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, 181e3d74329Smrg CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_32BPP_SWAP); 182e3d74329Smrg else if (info->CurrentLayout.pixel_bytes == 2) 183e3d74329Smrg R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, 184e3d74329Smrg CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_16BPP_SWAP); 185e3d74329Smrg else 186e3d74329Smrg#endif 187e3d74329Smrg memcpy(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, CURSOR_WIDTH * CURSOR_HEIGHT / 4); 188c582b7e3Smrg 189e3d74329Smrg if (crtc_id == 0) 190e3d74329Smrg OUTREG(R128_CRTC_GEN_CNTL, save1); 191e3d74329Smrg else 192e3d74329Smrg OUTREG(R128_CRTC2_GEN_CNTL, save2); 193c582b7e3Smrg} 194c582b7e3Smrg 195c582b7e3Smrg/* Initialize hardware cursor support. */ 196c582b7e3SmrgBool R128CursorInit(ScreenPtr pScreen) 197c582b7e3Smrg{ 19842a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 199c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 20042a55b46Smrg FBAreaPtr fbarea = NULL; 20142a55b46Smrg#ifdef USE_EXA 20242a55b46Smrg ExaOffscreenArea* osArea = NULL; 20342a55b46Smrg#else 20442a55b46Smrg void* osArea = NULL; 20542a55b46Smrg#endif 206e3d74329Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 207e3d74329Smrg uint32_t cursor_offset = 0; 208e3d74329Smrg int cpp = info->CurrentLayout.pixel_bytes; 209c582b7e3Smrg int width; 210e3d74329Smrg int width_bytes; 211c582b7e3Smrg int height; 212c582b7e3Smrg int size; 213e3d74329Smrg int size_bytes; 214e3d74329Smrg int c; 215c582b7e3Smrg 216e3d74329Smrg size = CURSOR_WIDTH * CURSOR_HEIGHT / 4; 217e3d74329Smrg size_bytes = size * 2; 218c582b7e3Smrg width = pScrn->displayWidth; 219e3d74329Smrg width_bytes = width * (pScrn->bitsPerPixel / 8); 220e3d74329Smrg height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; 22142a55b46Smrg 22242a55b46Smrg if(!info->useEXA) { 22342a55b46Smrg fbarea = xf86AllocateOffscreenArea(pScreen, width, height, 22442a55b46Smrg 16, NULL, NULL, NULL); 22542a55b46Smrg 226e3d74329Smrg if (fbarea) 227e3d74329Smrg cursor_offset = R128_ALIGN((fbarea->box.x1 + width * fbarea->box.y1) * cpp, 16); 22842a55b46Smrg } 22942a55b46Smrg#ifdef USE_EXA 23042a55b46Smrg else { 23142a55b46Smrg osArea = exaOffscreenAlloc(pScreen, width * height, 16, 23242a55b46Smrg TRUE, NULL, NULL); 23342a55b46Smrg 234e3d74329Smrg if (osArea) 235e3d74329Smrg cursor_offset = osArea->offset; 23642a55b46Smrg } 23742a55b46Smrg#endif 23842a55b46Smrg 23942a55b46Smrg if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) { 240c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 241c582b7e3Smrg "Hardware cursor disabled" 242c582b7e3Smrg " due to insufficient offscreen memory\n"); 243e3d74329Smrg return FALSE; 244e3d74329Smrg } else { 245e3d74329Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 246e3d74329Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 247e3d74329Smrg R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 248e3d74329Smrg 249e3d74329Smrg r128_crtc->cursor_offset = cursor_offset + (c * size); 250e3d74329Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 251e3d74329Smrg "Will use %d kb for hardware cursor %d at offset 0x%08x\n", 252e3d74329Smrg (size_bytes * xf86_config->num_crtc) / 1024, c, 253e3d74329Smrg (unsigned int)r128_crtc->cursor_offset); 254e3d74329Smrg } 255c582b7e3Smrg } 256c582b7e3Smrg 257e3d74329Smrg return xf86_cursors_init(pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, 258e3d74329Smrg (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 259e3d74329Smrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 260e3d74329Smrg HARDWARE_CURSOR_SHOW_TRANSPARENT | 261e3d74329Smrg HARDWARE_CURSOR_UPDATE_UNHIDDEN | 262e3d74329Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 263e3d74329Smrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 264e3d74329Smrg#endif 265e3d74329Smrg HARDWARE_CURSOR_INVERT_MASK | 266e3d74329Smrg HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 267e3d74329Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)); 268c582b7e3Smrg} 269