/* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /* * Authors: * Rickard E. Faith * Kevin E. Martin * * References: * * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April * 1999. * * RAGE 128 Software Development Manual (Technical Reference Manual P/N * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Driver data structures */ #include "r128.h" #include "r128_reg.h" /* X and server generic header files */ #include "xf86.h" /* Because for EXA we need to use a different allocator */ #ifdef USE_EXA #include "exa.h" #endif #define CURSOR_WIDTH 64 #define CURSOR_HEIGHT 64 void r128_crtc_show_cursor(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; R128CrtcPrivatePtr r128_crtc = crtc->driver_private; R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int crtc_id = r128_crtc->crtc_id; switch (crtc_id) { case 0: OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); break; case 1: OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, ~R128_CRTC2_CUR_EN); break; default: return; } } void r128_crtc_hide_cursor(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; R128CrtcPrivatePtr r128_crtc = crtc->driver_private; R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int crtc_id = r128_crtc->crtc_id; switch (crtc_id) { case 0: OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); break; case 1: OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); break; default: return; } } void r128_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) { ScrnInfoPtr pScrn = crtc->scrn; R128CrtcPrivatePtr r128_crtc = crtc->driver_private; R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int crtc_id = r128_crtc->crtc_id; switch (crtc_id) { case 0: OUTREG(R128_CUR_CLR0, bg); OUTREG(R128_CUR_CLR1, fg); break; case 1: OUTREG(R128_CUR2_CLR0, bg); OUTREG(R128_CUR2_CLR1, fg); break; default: return; } } void r128_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) { ScrnInfoPtr pScrn = crtc->scrn; R128InfoPtr info = R128PTR(pScrn); R128CrtcPrivatePtr r128_crtc = crtc->driver_private; unsigned char *R128MMIO = info->MMIO; int crtc_id = r128_crtc->crtc_id; int xorigin = 0, yorigin = 0; DisplayModePtr mode = &crtc->mode; if (x < 0) xorigin = -x + 1; if (y < 0) yorigin = -y + 1; if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; if (mode->Flags & V_INTERLACE) y /= 2; else if (mode->Flags & V_DBLSCAN) y *= 2; if(crtc_id == 0) { OUTREG(R128_CUR_HORZ_VERT_OFF, (R128_CUR_LOCK | (xorigin << 16) | yorigin)); OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); OUTREG(R128_CUR_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); } else if (crtc_id == 1) { OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK | (xorigin << 16) | yorigin)); OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); OUTREG(R128_CUR2_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); } } void r128_crtc_load_cursor_image(xf86CrtcPtr crtc, unsigned char *src) { ScrnInfoPtr pScrn = crtc->scrn; R128CrtcPrivatePtr r128_crtc = crtc->driver_private; int crtc_id = r128_crtc->crtc_id; R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; uint32_t save1 = 0; uint32_t save2 = 0; if (crtc_id == 0) { save1 = INREG(R128_CRTC_GEN_CNTL); OUTREG(R128_CRTC_GEN_CNTL, save1 & (uint32_t)~R128_CRTC_CUR_EN); } else if (crtc_id == 1) { save2 = INREG(R128_CRTC2_GEN_CNTL); OUTREG(R128_CRTC2_GEN_CNTL, save2 & (uint32_t)~R128_CRTC2_CUR_EN); } #if X_BYTE_ORDER == X_BIG_ENDIAN if (info->CurrentLayout.pixel_bytes == 4 || info->CurrentLayout.pixel_bytes == 3) R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_32BPP_SWAP); else if (info->CurrentLayout.pixel_bytes == 2) R128CopySwap(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, CURSOR_WIDTH * CURSOR_HEIGHT / 4, APER_0_BIG_ENDIAN_16BPP_SWAP); else #endif memcpy(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset, src, CURSOR_WIDTH * CURSOR_HEIGHT / 4); if (crtc_id == 0) OUTREG(R128_CRTC_GEN_CNTL, save1); else OUTREG(R128_CRTC2_GEN_CNTL, save2); } /* Initialize hardware cursor support. */ Bool R128CursorInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); R128InfoPtr info = R128PTR(pScrn); FBAreaPtr fbarea = NULL; #ifdef USE_EXA ExaOffscreenArea* osArea = NULL; #else void* osArea = NULL; #endif xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); uint32_t cursor_offset = 0; int cpp = info->CurrentLayout.pixel_bytes; int width; int width_bytes; int height; int size; int size_bytes; int c; size = CURSOR_WIDTH * CURSOR_HEIGHT / 4; size_bytes = size * 2; width = pScrn->displayWidth; width_bytes = width * (pScrn->bitsPerPixel / 8); height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; if(!info->useEXA) { fbarea = xf86AllocateOffscreenArea(pScreen, width, height, 16, NULL, NULL, NULL); if (fbarea) cursor_offset = R128_ALIGN((fbarea->box.x1 + width * fbarea->box.y1) * cpp, 16); } #ifdef USE_EXA else { osArea = exaOffscreenAlloc(pScreen, width * height, 16, TRUE, NULL, NULL); if (osArea) cursor_offset = osArea->offset; } #endif if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Hardware cursor disabled" " due to insufficient offscreen memory\n"); return FALSE; } else { for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; R128CrtcPrivatePtr r128_crtc = crtc->driver_private; r128_crtc->cursor_offset = cursor_offset + (c * size); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use %d kb for hardware cursor %d at offset 0x%08x\n", (size_bytes * xf86_config->num_crtc) / 1024, c, (unsigned int)r128_crtc->cursor_offset); } } return xf86_cursors_init(pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | HARDWARE_CURSOR_SHOW_TRANSPARENT | HARDWARE_CURSOR_UPDATE_UNHIDDEN | #if X_BYTE_ORDER == X_LITTLE_ENDIAN HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | #endif HARDWARE_CURSOR_INVERT_MASK | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)); }