1
2
3
4
5#include <linux/fb.h>
6#include <linux/init.h>
7#include <linux/string.h>
8#include "../core/fb_draw.h"
9
10#include <asm/io.h>
11
12#ifdef __sparc__
13#include <asm/fbio.h>
14#endif
15
16#include <video/mach64.h>
17#include "atyfb.h"
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62static const u8 cursor_bits_lookup[16] = {
63 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
64 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
65};
66
67static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
68{
69 struct atyfb_par *par = (struct atyfb_par *) info->par;
70 u16 xoff, yoff;
71 int x, y, h;
72
73#ifdef __sparc__
74 if (par->mmaped)
75 return -EPERM;
76#endif
77 if (par->asleep)
78 return -EPERM;
79
80 wait_for_fifo(1, par);
81 if (cursor->enable)
82 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
83 | HWCURSOR_ENABLE, par);
84 else
85 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
86 & ~HWCURSOR_ENABLE, par);
87
88
89 if (cursor->set & FB_CUR_SETPOS) {
90 x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
91 if (x < 0) {
92 xoff = -x;
93 x = 0;
94 } else {
95 xoff = 0;
96 }
97
98 y = cursor->image.dy - cursor->hot.y - info->var.yoffset;
99 if (y < 0) {
100 yoff = -y;
101 y = 0;
102 } else {
103 yoff = 0;
104 }
105
106 h = cursor->image.height;
107
108
109
110
111
112 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) {
113 y<<=1;
114 h<<=1;
115 }
116 wait_for_fifo(3, par);
117 aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
118 aty_st_le32(CUR_HORZ_VERT_OFF,
119 ((u32) (64 - h + yoff) << 16) | xoff, par);
120 aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
121 }
122
123
124 if (cursor->set & FB_CUR_SETCMAP) {
125 u32 fg_idx, bg_idx, fg, bg;
126
127 fg_idx = cursor->image.fg_color;
128 bg_idx = cursor->image.bg_color;
129
130 fg = ((info->cmap.red[fg_idx] & 0xff) << 24) |
131 ((info->cmap.green[fg_idx] & 0xff) << 16) |
132 ((info->cmap.blue[fg_idx] & 0xff) << 8) | 0xff;
133
134 bg = ((info->cmap.red[bg_idx] & 0xff) << 24) |
135 ((info->cmap.green[bg_idx] & 0xff) << 16) |
136 ((info->cmap.blue[bg_idx] & 0xff) << 8);
137
138 wait_for_fifo(2, par);
139 aty_st_le32(CUR_CLR0, bg, par);
140 aty_st_le32(CUR_CLR1, fg, par);
141 }
142
143 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
144 u8 *src = (u8 *)cursor->image.data;
145 u8 *msk = (u8 *)cursor->mask;
146 u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
147 unsigned int width = (cursor->image.width + 7) >> 3;
148 unsigned int height = cursor->image.height;
149 unsigned int align = info->sprite.scan_align;
150
151 unsigned int i, j, offset;
152 u8 m, b;
153
154
155 fb_memset(dst, 0xaa, 1024);
156
157 offset = align - width*2;
158
159 for (i = 0; i < height; i++) {
160 for (j = 0; j < width; j++) {
161 u16 l = 0xaaaa;
162 b = *src++;
163 m = *msk++;
164 switch (cursor->rop) {
165 case ROP_XOR:
166
167 l = cursor_bits_lookup[(b ^ m) >> 4] |
168
169 (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
170 break;
171 case ROP_COPY:
172
173 l = cursor_bits_lookup[(b & m) >> 4] |
174
175 (cursor_bits_lookup[(b & m) & 0x0f] << 8);
176 break;
177 }
178
179
180
181
182 if ((j + 1) * 8 > cursor->image.width) {
183 l = comp(l, 0xaaaa,
184 (1 << ((cursor->image.width & 7) * 2)) - 1);
185 }
186 fb_writeb(l & 0xff, dst++);
187 fb_writeb(l >> 8, dst++);
188 }
189 dst += offset;
190 }
191 }
192
193 return 0;
194}
195
196int aty_init_cursor(struct fb_info *info)
197{
198 unsigned long addr;
199
200 info->fix.smem_len -= PAGE_SIZE;
201
202#ifdef __sparc__
203 addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
204 info->sprite.addr = (u8 *) addr;
205#else
206#ifdef __BIG_ENDIAN
207 addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
208 info->sprite.addr = (u8 *) ioremap(addr, 1024);
209#else
210 addr = (unsigned long) info->screen_base + info->fix.smem_len;
211 info->sprite.addr = (u8 *) addr;
212#endif
213#endif
214 if (!info->sprite.addr)
215 return -ENXIO;
216 info->sprite.size = PAGE_SIZE;
217 info->sprite.scan_align = 16;
218 info->sprite.buf_align = 16;
219 info->sprite.flags = FB_PIXMAP_IO;
220
221 info->fbops->fb_cursor = atyfb_cursor;
222
223 return 0;
224}
225
226