1 /* -*- c-basic-offset: 4 -*- */ 2 /************************************************************************** 3 4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5 Copyright 2002 David Dawes 6 All Rights Reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a 9 copy of this software and associated documentation files (the 10 "Software"), to deal in the Software without restriction, including 11 without limitation the rights to use, copy, modify, merge, publish, 12 distribute, sub license, and/or sell copies of the Software, and to 13 permit persons to whom the Software is furnished to do so, subject to 14 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 portions 18 of the Software. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28 **************************************************************************/ 29 30 /* 31 * Authors: 32 * Keith Whitwell <keith (at) tungstengraphics.com> 33 * David Dawes <dawes (at) xfree86.org> 34 * 35 * Updated for Dual Head capabilities: 36 * Alan Hourihane <alanh (at) tungstengraphics.com> 37 * 38 * Add ARGB HW cursor support: 39 * Alan Hourihane <alanh (at) 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 57 static void 58 I830SetPipeCursorBase (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 74 void 75 I830InitHWCursor(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 112 Bool 113 I830CursorInit(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 127 void 128 i830_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 141 void 142 i830_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 174 void 175 i830_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 212 void 213 i830_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 238 void 239 i830_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 253 void 254 i830_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