]>
Commit | Line | Data |
---|---|---|
81dee67e SM |
1 | #include<linux/module.h> |
2 | #include<linux/kernel.h> | |
3 | #include<linux/errno.h> | |
4 | #include<linux/string.h> | |
5 | #include<linux/mm.h> | |
6 | #include<linux/slab.h> | |
7 | #include<linux/delay.h> | |
8 | #include<linux/fb.h> | |
9 | #include<linux/ioport.h> | |
10 | #include<linux/init.h> | |
11 | #include<linux/pci.h> | |
12 | #include<linux/vmalloc.h> | |
13 | #include<linux/pagemap.h> | |
14 | #include <linux/console.h> | |
15 | #include<linux/platform_device.h> | |
16 | #include<linux/screen_info.h> | |
17 | ||
18 | #include "sm750.h" | |
19 | #include "sm750_help.h" | |
20 | #include "sm750_cursor.h" | |
21 | ||
22 | ||
23 | #define PEEK32(addr) \ | |
24 | readl(cursor->mmio + (addr)) | |
25 | ||
c97b2c15 IA |
26 | #define POKE32(addr, data) \ |
27 | writel((data), cursor->mmio + (addr)) | |
81dee67e SM |
28 | |
29 | /* cursor control for voyager and 718/750*/ | |
30 | #define HWC_ADDRESS 0x0 | |
31 | #define HWC_ADDRESS_ENABLE 31:31 | |
32 | #define HWC_ADDRESS_ENABLE_DISABLE 0 | |
33 | #define HWC_ADDRESS_ENABLE_ENABLE 1 | |
34 | #define HWC_ADDRESS_EXT 27:27 | |
35 | #define HWC_ADDRESS_EXT_LOCAL 0 | |
36 | #define HWC_ADDRESS_EXT_EXTERNAL 1 | |
37 | #define HWC_ADDRESS_CS 26:26 | |
38 | #define HWC_ADDRESS_CS_0 0 | |
39 | #define HWC_ADDRESS_CS_1 1 | |
40 | #define HWC_ADDRESS_ADDRESS 25:0 | |
41 | ||
42 | #define HWC_LOCATION 0x4 | |
43 | #define HWC_LOCATION_TOP 27:27 | |
44 | #define HWC_LOCATION_TOP_INSIDE 0 | |
45 | #define HWC_LOCATION_TOP_OUTSIDE 1 | |
46 | #define HWC_LOCATION_Y 26:16 | |
47 | #define HWC_LOCATION_LEFT 11:11 | |
48 | #define HWC_LOCATION_LEFT_INSIDE 0 | |
49 | #define HWC_LOCATION_LEFT_OUTSIDE 1 | |
50 | #define HWC_LOCATION_X 10:0 | |
51 | ||
52 | #define HWC_COLOR_12 0x8 | |
53 | #define HWC_COLOR_12_2_RGB565 31:16 | |
54 | #define HWC_COLOR_12_1_RGB565 15:0 | |
55 | ||
56 | #define HWC_COLOR_3 0xC | |
57 | #define HWC_COLOR_3_RGB565 15:0 | |
58 | ||
59 | ||
60 | /* hw_cursor_xxx works for voyager,718 and 750 */ | |
eb0f4271 | 61 | void hw_cursor_enable(struct lynx_cursor *cursor) |
81dee67e SM |
62 | { |
63 | u32 reg; | |
40403c1b | 64 | |
c97b2c15 IA |
65 | reg = FIELD_VALUE(0, HWC_ADDRESS, ADDRESS, cursor->offset)| |
66 | FIELD_SET(0, HWC_ADDRESS, EXT, LOCAL)| | |
67 | FIELD_SET(0, HWC_ADDRESS, ENABLE, ENABLE); | |
68 | POKE32(HWC_ADDRESS, reg); | |
81dee67e | 69 | } |
eb0f4271 | 70 | void hw_cursor_disable(struct lynx_cursor *cursor) |
81dee67e | 71 | { |
c97b2c15 | 72 | POKE32(HWC_ADDRESS, 0); |
81dee67e SM |
73 | } |
74 | ||
eb0f4271 | 75 | void hw_cursor_setSize(struct lynx_cursor *cursor, |
c97b2c15 | 76 | int w, int h) |
81dee67e SM |
77 | { |
78 | cursor->w = w; | |
79 | cursor->h = h; | |
80 | } | |
eb0f4271 | 81 | void hw_cursor_setPos(struct lynx_cursor *cursor, |
c97b2c15 | 82 | int x, int y) |
81dee67e SM |
83 | { |
84 | u32 reg; | |
40403c1b | 85 | |
c97b2c15 IA |
86 | reg = FIELD_VALUE(0, HWC_LOCATION, Y, y)| |
87 | FIELD_VALUE(0, HWC_LOCATION, X, x); | |
88 | POKE32(HWC_LOCATION, reg); | |
81dee67e | 89 | } |
eb0f4271 | 90 | void hw_cursor_setColor(struct lynx_cursor *cursor, |
c97b2c15 | 91 | u32 fg, u32 bg) |
81dee67e | 92 | { |
c97b2c15 IA |
93 | POKE32(HWC_COLOR_12, (fg<<16)|(bg&0xffff)); |
94 | POKE32(HWC_COLOR_3, 0xffe0); | |
81dee67e SM |
95 | } |
96 | ||
eb0f4271 | 97 | void hw_cursor_setData(struct lynx_cursor *cursor, |
cc6c16df | 98 | u16 rop, const u8 *pcol, const u8 *pmsk) |
81dee67e | 99 | { |
c97b2c15 IA |
100 | int i, j, count, pitch, offset; |
101 | u8 color, mask, opr; | |
81dee67e | 102 | u16 data; |
35fb80b9 | 103 | void __iomem *pbuffer, *pstart; |
81dee67e SM |
104 | |
105 | /* in byte*/ | |
106 | pitch = cursor->w >> 3; | |
107 | ||
108 | /* in byte */ | |
109 | count = pitch * cursor->h; | |
110 | ||
35fb80b9 LS |
111 | /* in byte */ |
112 | offset = cursor->maxW * 2 / 8; | |
81dee67e SM |
113 | |
114 | data = 0; | |
35fb80b9 | 115 | pstart = cursor->vstart; |
81dee67e SM |
116 | pbuffer = pstart; |
117 | ||
118 | /* | |
119 | if(odd &1){ | |
120 | hw_cursor_setData2(cursor,rop,pcol,pmsk); | |
121 | } | |
122 | odd++; | |
123 | if(odd > 0xfffffff0) | |
124 | odd=0; | |
125 | */ | |
126 | ||
259fef35 | 127 | for (i = 0; i < count; i++) { |
81dee67e SM |
128 | color = *pcol++; |
129 | mask = *pmsk++; | |
130 | data = 0; | |
131 | ||
132 | /* either method below works well, | |
133 | * but method 2 shows no lag | |
134 | * and method 1 seems a bit wrong*/ | |
135 | #if 0 | |
9ccc5f44 | 136 | if (rop == ROP_XOR) |
81dee67e SM |
137 | opr = mask ^ color; |
138 | else | |
139 | opr = mask & color; | |
140 | ||
259fef35 | 141 | for (j = 0; j < 8; j++) { |
81dee67e | 142 | |
259fef35 JL |
143 | if (opr & (0x80 >> j)) { |
144 | /* use fg color,id = 2 */ | |
81dee67e | 145 | data |= 2 << (j*2); |
6338a781 | 146 | } else { |
5ee35ea7 | 147 | /* use bg color,id = 1 */ |
81dee67e SM |
148 | data |= 1 << (j*2); |
149 | } | |
150 | } | |
151 | #else | |
adbb90e8 | 152 | for (j = 0; j < 8; j++) { |
8c11f5a2 | 153 | if (mask & (0x80>>j)) { |
9ccc5f44 | 154 | if (rop == ROP_XOR) |
81dee67e SM |
155 | opr = mask ^ color; |
156 | else | |
157 | opr = mask & color; | |
158 | ||
159 | /* 2 stands for forecolor and 1 for backcolor */ | |
160 | data |= ((opr & (0x80>>j))?2:1)<<(j*2); | |
161 | } | |
162 | } | |
163 | #endif | |
35fb80b9 | 164 | iowrite16(data, pbuffer); |
81dee67e SM |
165 | |
166 | /* assume pitch is 1,2,4,8,...*/ | |
167 | #if 0 | |
9ccc5f44 | 168 | if (!((i+1)&(pitch-1))) /* below line equal to is line */ |
81dee67e | 169 | #else |
9ccc5f44 | 170 | if ((i+1) % pitch == 0) |
81dee67e SM |
171 | #endif |
172 | { | |
173 | /* need a return */ | |
174 | pstart += offset; | |
175 | pbuffer = pstart; | |
6338a781 | 176 | } else { |
35fb80b9 | 177 | pbuffer += sizeof(u16); |
81dee67e SM |
178 | } |
179 | ||
180 | } | |
181 | ||
182 | ||
183 | } | |
184 | ||
185 | ||
eb0f4271 | 186 | void hw_cursor_setData2(struct lynx_cursor *cursor, |
cc6c16df | 187 | u16 rop, const u8 *pcol, const u8 *pmsk) |
81dee67e | 188 | { |
c97b2c15 | 189 | int i, j, count, pitch, offset; |
041d3a42 | 190 | u8 color, mask; |
81dee67e | 191 | u16 data; |
35fb80b9 | 192 | void __iomem *pbuffer, *pstart; |
81dee67e SM |
193 | |
194 | /* in byte*/ | |
195 | pitch = cursor->w >> 3; | |
196 | ||
197 | /* in byte */ | |
198 | count = pitch * cursor->h; | |
199 | ||
35fb80b9 LS |
200 | /* in byte */ |
201 | offset = cursor->maxW * 2 / 8; | |
81dee67e SM |
202 | |
203 | data = 0; | |
35fb80b9 | 204 | pstart = cursor->vstart; |
81dee67e SM |
205 | pbuffer = pstart; |
206 | ||
259fef35 | 207 | for (i = 0; i < count; i++) { |
81dee67e SM |
208 | color = *pcol++; |
209 | mask = *pmsk++; | |
210 | data = 0; | |
211 | ||
212 | /* either method below works well, but method 2 shows no lag */ | |
213 | #if 0 | |
9ccc5f44 | 214 | if (rop == ROP_XOR) |
81dee67e SM |
215 | opr = mask ^ color; |
216 | else | |
217 | opr = mask & color; | |
218 | ||
259fef35 | 219 | for (j = 0; j < 8; j++) { |
81dee67e | 220 | |
259fef35 JL |
221 | if (opr & (0x80 >> j)) { |
222 | /* use fg color,id = 2 */ | |
81dee67e | 223 | data |= 2 << (j*2); |
6338a781 | 224 | } else { |
5ee35ea7 | 225 | /* use bg color,id = 1 */ |
81dee67e SM |
226 | data |= 1 << (j*2); |
227 | } | |
228 | } | |
229 | #else | |
adbb90e8 | 230 | for (j = 0; j < 8; j++) { |
9ccc5f44 | 231 | if (mask & (1<<j)) |
81dee67e SM |
232 | data |= ((color & (1<<j))?1:2)<<(j*2); |
233 | } | |
234 | #endif | |
35fb80b9 | 235 | iowrite16(data, pbuffer); |
81dee67e SM |
236 | |
237 | /* assume pitch is 1,2,4,8,...*/ | |
259fef35 | 238 | if (!(i&(pitch-1))) { |
81dee67e SM |
239 | /* need a return */ |
240 | pstart += offset; | |
241 | pbuffer = pstart; | |
6338a781 | 242 | } else { |
35fb80b9 | 243 | pbuffer += sizeof(u16); |
81dee67e SM |
244 | } |
245 | ||
246 | } | |
81dee67e | 247 | } |