mach64_cursor.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  ATI Mach64 CT/VT/GT/LT Cursor Support
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __sparc__
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pbm.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fbio.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <video/mach64.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "atyfb.h"
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The hardware cursor definition requires 2 bits per pixel. The
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cursor size reguardless of the visible cursor size is 64 pixels
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by 64 lines. The total memory required to define the cursor is
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16 bytes / line for 64 lines or 1024 bytes of data. The data
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * must be in a contigiuos format. The 2 bit cursor code values are
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as follows:
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	00 - pixel colour = CURSOR_CLR_0
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	01 - pixel colour = CURSOR_CLR_1
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	10 - pixel colour = transparent (current display pixel)
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	11 - pixel colour = 1's complement of current display pixel
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Cursor Offset        64 pixels		 Actual Displayed Area
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *            \_________________________/
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |			|	|	|
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |<--------------->|	|	|
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      | CURS_HORZ_OFFSET|	|	|
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |			|_______|	|  64 Lines
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |			   ^	|	|
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |			   |	|	|
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |		CURS_VERT_OFFSET|	|
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |			   |	|	|
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      |____________________|____|	|
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Screen position of the top left corner of the displayed
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cursor is specificed by CURS_HORZ_VERT_POSN. Care must be taken
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when the cursor hot spot is not the top left corner and the
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * physical cursor position becomes negative. It will be be displayed
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if either the horizontal or vertical cursor position is negative
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If x becomes negative the cursor manager must adjust the CURS_HORZ_OFFSET
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to a larger number and saturate CUR_HORZ_POSN to zero.
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CUR_OFFSET must be adjusted to a point to the appropraite line in the cursor
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * definitation and CUR_VERT_POSN must be saturated to zero.
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  Hardware Cursor support.
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 cursor_bits_lookup[16] = {
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 cursor_mask_lookup[16] = {
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct atyfb_par *par = (struct atyfb_par *) info->par;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 xoff, yoff;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int x, y, h;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __sparc__
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (par->mmaped)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EPERM;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (par->asleep)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EPERM;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Hide cursor */
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_fifo(1, par);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) & ~HWCURSOR_ENABLE, par);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set position */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cursor->set & FB_CUR_SETPOS) {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (x < 0) {
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			xoff = -x;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			x = 0;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			xoff = 0;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		y = cursor->image.dy - cursor->hot.y - info->var.yoffset;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (y < 0) {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			yoff = -y;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			y = 0;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			yoff = 0;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		h = cursor->image.height;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * In doublescan mode, the cursor location
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * and heigh also needs to be doubled.
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) {
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			y<<=1;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			h<<=1;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_for_fifo(4, par);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(CUR_HORZ_VERT_OFF,
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    ((u32) (64 - h + yoff) << 16) | xoff, par);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set color map */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cursor->set & FB_CUR_SETCMAP) {
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 fg_idx, bg_idx, fg, bg;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fg_idx = cursor->image.fg_color;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bg_idx = cursor->image.bg_color;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fg = (info->cmap.red[fg_idx] << 24) |
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (info->cmap.green[fg_idx] << 16) |
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (info->cmap.blue[fg_idx] << 8) | 15;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bg = (info->cmap.red[bg_idx] << 24) |
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (info->cmap.green[bg_idx] << 16) |
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (info->cmap.blue[bg_idx] << 8);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_for_fifo(2, par);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(CUR_CLR0, bg, par);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(CUR_CLR1, fg, par);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    u8 *src = (u8 *)cursor->image.data;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    u8 *msk = (u8 *)cursor->mask;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    unsigned int width = (cursor->image.width + 7) >> 3;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    unsigned int height = cursor->image.height;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    unsigned int align = info->sprite.scan_align;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    unsigned int i, j, offset;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    u8 m, b;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    // Clear cursor image with 1010101010...
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    fb_memset(dst, 0xaa, 1024);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    offset = align - width*2;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    for (i = 0; i < height; i++) {
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = 0; j < width; j++) {
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			b = *src++;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			m = *msk++;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			switch (cursor->rop) {
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ROP_XOR:
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    // Upper 4 bits of mask data
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cursor_bits_lookup[(b ^ m) >> 4], dst++);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    // Lower 4 bits of mask
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cursor_bits_lookup[(b ^ m) & 0x0f], dst++);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    break;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ROP_COPY:
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    // Upper 4 bits of mask data
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cursor_bits_lookup[(b & m) >> 4], dst++);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    // Lower 4 bits of mask
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cursor_bits_lookup[(b & m) & 0x0f], dst++);
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    break;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += offset;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    }
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cursor->enable) {
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_for_fifo(1, par);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | HWCURSOR_ENABLE, par);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init aty_init_cursor(struct fb_info *info)
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long addr;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.smem_len -= PAGE_SIZE;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __sparc__
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.addr = (u8 *) addr;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __BIG_ENDIAN
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.addr = (u8 *) ioremap(addr, 1024);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	addr = (unsigned long) info->screen_base + info->fix.smem_len;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.addr = (u8 *) addr;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!info->sprite.addr)
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENXIO;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.size = PAGE_SIZE;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.scan_align = 16;	/* Scratch pad 64 bytes wide */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.buf_align = 16; 	/* and 64 lines tall. */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->sprite.flags = FB_PIXMAP_IO;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fbops->fb_cursor = atyfb_cursor;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227