radeon_cursor.c revision 70cce690
1/*
2 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3 *                VA Linux Systems Inc., Fremont, California.
4 *
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation on the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial
17 * portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#define RADEONCTRACE(x)
34/*#define RADEONCTRACE(x) RADEONTRACE(x) */
35
36/*
37 * Authors:
38 *   Kevin E. Martin <martin@xfree86.org>
39 *   Rickard E. Faith <faith@valinux.com>
40 *
41 * References:
42 *
43 * !!!! FIXME !!!!
44 *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
45 *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
46 *   1999.
47 *
48 *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
49 *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
50 *
51 */
52
53				/* Driver data structures */
54#include "radeon.h"
55#include "radeon_version.h"
56#include "radeon_reg.h"
57#include "radeon_macros.h"
58
59				/* X and server generic header files */
60#include "xf86.h"
61
62#define CURSOR_WIDTH	64
63#define CURSOR_HEIGHT	64
64
65/*
66 * The cursor bits are always 32bpp.  On MSBFirst buses,
67 * configure byte swapping to swap 32 bit units when writing
68 * the cursor image.  Byte swapping must always be returned
69 * to its previous value before returning.
70 */
71#if X_BYTE_ORDER == X_BIG_ENDIAN
72
73#define CURSOR_SWAPPING_DECL_MMIO   unsigned char *RADEONMMIO = info->MMIO;
74#define CURSOR_SWAPPING_START() \
75  do { \
76  if (info->ChipFamily < CHIP_FAMILY_R600) \
77    OUTREG(RADEON_SURFACE_CNTL, \
78	   (info->ModeReg->surface_cntl | \
79	     RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \
80	   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \
81  } while (0)
82#define CURSOR_SWAPPING_END()	\
83  do { \
84  if (info->ChipFamily < CHIP_FAMILY_R600) \
85      OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); \
86  } while (0)
87#else
88
89#define CURSOR_SWAPPING_DECL_MMIO
90#define CURSOR_SWAPPING_START()
91#define CURSOR_SWAPPING_END()
92
93#endif
94
95static void
96avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable)
97{
98    ScrnInfoPtr pScrn = crtc->scrn;
99    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
100    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
101    unsigned char     *RADEONMMIO = info->MMIO;
102
103    /* always use the same cursor mode even if the cursor is disabled,
104     * otherwise you may end up with cursor curruption bands
105     */
106    OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
107
108    if (enable) {
109	uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset;
110	if (info->ChipFamily >= CHIP_FAMILY_RV770) {
111	    if (radeon_crtc->crtc_id)
112		OUTREG(R700_D2CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf);
113	    else
114		OUTREG(R700_D1CUR_SURFACE_ADDRESS_HIGH, (location >> 32) & 0xf);
115	}
116	OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
117	       info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset);
118	OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
119	       AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
120    }
121}
122
123static void
124avivo_lock_cursor(xf86CrtcPtr crtc, Bool lock)
125{
126    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
127    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
128    unsigned char     *RADEONMMIO = info->MMIO;
129    uint32_t tmp;
130
131    tmp = INREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
132
133    if (lock)
134	tmp |= AVIVO_D1CURSOR_UPDATE_LOCK;
135    else
136	tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
137
138    OUTREG(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp);
139}
140
141static void
142evergreen_setup_cursor(xf86CrtcPtr crtc, Bool enable)
143{
144    ScrnInfoPtr pScrn = crtc->scrn;
145    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
146    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
147    unsigned char     *RADEONMMIO = info->MMIO;
148
149    /* always use the same cursor mode even if the cursor is disabled,
150     * otherwise you may end up with cursor curruption bands
151     */
152    OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
153	   EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
154
155    if (enable) {
156	uint64_t location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset;
157	OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
158	       (location >> 32) & 0xf);
159	OUTREG(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
160	       location & EVERGREEN_CUR_SURFACE_ADDRESS_MASK);
161	OUTREG(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
162	       EVERGREEN_CURSOR_EN | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
163    }
164}
165
166static void
167evergreen_lock_cursor(xf86CrtcPtr crtc, Bool lock)
168{
169    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
170    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
171    unsigned char     *RADEONMMIO = info->MMIO;
172    uint32_t tmp;
173
174    tmp = INREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
175
176    if (lock)
177	tmp |= EVERGREEN_CURSOR_UPDATE_LOCK;
178    else
179	tmp &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
180
181    OUTREG(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, tmp);
182}
183
184void
185radeon_crtc_show_cursor (xf86CrtcPtr crtc)
186{
187    ScrnInfoPtr pScrn = crtc->scrn;
188    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
189    int crtc_id = radeon_crtc->crtc_id;
190    RADEONInfoPtr      info       = RADEONPTR(pScrn);
191    unsigned char     *RADEONMMIO = info->MMIO;
192
193    if (IS_DCE4_VARIANT) {
194	evergreen_lock_cursor(crtc, TRUE);
195	evergreen_setup_cursor(crtc, TRUE);
196	evergreen_lock_cursor(crtc, FALSE);
197    } else if (IS_AVIVO_VARIANT) {
198	avivo_lock_cursor(crtc, TRUE);
199	avivo_setup_cursor(crtc, TRUE);
200	avivo_lock_cursor(crtc, FALSE);
201    } else {
202        switch (crtc_id) {
203        case 0:
204            OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
205	    break;
206        case 1:
207            OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
208	    break;
209        default:
210            return;
211        }
212
213        OUTREGP(RADEON_MM_DATA, RADEON_CRTC_CUR_EN | 2 << 20,
214                ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
215    }
216}
217
218void
219radeon_crtc_hide_cursor (xf86CrtcPtr crtc)
220{
221    ScrnInfoPtr pScrn = crtc->scrn;
222    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
223    int crtc_id = radeon_crtc->crtc_id;
224    RADEONInfoPtr      info       = RADEONPTR(pScrn);
225    unsigned char     *RADEONMMIO = info->MMIO;
226
227    if (IS_DCE4_VARIANT) {
228	evergreen_lock_cursor(crtc, TRUE);
229	evergreen_setup_cursor(crtc, FALSE);
230	evergreen_lock_cursor(crtc, FALSE);
231    } else if (IS_AVIVO_VARIANT) {
232	avivo_lock_cursor(crtc, TRUE);
233	avivo_setup_cursor(crtc, FALSE);
234	avivo_lock_cursor(crtc, FALSE);
235    } else {
236	switch(crtc_id) {
237    	case 0:
238            OUTREG(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
239            break;
240    	case 1:
241	    OUTREG(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
242	    break;
243        default:
244	    return;
245        }
246
247        OUTREGP(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
248   }
249}
250
251void
252radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
253{
254    ScrnInfoPtr pScrn = crtc->scrn;
255    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
256    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
257    int crtc_id = radeon_crtc->crtc_id;
258    RADEONInfoPtr      info       = RADEONPTR(pScrn);
259    unsigned char     *RADEONMMIO = info->MMIO;
260    int xorigin = 0, yorigin = 0;
261    int stride = 256;
262    DisplayModePtr mode = &crtc->mode;
263    int w = CURSOR_WIDTH;
264
265    if (x < 0)                        xorigin = -x+1;
266    if (y < 0)                        yorigin = -y+1;
267    if (xorigin >= CURSOR_WIDTH)  xorigin = CURSOR_WIDTH - 1;
268    if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1;
269
270    if (IS_AVIVO_VARIANT) {
271	/* avivo cursor spans the full fb width */
272	if (crtc->rotatedData == NULL) {
273	    x += crtc->x;
274	    y += crtc->y;
275	}
276
277	if (pRADEONEnt->Controller[0]->enabled &&
278	    pRADEONEnt->Controller[1]->enabled) {
279	    int cursor_end, frame_end;
280
281	    cursor_end = x - xorigin + w;
282	    frame_end = crtc->x + mode->CrtcHDisplay;
283
284	    if (cursor_end >= frame_end) {
285		w = w - (cursor_end - frame_end);
286		if (!(frame_end & 0x7f))
287		    w--;
288	    } else {
289		if (!(cursor_end & 0x7f))
290		    w--;
291	    }
292	    if (w <= 0)
293		w = 1;
294	}
295    }
296
297    if (IS_DCE4_VARIANT) {
298	evergreen_lock_cursor(crtc, TRUE);
299	OUTREG(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16)
300	       | (yorigin ? 0 : y));
301	OUTREG(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
302	OUTREG(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
303	       ((w - 1) << 16) | (CURSOR_HEIGHT - 1));
304	evergreen_lock_cursor(crtc, FALSE);
305    } else if (IS_AVIVO_VARIANT) {
306	avivo_lock_cursor(crtc, TRUE);
307	OUTREG(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16)
308	       | (yorigin ? 0 : y));
309	OUTREG(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
310	OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((w - 1) << 16) | (CURSOR_HEIGHT - 1));
311	avivo_lock_cursor(crtc, FALSE);
312    } else {
313	if (mode->Flags & V_DBLSCAN)
314	    y *= 2;
315
316	if (crtc_id == 0) {
317	    OUTREG(RADEON_CUR_HORZ_VERT_OFF,  (RADEON_CUR_LOCK
318					       | (xorigin << 16)
319					       | yorigin));
320	    OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
321					       | ((xorigin ? 0 : x) << 16)
322					       | (yorigin ? 0 : y)));
323	    RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
324			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
325	    OUTREG(RADEON_CUR_OFFSET,
326		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
327	} else if (crtc_id == 1) {
328	    OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
329						| (xorigin << 16)
330						| yorigin));
331	    OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
332						| ((xorigin ? 0 : x) << 16)
333						| (yorigin ? 0 : y)));
334	    RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
335			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
336	    OUTREG(RADEON_CUR2_OFFSET,
337		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
338	}
339    }
340}
341
342void
343radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
344{
345    ScrnInfoPtr pScrn = crtc->scrn;
346    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
347    RADEONInfoPtr info = RADEONPTR(pScrn);
348    uint32_t *pixels = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset);
349    int            pixel, i;
350    CURSOR_SWAPPING_DECL_MMIO
351
352    RADEONCTRACE(("RADEONSetCursorColors\n"));
353
354#ifdef ARGB_CURSOR
355    /* Don't recolour cursors set with SetCursorARGB. */
356    if (info->cursor_argb)
357       return;
358#endif
359
360    fg |= 0xff000000;
361    bg |= 0xff000000;
362
363    /* Don't recolour the image if we don't have to. */
364    if (fg == info->cursor_fg && bg == info->cursor_bg)
365       return;
366
367    CURSOR_SWAPPING_START();
368
369    /* Note: We assume that the pixels are either fully opaque or fully
370     * transparent, so we won't premultiply them, and we can just
371     * check for non-zero pixel values; those are either fg or bg
372     */
373    for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++)
374       if ((pixel = *pixels))
375           *pixels = (pixel == info->cursor_fg) ? fg : bg;
376
377    CURSOR_SWAPPING_END();
378    info->cursor_fg = fg;
379    info->cursor_bg = bg;
380}
381
382#ifdef ARGB_CURSOR
383
384void
385radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
386{
387    ScrnInfoPtr pScrn = crtc->scrn;
388    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
389    RADEONInfoPtr  info = RADEONPTR(pScrn);
390    CURSOR_SWAPPING_DECL_MMIO
391    uint32_t *d = (uint32_t *)(pointer)(info->FB + pScrn->fbOffset + radeon_crtc->cursor_offset);
392
393    RADEONCTRACE(("RADEONLoadCursorARGB\n"));
394
395    info->cursor_argb = TRUE;
396
397    CURSOR_SWAPPING_START();
398
399    memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4);
400
401    CURSOR_SWAPPING_END ();
402}
403
404#endif
405
406
407/* Initialize hardware cursor support. */
408Bool RADEONCursorInit(ScreenPtr pScreen)
409{
410    ScrnInfoPtr        pScrn   = xf86Screens[pScreen->myNum];
411    RADEONInfoPtr      info    = RADEONPTR(pScrn);
412    unsigned char     *RADEONMMIO = info->MMIO;
413    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
414    int                c;
415
416    for (c = 0; c < xf86_config->num_crtc; c++) {
417	xf86CrtcPtr crtc = xf86_config->crtc[c];
418	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
419
420	if (!info->useEXA) {
421	    int size_bytes  = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
422	    int align = IS_AVIVO_VARIANT ? 4096 : 256;
423
424	    radeon_crtc->cursor_offset =
425		radeon_legacy_allocate_memory(pScrn, &radeon_crtc->cursor_mem,
426				size_bytes, align, RADEON_GEM_DOMAIN_VRAM);
427
428	    if (radeon_crtc->cursor_offset == 0)
429		return FALSE;
430
431	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
432		       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
433		       (size_bytes * xf86_config->num_crtc) / 1024,
434		       c,
435		       (unsigned int)radeon_crtc->cursor_offset);
436	}
437	/* set the cursor mode the same on both crtcs to avoid corruption */
438	/* XXX check if this is needed on evergreen */
439	if (IS_AVIVO_VARIANT)
440	    OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
441		   (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
442    }
443
444    return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT,
445			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
446			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
447			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
448			       HARDWARE_CURSOR_ARGB));
449}
450