Home | History | Annotate | Line # | Download | only in src
      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