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