i830_cursor.c revision fa225cbc
1/* -*- c-basic-offset: 4 -*- */ 2/************************************************************************** 3 4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5Copyright © 2002 David Dawes 6All Rights Reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a 9copy of this software and associated documentation files (the 10"Software"), to deal in the Software without restriction, including 11without limitation the rights to use, copy, modify, merge, publish, 12distribute, sub license, and/or sell copies of the Software, and to 13permit persons to whom the Software is furnished to do so, subject to 14the following conditions: 15 16The above copyright notice and this permission notice (including the 17next paragraph) shall be included in all copies or substantial portions 18of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28**************************************************************************/ 29 30/* 31 * Authors: 32 * Keith Whitwell <keith@tungstengraphics.com> 33 * David Dawes <dawes@xfree86.org> 34 * 35 * Updated for Dual Head capabilities: 36 * Alan Hourihane <alanh@tungstengraphics.com> 37 * 38 * Add ARGB HW cursor support: 39 * Alan Hourihane <alanh@tungstengraphics.com> 40 * 41 */ 42 43#ifdef HAVE_CONFIG_H 44#include "config.h" 45#endif 46 47#include <string.h> 48 49#include "xf86.h" 50#include "xf86_OSproc.h" 51#include "compiler.h" 52 53#include "xf86fbman.h" 54 55#include "i830.h" 56 57static void 58I830SetPipeCursorBase (xf86CrtcPtr crtc) 59{ 60 ScrnInfoPtr pScrn = crtc->scrn; 61 I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 62 int pipe = intel_crtc->pipe; 63 I830Ptr pI830 = I830PTR(pScrn); 64 int cursor_base; 65 66 cursor_base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE; 67 68 if (intel_crtc->cursor_is_argb) 69 OUTREG(cursor_base, intel_crtc->cursor_argb_addr); 70 else 71 OUTREG(cursor_base, intel_crtc->cursor_addr); 72} 73 74void 75I830InitHWCursor(ScrnInfoPtr pScrn) 76{ 77 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 78 I830Ptr pI830 = I830PTR(pScrn); 79 uint32_t temp; 80 int i; 81 82 DPRINTF(PFX, "I830InitHWCursor\n"); 83 84 if (!IS_I9XX(pI830)) 85 OUTREG(CURSOR_SIZE, (I810_CURSOR_Y << 12) | I810_CURSOR_X); 86 87 /* Initialise the HW cursor registers, leaving the cursor hidden. */ 88 for (i = 0; i < xf86_config->num_crtc; i++) 89 { 90 int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; 91 92 temp = INREG(cursor_control); 93 if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 94 { 95 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | 96 MCURSOR_MEM_TYPE_LOCAL | 97 MCURSOR_PIPE_SELECT); 98 temp |= (i << 28); 99 temp |= CURSOR_MODE_DISABLE; 100 } 101 else 102 { 103 temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); 104 } 105 106 /* Need to set control, then address. */ 107 OUTREG(cursor_control, temp); 108 I830SetPipeCursorBase(xf86_config->crtc[i]); 109 } 110} 111 112Bool 113I830CursorInit(ScreenPtr pScreen) 114{ 115 return xf86_cursors_init (pScreen, I810_CURSOR_X, I810_CURSOR_Y, 116 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 117 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 118 HARDWARE_CURSOR_INVERT_MASK | 119 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 120 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 121 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 122 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 123 HARDWARE_CURSOR_ARGB)); 124} 125 126#ifdef ARGB_CURSOR 127void 128i830_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 129{ 130 I830Ptr pI830 = I830PTR(crtc->scrn); 131 I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 132 uint32_t *pcurs; 133 134 pcurs = (uint32_t *) (pI830->FbBase + intel_crtc->cursor_argb_offset); 135 136 intel_crtc->cursor_is_argb = TRUE; 137 memcpy (pcurs, image, I810_CURSOR_Y * I810_CURSOR_X * 4); 138} 139#endif 140 141void 142i830_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 143{ 144 ScrnInfoPtr scrn = crtc->scrn; 145 I830Ptr pI830 = I830PTR(scrn); 146 I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc); 147 uint32_t temp; 148 149 temp = 0; 150 if (x < 0) { 151 temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; 152 x = -x; 153 } 154 if (y < 0) { 155 temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; 156 y = -y; 157 } 158 temp |= x << CURSOR_X_SHIFT; 159 temp |= y << CURSOR_Y_SHIFT; 160 161 switch (intel_crtc->pipe) { 162 case 0: 163 OUTREG(CURSOR_A_POSITION, temp); 164 break; 165 case 1: 166 OUTREG(CURSOR_B_POSITION, temp); 167 break; 168 } 169 170 if (crtc->cursor_shown) 171 I830SetPipeCursorBase (crtc); 172} 173 174void 175i830_crtc_show_cursor (xf86CrtcPtr crtc) 176{ 177 ScrnInfoPtr scrn = crtc->scrn; 178 I830Ptr pI830 = I830PTR(scrn); 179 I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc); 180 int pipe = intel_crtc->pipe; 181 uint32_t temp; 182 int cursor_control = (pipe == 0 ? CURSOR_A_CONTROL : 183 CURSOR_B_CONTROL); 184 185 temp = INREG(cursor_control); 186 187 if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 188 { 189 temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); 190 if (intel_crtc->cursor_is_argb) 191 temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; 192 else 193 temp |= CURSOR_MODE_64_4C_AX; 194 195 temp |= (pipe << 28); /* Connect to correct pipe */ 196 } 197 else 198 { 199 temp &= ~(CURSOR_FORMAT_MASK); 200 temp |= CURSOR_ENABLE; 201 if (intel_crtc->cursor_is_argb) 202 temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; 203 else 204 temp |= CURSOR_FORMAT_3C; 205 } 206 207 /* Need to set mode, then address. */ 208 OUTREG(cursor_control, temp); 209 I830SetPipeCursorBase (crtc); 210} 211 212void 213i830_crtc_hide_cursor (xf86CrtcPtr crtc) 214{ 215 ScrnInfoPtr scrn = crtc->scrn; 216 I830Ptr pI830 = I830PTR(scrn); 217 I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc); 218 int pipe = intel_crtc->pipe; 219 uint32_t temp; 220 int cursor_control = (pipe == 0 ? CURSOR_A_CONTROL : 221 CURSOR_B_CONTROL); 222 223 temp = INREG(cursor_control); 224 225 if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 226 { 227 temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); 228 temp |= CURSOR_MODE_DISABLE; 229 } 230 else 231 temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); 232 233 /* Need to set mode, then address. */ 234 OUTREG(cursor_control, temp); 235 I830SetPipeCursorBase (crtc); 236} 237 238void 239i830_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 240{ 241 ScrnInfoPtr scrn = crtc->scrn; 242 I830Ptr pI830 = I830PTR(scrn); 243 I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc); 244 int pipe = intel_crtc->pipe; 245 int pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0; 246 247 OUTREG(pal0 + 0, bg & 0x00ffffff); 248 OUTREG(pal0 + 4, fg & 0x00ffffff); 249 OUTREG(pal0 + 8, fg & 0x00ffffff); 250 OUTREG(pal0 + 12, bg & 0x00ffffff); 251} 252 253void 254i830_update_cursor_offsets (ScrnInfoPtr pScrn) 255{ 256 I830Ptr pI830 = I830PTR(pScrn); 257 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 258 int i; 259 260 if (pI830->cursor_mem) { 261 unsigned long cursor_offset_base = pI830->cursor_mem->offset; 262 unsigned long cursor_addr_base, offset = 0; 263 264 /* Single memory buffer for cursors */ 265 if (pI830->CursorNeedsPhysical) { 266 /* On any hardware that requires physical addresses for cursors, 267 * the PTEs don't support memory above 4GB, so we can safely 268 * ignore the top 32 bits of cursor_mem->bus_addr. 269 */ 270 cursor_addr_base = (unsigned long)pI830->cursor_mem->bus_addr; 271 } else 272 cursor_addr_base = pI830->cursor_mem->offset; 273 274 for (i = 0; i < xf86_config->num_crtc; i++) { 275 xf86CrtcPtr crtc = xf86_config->crtc[i]; 276 I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 277 278 intel_crtc->cursor_argb_addr = cursor_addr_base + offset; 279 intel_crtc->cursor_argb_offset = cursor_offset_base + offset; 280 offset += HWCURSOR_SIZE_ARGB; 281 282 intel_crtc->cursor_addr = cursor_addr_base + offset; 283 intel_crtc->cursor_offset = cursor_offset_base + offset; 284 offset += HWCURSOR_SIZE; 285 } 286 } else { 287 /* Separate allocations per cursor */ 288 for (i = 0; i < xf86_config->num_crtc; i++) { 289 xf86CrtcPtr crtc = xf86_config->crtc[i]; 290 I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 291 292 if (pI830->CursorNeedsPhysical) { 293 intel_crtc->cursor_addr = 294 pI830->cursor_mem_classic[i]->bus_addr; 295 intel_crtc->cursor_argb_addr = 296 pI830->cursor_mem_argb[i]->bus_addr; 297 } else { 298 intel_crtc->cursor_addr = 299 pI830->cursor_mem_classic[i]->offset; 300 intel_crtc->cursor_argb_addr = 301 pI830->cursor_mem_argb[i]->offset; 302 } 303 intel_crtc->cursor_offset = pI830->cursor_mem_classic[i]->offset; 304 intel_crtc->cursor_argb_offset = pI830->cursor_mem_argb[i]->offset; 305 } 306 } 307} 308