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