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