diff options
author | Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de> | 2007-05-01 16:32:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-04 20:59:05 -0400 |
commit | a100501212f2e26bb6d70bfb5c55eefd90e22b65 (patch) | |
tree | 64373f2a78d8920e11fe2a66152f280332b51363 | |
parent | c04cb856e20a8bf68762d60737b84328c1ab5900 (diff) |
m68k: Atari fb revival
Update the atari fb to 2.6 by Michael Schmitz,
Reformatting and rewrite of bit plane functions by Roman Zippel,
A few more fixes by Geert Uytterhoeven.
Signed-off-by: Michael Schmitz <schmitz@debian.org>
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/video/Kconfig | 5 | ||||
-rw-r--r-- | drivers/video/Makefile | 3 | ||||
-rw-r--r-- | drivers/video/atafb.c | 2801 | ||||
-rw-r--r-- | drivers/video/atafb.h | 36 | ||||
-rw-r--r-- | drivers/video/atafb_iplan2p2.c | 293 | ||||
-rw-r--r-- | drivers/video/atafb_iplan2p4.c | 308 | ||||
-rw-r--r-- | drivers/video/atafb_iplan2p8.c | 345 | ||||
-rw-r--r-- | drivers/video/atafb_mfb.c | 112 | ||||
-rw-r--r-- | drivers/video/atafb_utils.h | 400 |
9 files changed, 2987 insertions, 1316 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index b1cb72c3780f..d18b51f989c9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -389,7 +389,10 @@ config FB_ARC | |||
389 | 389 | ||
390 | config FB_ATARI | 390 | config FB_ATARI |
391 | bool "Atari native chipset support" | 391 | bool "Atari native chipset support" |
392 | depends on (FB = y) && ATARI && BROKEN | 392 | depends on (FB = y) && ATARI |
393 | select FB_CFB_FILLRECT | ||
394 | select FB_CFB_COPYAREA | ||
395 | select FB_CFB_IMAGEBLIT | ||
393 | help | 396 | help |
394 | This is the frame buffer device driver for the builtin graphics | 397 | This is the frame buffer device driver for the builtin graphics |
395 | chipset found in Ataris. | 398 | chipset found in Ataris. |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 760305c8a841..869351785ee8 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -63,7 +63,8 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o | |||
63 | obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o | 63 | obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o |
64 | obj-$(CONFIG_FB_SGIVW) += sgivwfb.o | 64 | obj-$(CONFIG_FB_SGIVW) += sgivwfb.o |
65 | obj-$(CONFIG_FB_ACORN) += acornfb.o | 65 | obj-$(CONFIG_FB_ACORN) += acornfb.o |
66 | obj-$(CONFIG_FB_ATARI) += atafb.o | 66 | obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \ |
67 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o | ||
67 | obj-$(CONFIG_FB_MAC) += macfb.o | 68 | obj-$(CONFIG_FB_MAC) += macfb.o |
68 | obj-$(CONFIG_FB_HGA) += hgafb.o | 69 | obj-$(CONFIG_FB_HGA) += hgafb.o |
69 | obj-$(CONFIG_FB_IGA) += igafb.o | 70 | obj-$(CONFIG_FB_IGA) += igafb.o |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index bffe2b946344..0038a0541c7e 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device | 2 | * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device |
3 | * | 3 | * |
4 | * Copyright (C) 1994 Martin Schaller & Roman Hodek | 4 | * Copyright (C) 1994 Martin Schaller & Roman Hodek |
5 | * | 5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file COPYING in the main directory of this archive | 7 | * License. See the file COPYING in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
@@ -70,14 +70,8 @@ | |||
70 | #include <linux/fb.h> | 70 | #include <linux/fb.h> |
71 | #include <asm/atarikb.h> | 71 | #include <asm/atarikb.h> |
72 | 72 | ||
73 | #include <video/fbcon.h> | 73 | #include "c2p.h" |
74 | #include <video/fbcon-cfb8.h> | 74 | #include "atafb.h" |
75 | #include <video/fbcon-cfb16.h> | ||
76 | #include <video/fbcon-iplan2p2.h> | ||
77 | #include <video/fbcon-iplan2p4.h> | ||
78 | #include <video/fbcon-iplan2p8.h> | ||
79 | #include <video/fbcon-mfb.h> | ||
80 | |||
81 | 75 | ||
82 | #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ | 76 | #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ |
83 | #define SWITCH_SND6 0x40 | 77 | #define SWITCH_SND6 0x40 |
@@ -87,22 +81,48 @@ | |||
87 | 81 | ||
88 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) | 82 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) |
89 | 83 | ||
84 | /* | ||
85 | * Interface to the world | ||
86 | */ | ||
87 | |||
88 | static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); | ||
89 | static int atafb_set_par(struct fb_info *info); | ||
90 | static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
91 | unsigned int blue, unsigned int transp, | ||
92 | struct fb_info *info); | ||
93 | static int atafb_blank(int blank, struct fb_info *info); | ||
94 | static int atafb_pan_display(struct fb_var_screeninfo *var, | ||
95 | struct fb_info *info); | ||
96 | static void atafb_fillrect(struct fb_info *info, | ||
97 | const struct fb_fillrect *rect); | ||
98 | static void atafb_copyarea(struct fb_info *info, | ||
99 | const struct fb_copyarea *region); | ||
100 | static void atafb_imageblit(struct fb_info *info, const struct fb_image *image); | ||
101 | static int atafb_ioctl(struct fb_info *info, unsigned int cmd, | ||
102 | unsigned long arg); | ||
103 | |||
90 | 104 | ||
91 | static int default_par=0; /* default resolution (0=none) */ | 105 | static int default_par; /* default resolution (0=none) */ |
92 | 106 | ||
93 | static unsigned long default_mem_req=0; | 107 | static unsigned long default_mem_req; |
94 | 108 | ||
95 | static int hwscroll=-1; | 109 | static int hwscroll = -1; |
96 | 110 | ||
97 | static int use_hwscroll = 1; | 111 | static int use_hwscroll = 1; |
98 | 112 | ||
99 | static int sttt_xres=640,st_yres=400,tt_yres=480; | 113 | static int sttt_xres = 640, st_yres = 400, tt_yres = 480; |
100 | static int sttt_xres_virtual=640,sttt_yres_virtual=400; | 114 | static int sttt_xres_virtual = 640, sttt_yres_virtual = 400; |
101 | static int ovsc_offset=0, ovsc_addlen=0; | 115 | static int ovsc_offset, ovsc_addlen; |
116 | |||
117 | /* | ||
118 | * Hardware parameters for current mode | ||
119 | */ | ||
102 | 120 | ||
103 | static struct atafb_par { | 121 | static struct atafb_par { |
104 | void *screen_base; | 122 | void *screen_base; |
105 | int yres_virtual; | 123 | int yres_virtual; |
124 | u_long next_line; | ||
125 | u_long next_plane; | ||
106 | #if defined ATAFB_TT || defined ATAFB_STE | 126 | #if defined ATAFB_TT || defined ATAFB_STE |
107 | union { | 127 | union { |
108 | struct { | 128 | struct { |
@@ -138,7 +158,7 @@ static struct atafb_par { | |||
138 | /* Don't calculate an own resolution, and thus don't change the one found when | 158 | /* Don't calculate an own resolution, and thus don't change the one found when |
139 | * booting (currently used for the Falcon to keep settings for internal video | 159 | * booting (currently used for the Falcon to keep settings for internal video |
140 | * hardware extensions (e.g. ScreenBlaster) */ | 160 | * hardware extensions (e.g. ScreenBlaster) */ |
141 | static int DontCalcRes = 0; | 161 | static int DontCalcRes = 0; |
142 | 162 | ||
143 | #ifdef ATAFB_FALCON | 163 | #ifdef ATAFB_FALCON |
144 | #define HHT hw.falcon.hht | 164 | #define HHT hw.falcon.hht |
@@ -163,83 +183,84 @@ static int DontCalcRes = 0; | |||
163 | #define VMO_PREMASK 0x0c | 183 | #define VMO_PREMASK 0x0c |
164 | #endif | 184 | #endif |
165 | 185 | ||
166 | static struct fb_info fb_info; | 186 | static struct fb_info fb_info = { |
187 | .fix = { | ||
188 | .id = "Atari ", | ||
189 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
190 | .accel = FB_ACCEL_NONE, | ||
191 | } | ||
192 | }; | ||
167 | 193 | ||
168 | static void *screen_base; /* base address of screen */ | 194 | static void *screen_base; /* base address of screen */ |
169 | static void *real_screen_base; /* (only for Overscan) */ | 195 | static void *real_screen_base; /* (only for Overscan) */ |
170 | 196 | ||
171 | static int screen_len; | 197 | static int screen_len; |
172 | 198 | ||
173 | static int current_par_valid=0; | 199 | static int current_par_valid; |
174 | 200 | ||
175 | static int mono_moni=0; | 201 | static int mono_moni; |
176 | |||
177 | static struct display disp; | ||
178 | 202 | ||
179 | 203 | ||
180 | #ifdef ATAFB_EXT | 204 | #ifdef ATAFB_EXT |
181 | /* external video handling */ | ||
182 | 205 | ||
183 | static unsigned external_xres; | 206 | /* external video handling */ |
184 | static unsigned external_xres_virtual; | 207 | static unsigned int external_xres; |
185 | static unsigned external_yres; | 208 | static unsigned int external_xres_virtual; |
186 | /* not needed - atafb will never support panning/hardwarescroll with external | 209 | static unsigned int external_yres; |
187 | * static unsigned external_yres_virtual; | ||
188 | */ | ||
189 | 210 | ||
190 | static unsigned external_depth; | 211 | /* |
191 | static int external_pmode; | 212 | * not needed - atafb will never support panning/hardwarescroll with external |
192 | static void *external_addr = 0; | 213 | * static unsigned int external_yres_virtual; |
193 | static unsigned long external_len; | 214 | */ |
194 | static unsigned long external_vgaiobase = 0; | 215 | static unsigned int external_depth; |
195 | static unsigned int external_bitspercol = 6; | 216 | static int external_pmode; |
196 | 217 | static void *external_addr; | |
197 | /* | 218 | static unsigned long external_len; |
198 | JOE <joe@amber.dinoco.de>: | 219 | static unsigned long external_vgaiobase; |
199 | added card type for external driver, is only needed for | 220 | static unsigned int external_bitspercol = 6; |
200 | colormap handling. | ||
201 | */ | ||
202 | 221 | ||
222 | /* | ||
223 | * JOE <joe@amber.dinoco.de>: | ||
224 | * added card type for external driver, is only needed for | ||
225 | * colormap handling. | ||
226 | */ | ||
203 | enum cardtype { IS_VGA, IS_MV300 }; | 227 | enum cardtype { IS_VGA, IS_MV300 }; |
204 | static enum cardtype external_card_type = IS_VGA; | 228 | static enum cardtype external_card_type = IS_VGA; |
205 | 229 | ||
206 | /* | 230 | /* |
207 | The MV300 mixes the color registers. So we need an array of munged | 231 | * The MV300 mixes the color registers. So we need an array of munged |
208 | indices in order to access the correct reg. | 232 | * indices in order to access the correct reg. |
209 | */ | 233 | */ |
210 | static int MV300_reg_1bit[2]={0,1}; | 234 | static int MV300_reg_1bit[2] = { |
211 | static int MV300_reg_4bit[16]={ | 235 | 0, 1 |
212 | 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; | 236 | }; |
213 | static int MV300_reg_8bit[256]={ | 237 | static int MV300_reg_4bit[16] = { |
214 | 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, | 238 | 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 |
215 | 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, | 239 | }; |
216 | 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, | 240 | static int MV300_reg_8bit[256] = { |
217 | 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, | 241 | 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, |
218 | 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, | 242 | 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, |
219 | 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, | 243 | 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, |
220 | 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, | 244 | 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, |
221 | 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, | 245 | 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, |
222 | 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, | 246 | 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, |
223 | 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, | 247 | 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, |
224 | 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, | 248 | 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, |
225 | 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, | 249 | 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, |
226 | 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, | 250 | 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, |
227 | 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, | 251 | 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, |
228 | 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, | 252 | 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, |
229 | 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; | 253 | 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, |
254 | 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, | ||
255 | 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, | ||
256 | 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 | ||
257 | }; | ||
230 | 258 | ||
231 | static int *MV300_reg = MV300_reg_8bit; | 259 | static int *MV300_reg = MV300_reg_8bit; |
232 | |||
233 | /* | ||
234 | And on the MV300 it's difficult to read out the hardware palette. So we | ||
235 | just keep track of the set colors in our own array here, and use that! | ||
236 | */ | ||
237 | |||
238 | static struct { unsigned char red,green,blue,pad; } ext_color[256]; | ||
239 | #endif /* ATAFB_EXT */ | 260 | #endif /* ATAFB_EXT */ |
240 | 261 | ||
241 | 262 | ||
242 | static int inverse=0; | 263 | static int inverse; |
243 | 264 | ||
244 | extern int fontheight_8x8; | 265 | extern int fontheight_8x8; |
245 | extern int fontwidth_8x8; | 266 | extern int fontwidth_8x8; |
@@ -249,96 +270,154 @@ extern int fontheight_8x16; | |||
249 | extern int fontwidth_8x16; | 270 | extern int fontwidth_8x16; |
250 | extern unsigned char fontdata_8x16[]; | 271 | extern unsigned char fontdata_8x16[]; |
251 | 272 | ||
273 | /* | ||
274 | * struct fb_ops { | ||
275 | * * open/release and usage marking | ||
276 | * struct module *owner; | ||
277 | * int (*fb_open)(struct fb_info *info, int user); | ||
278 | * int (*fb_release)(struct fb_info *info, int user); | ||
279 | * | ||
280 | * * For framebuffers with strange non linear layouts or that do not | ||
281 | * * work with normal memory mapped access | ||
282 | * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos); | ||
283 | * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos); | ||
284 | * | ||
285 | * * checks var and eventually tweaks it to something supported, | ||
286 | * * DOES NOT MODIFY PAR * | ||
287 | * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); | ||
288 | * | ||
289 | * * set the video mode according to info->var * | ||
290 | * int (*fb_set_par)(struct fb_info *info); | ||
291 | * | ||
292 | * * set color register * | ||
293 | * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green, | ||
294 | * unsigned int blue, unsigned int transp, struct fb_info *info); | ||
295 | * | ||
296 | * * set color registers in batch * | ||
297 | * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); | ||
298 | * | ||
299 | * * blank display * | ||
300 | * int (*fb_blank)(int blank, struct fb_info *info); | ||
301 | * | ||
302 | * * pan display * | ||
303 | * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); | ||
304 | * | ||
305 | * *** The meat of the drawing engine *** | ||
306 | * * Draws a rectangle * | ||
307 | * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); | ||
308 | * * Copy data from area to another * | ||
309 | * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); | ||
310 | * * Draws a image to the display * | ||
311 | * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); | ||
312 | * | ||
313 | * * Draws cursor * | ||
314 | * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); | ||
315 | * | ||
316 | * * Rotates the display * | ||
317 | * void (*fb_rotate)(struct fb_info *info, int angle); | ||
318 | * | ||
319 | * * wait for blit idle, optional * | ||
320 | * int (*fb_sync)(struct fb_info *info); | ||
321 | * | ||
322 | * * perform fb specific ioctl (optional) * | ||
323 | * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, | ||
324 | * unsigned long arg); | ||
325 | * | ||
326 | * * Handle 32bit compat ioctl (optional) * | ||
327 | * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd, | ||
328 | * unsigned long arg); | ||
329 | * | ||
330 | * * perform fb specific mmap * | ||
331 | * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); | ||
332 | * | ||
333 | * * save current hardware state * | ||
334 | * void (*fb_save_state)(struct fb_info *info); | ||
335 | * | ||
336 | * * restore saved state * | ||
337 | * void (*fb_restore_state)(struct fb_info *info); | ||
338 | * } ; | ||
339 | */ | ||
340 | |||
341 | |||
252 | /* ++roman: This structure abstracts from the underlying hardware (ST(e), | 342 | /* ++roman: This structure abstracts from the underlying hardware (ST(e), |
253 | * TT, or Falcon. | 343 | * TT, or Falcon. |
254 | * | 344 | * |
255 | * int (*detect)( void ) | 345 | * int (*detect)(void) |
256 | * This function should detect the current video mode settings and | 346 | * This function should detect the current video mode settings and |
257 | * store them in atafb_predefined[0] for later reference by the | 347 | * store them in atafb_predefined[0] for later reference by the |
258 | * user. Return the index+1 of an equivalent predefined mode or 0 | 348 | * user. Return the index+1 of an equivalent predefined mode or 0 |
259 | * if there is no such. | 349 | * if there is no such. |
260 | * | 350 | * |
261 | * int (*encode_fix)( struct fb_fix_screeninfo *fix, | 351 | * int (*encode_fix)(struct fb_fix_screeninfo *fix, |
262 | * struct atafb_par *par ) | 352 | * struct atafb_par *par) |
263 | * This function should fill in the 'fix' structure based on the | 353 | * This function should fill in the 'fix' structure based on the |
264 | * values in the 'par' structure. | 354 | * values in the 'par' structure. |
265 | * | 355 | * !!! Obsolete, perhaps !!! |
266 | * int (*decode_var)( struct fb_var_screeninfo *var, | 356 | * |
267 | * struct atafb_par *par ) | 357 | * int (*decode_var)(struct fb_var_screeninfo *var, |
358 | * struct atafb_par *par) | ||
268 | * Get the video params out of 'var'. If a value doesn't fit, round | 359 | * Get the video params out of 'var'. If a value doesn't fit, round |
269 | * it up, if it's too big, return EINVAL. | 360 | * it up, if it's too big, return EINVAL. |
270 | * Round up in the following order: bits_per_pixel, xres, yres, | 361 | * Round up in the following order: bits_per_pixel, xres, yres, |
271 | * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, | 362 | * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, |
272 | * horizontal timing, vertical timing. | 363 | * horizontal timing, vertical timing. |
273 | * | 364 | * |
274 | * int (*encode_var)( struct fb_var_screeninfo *var, | 365 | * int (*encode_var)(struct fb_var_screeninfo *var, |
275 | * struct atafb_par *par ); | 366 | * struct atafb_par *par); |
276 | * Fill the 'var' structure based on the values in 'par' and maybe | 367 | * Fill the 'var' structure based on the values in 'par' and maybe |
277 | * other values read out of the hardware. | 368 | * other values read out of the hardware. |
278 | * | 369 | * |
279 | * void (*get_par)( struct atafb_par *par ) | 370 | * void (*get_par)(struct atafb_par *par) |
280 | * Fill the hardware's 'par' structure. | 371 | * Fill the hardware's 'par' structure. |
281 | * | 372 | * !!! Used only by detect() !!! |
282 | * void (*set_par)( struct atafb_par *par ) | 373 | * |
374 | * void (*set_par)(struct atafb_par *par) | ||
283 | * Set the hardware according to 'par'. | 375 | * Set the hardware according to 'par'. |
284 | * | ||
285 | * int (*getcolreg)( unsigned regno, unsigned *red, | ||
286 | * unsigned *green, unsigned *blue, | ||
287 | * unsigned *transp, struct fb_info *info ) | ||
288 | * Read a single color register and split it into | ||
289 | * colors/transparent. Return != 0 for invalid regno. | ||
290 | * | 376 | * |
291 | * void (*set_screen_base)(void *s_base) | 377 | * void (*set_screen_base)(void *s_base) |
292 | * Set the base address of the displayed frame buffer. Only called | 378 | * Set the base address of the displayed frame buffer. Only called |
293 | * if yres_virtual > yres or xres_virtual > xres. | 379 | * if yres_virtual > yres or xres_virtual > xres. |
294 | * | 380 | * |
295 | * int (*blank)( int blank_mode ) | 381 | * int (*blank)(int blank_mode) |
296 | * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then | 382 | * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then |
297 | * the caller blanks by setting the CLUT to all black. Return 0 if blanking | 383 | * the caller blanks by setting the CLUT to all black. Return 0 if blanking |
298 | * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which | 384 | * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which |
299 | * doesn't support it. Implements VESA suspend and powerdown modes on | 385 | * doesn't support it. Implements VESA suspend and powerdown modes on |
300 | * hardware that supports disabling hsync/vsync: | 386 | * hardware that supports disabling hsync/vsync: |
301 | * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown. | 387 | * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown. |
302 | */ | 388 | */ |
303 | 389 | ||
304 | static struct fb_hwswitch { | 390 | static struct fb_hwswitch { |
305 | int (*detect)( void ); | 391 | int (*detect)(void); |
306 | int (*encode_fix)( struct fb_fix_screeninfo *fix, | 392 | int (*encode_fix)(struct fb_fix_screeninfo *fix, |
307 | struct atafb_par *par ); | 393 | struct atafb_par *par); |
308 | int (*decode_var)( struct fb_var_screeninfo *var, | 394 | int (*decode_var)(struct fb_var_screeninfo *var, |
309 | struct atafb_par *par ); | 395 | struct atafb_par *par); |
310 | int (*encode_var)( struct fb_var_screeninfo *var, | 396 | int (*encode_var)(struct fb_var_screeninfo *var, |
311 | struct atafb_par *par ); | 397 | struct atafb_par *par); |
312 | void (*get_par)( struct atafb_par *par ); | 398 | void (*get_par)(struct atafb_par *par); |
313 | void (*set_par)( struct atafb_par *par ); | 399 | void (*set_par)(struct atafb_par *par); |
314 | int (*getcolreg)( unsigned regno, unsigned *red, | ||
315 | unsigned *green, unsigned *blue, | ||
316 | unsigned *transp, struct fb_info *info ); | ||
317 | void (*set_screen_base)(void *s_base); | 400 | void (*set_screen_base)(void *s_base); |
318 | int (*blank)( int blank_mode ); | 401 | int (*blank)(int blank_mode); |
319 | int (*pan_display)( struct fb_var_screeninfo *var, | 402 | int (*pan_display)(struct fb_var_screeninfo *var, |
320 | struct atafb_par *par); | 403 | struct fb_info *info); |
321 | } *fbhw; | 404 | } *fbhw; |
322 | 405 | ||
323 | static char *autodetect_names[] = {"autodetect", NULL}; | 406 | static char *autodetect_names[] = { "autodetect", NULL }; |
324 | static char *stlow_names[] = {"stlow", NULL}; | 407 | static char *stlow_names[] = { "stlow", NULL }; |
325 | static char *stmid_names[] = {"stmid", "default5", NULL}; | 408 | static char *stmid_names[] = { "stmid", "default5", NULL }; |
326 | static char *sthigh_names[] = {"sthigh", "default4", NULL}; | 409 | static char *sthigh_names[] = { "sthigh", "default4", NULL }; |
327 | static char *ttlow_names[] = {"ttlow", NULL}; | 410 | static char *ttlow_names[] = { "ttlow", NULL }; |
328 | static char *ttmid_names[]= {"ttmid", "default1", NULL}; | 411 | static char *ttmid_names[] = { "ttmid", "default1", NULL }; |
329 | static char *tthigh_names[]= {"tthigh", "default2", NULL}; | 412 | static char *tthigh_names[] = { "tthigh", "default2", NULL }; |
330 | static char *vga2_names[] = {"vga2", NULL}; | 413 | static char *vga2_names[] = { "vga2", NULL }; |
331 | static char *vga4_names[] = {"vga4", NULL}; | 414 | static char *vga4_names[] = { "vga4", NULL }; |
332 | static char *vga16_names[] = {"vga16", "default3", NULL}; | 415 | static char *vga16_names[] = { "vga16", "default3", NULL }; |
333 | static char *vga256_names[] = {"vga256", NULL}; | 416 | static char *vga256_names[] = { "vga256", NULL }; |
334 | static char *falh2_names[] = {"falh2", NULL}; | 417 | static char *falh2_names[] = { "falh2", NULL }; |
335 | static char *falh16_names[] = {"falh16", NULL}; | 418 | static char *falh16_names[] = { "falh16", NULL }; |
336 | 419 | ||
337 | static char **fb_var_names[] = { | 420 | static char **fb_var_names[] = { |
338 | /* Writing the name arrays directly in this array (via "(char *[]){...}") | ||
339 | * crashes gcc 2.5.8 (sigsegv) if the inner array | ||
340 | * contains more than two items. I've also seen that all elements | ||
341 | * were identical to the last (my cross-gcc) :-(*/ | ||
342 | autodetect_names, | 421 | autodetect_names, |
343 | stlow_names, | 422 | stlow_names, |
344 | stmid_names, | 423 | stmid_names, |
@@ -353,18 +432,17 @@ static char **fb_var_names[] = { | |||
353 | falh2_names, | 432 | falh2_names, |
354 | falh16_names, | 433 | falh16_names, |
355 | NULL | 434 | NULL |
356 | /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */ | ||
357 | }; | 435 | }; |
358 | 436 | ||
359 | static struct fb_var_screeninfo atafb_predefined[] = { | 437 | static struct fb_var_screeninfo atafb_predefined[] = { |
360 | /* | 438 | /* |
361 | * yres_virtual==0 means use hw-scrolling if possible, else yres | 439 | * yres_virtual == 0 means use hw-scrolling if possible, else yres |
362 | */ | 440 | */ |
363 | { /* autodetect */ | 441 | { /* autodetect */ |
364 | 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ | 442 | 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ |
365 | {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ | 443 | {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ |
366 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 444 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
367 | { /* st low */ | 445 | { /* st low */ |
368 | 320, 200, 320, 0, 0, 0, 4, 0, | 446 | 320, 200, 320, 0, 0, 0, 4, 0, |
369 | {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, | 447 | {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, |
370 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 448 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
@@ -414,27 +492,100 @@ static struct fb_var_screeninfo atafb_predefined[] = { | |||
414 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 492 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
415 | }; | 493 | }; |
416 | 494 | ||
417 | static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); | 495 | static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined); |
418 | 496 | ||
497 | static struct fb_videomode atafb_modedb[] __initdata = { | ||
498 | /* | ||
499 | * Atari Video Modes | ||
500 | * | ||
501 | * If you change these, make sure to update DEFMODE_* as well! | ||
502 | */ | ||
419 | 503 | ||
420 | static int | 504 | /* |
421 | get_video_mode(char *vname) | 505 | * ST/TT Video Modes |
506 | */ | ||
507 | |||
508 | { | ||
509 | /* 320x200, 15 kHz, 60 Hz (ST low) */ | ||
510 | "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4, | ||
511 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
512 | }, { | ||
513 | /* 640x200, 15 kHz, 60 Hz (ST medium) */ | ||
514 | "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4, | ||
515 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
516 | }, { | ||
517 | /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */ | ||
518 | "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4, | ||
519 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
520 | }, { | ||
521 | /* 320x480, 15 kHz, 60 Hz (TT low) */ | ||
522 | "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30, | ||
523 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
524 | }, { | ||
525 | /* 640x480, 29 kHz, 57 Hz (TT medium) */ | ||
526 | "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30, | ||
527 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
528 | }, { | ||
529 | /* 1280x960, 29 kHz, 60 Hz (TT high) */ | ||
530 | "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30, | ||
531 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
532 | }, | ||
533 | |||
534 | /* | ||
535 | * VGA Video Modes | ||
536 | */ | ||
537 | |||
538 | { | ||
539 | /* 640x480, 31 kHz, 60 Hz (VGA) */ | ||
540 | "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3, | ||
541 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
542 | }, { | ||
543 | /* 640x400, 31 kHz, 70 Hz (VGA) */ | ||
544 | "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3, | ||
545 | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
546 | }, | ||
547 | |||
548 | /* | ||
549 | * Falcon HiRes Video Modes | ||
550 | */ | ||
551 | |||
552 | { | ||
553 | /* 896x608, 31 kHz, 60 Hz (Falcon High) */ | ||
554 | "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3, | ||
555 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
556 | }, | ||
557 | }; | ||
558 | |||
559 | #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb) | ||
560 | |||
561 | static char *mode_option __initdata = NULL; | ||
562 | |||
563 | /* default modes */ | ||
564 | |||
565 | #define DEFMODE_TT 5 /* "tt-high" for TT */ | ||
566 | #define DEFMODE_F30 7 /* "vga70" for Falcon */ | ||
567 | #define DEFMODE_STE 2 /* "st-high" for ST/E */ | ||
568 | #define DEFMODE_EXT 6 /* "vga" for external */ | ||
569 | |||
570 | |||
571 | static int get_video_mode(char *vname) | ||
422 | { | 572 | { |
423 | char ***name_list; | 573 | char ***name_list; |
424 | char **name; | 574 | char **name; |
425 | int i; | 575 | int i; |
426 | name_list=fb_var_names; | 576 | |
427 | for (i = 0 ; i < num_atafb_predefined ; i++) { | 577 | name_list = fb_var_names; |
428 | name=*(name_list++); | 578 | for (i = 0; i < num_atafb_predefined; i++) { |
429 | if (! name || ! *name) | 579 | name = *name_list++; |
430 | break; | 580 | if (!name || !*name) |
431 | while (*name) { | 581 | break; |
432 | if (! strcmp(vname, *name)) | 582 | while (*name) { |
433 | return i+1; | 583 | if (!strcmp(vname, *name)) |
434 | name++; | 584 | return i + 1; |
585 | name++; | ||
586 | } | ||
435 | } | 587 | } |
436 | } | 588 | return 0; |
437 | return 0; | ||
438 | } | 589 | } |
439 | 590 | ||
440 | 591 | ||
@@ -443,93 +594,84 @@ get_video_mode(char *vname) | |||
443 | 594 | ||
444 | #ifdef ATAFB_TT | 595 | #ifdef ATAFB_TT |
445 | 596 | ||
446 | static int tt_encode_fix( struct fb_fix_screeninfo *fix, | 597 | static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) |
447 | struct atafb_par *par ) | ||
448 | |||
449 | { | 598 | { |
450 | int mode; | 599 | int mode; |
451 | 600 | ||
452 | strcpy(fix->id,"Atari Builtin"); | 601 | strcpy(fix->id, "Atari Builtin"); |
453 | fix->smem_start = (unsigned long)real_screen_base; | 602 | fix->smem_start = (unsigned long)real_screen_base; |
454 | fix->smem_len = screen_len; | 603 | fix->smem_len = screen_len; |
455 | fix->type=FB_TYPE_INTERLEAVED_PLANES; | 604 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
456 | fix->type_aux=2; | 605 | fix->type_aux = 2; |
457 | fix->visual=FB_VISUAL_PSEUDOCOLOR; | 606 | fix->visual = FB_VISUAL_PSEUDOCOLOR; |
458 | mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK; | 607 | mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK; |
459 | if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) { | 608 | if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) { |
460 | fix->type=FB_TYPE_PACKED_PIXELS; | 609 | fix->type = FB_TYPE_PACKED_PIXELS; |
461 | fix->type_aux=0; | 610 | fix->type_aux = 0; |
462 | if (mode == TT_SHIFTER_TTHIGH) | 611 | if (mode == TT_SHIFTER_TTHIGH) |
463 | fix->visual=FB_VISUAL_MONO01; | 612 | fix->visual = FB_VISUAL_MONO01; |
464 | } | 613 | } |
465 | fix->xpanstep=0; | 614 | fix->xpanstep = 0; |
466 | fix->ypanstep=1; | 615 | fix->ypanstep = 1; |
467 | fix->ywrapstep=0; | 616 | fix->ywrapstep = 0; |
468 | fix->line_length = 0; | 617 | fix->line_length = 0; |
469 | fix->accel = FB_ACCEL_ATARIBLITT; | 618 | fix->accel = FB_ACCEL_ATARIBLITT; |
470 | return 0; | 619 | return 0; |
471 | } | 620 | } |
472 | 621 | ||
473 | 622 | static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
474 | static int tt_decode_var( struct fb_var_screeninfo *var, | ||
475 | struct atafb_par *par ) | ||
476 | { | 623 | { |
477 | int xres=var->xres; | 624 | int xres = var->xres; |
478 | int yres=var->yres; | 625 | int yres = var->yres; |
479 | int bpp=var->bits_per_pixel; | 626 | int bpp = var->bits_per_pixel; |
480 | int linelen; | 627 | int linelen; |
481 | int yres_virtual = var->yres_virtual; | 628 | int yres_virtual = var->yres_virtual; |
482 | 629 | ||
483 | if (mono_moni) { | 630 | if (mono_moni) { |
484 | if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2) | 631 | if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2) |
485 | return -EINVAL; | 632 | return -EINVAL; |
486 | par->hw.tt.mode=TT_SHIFTER_TTHIGH; | 633 | par->hw.tt.mode = TT_SHIFTER_TTHIGH; |
487 | xres=sttt_xres*2; | 634 | xres = sttt_xres * 2; |
488 | yres=tt_yres*2; | 635 | yres = tt_yres * 2; |
489 | bpp=1; | 636 | bpp = 1; |
490 | } else { | 637 | } else { |
491 | if (bpp > 8 || xres > sttt_xres || yres > tt_yres) | 638 | if (bpp > 8 || xres > sttt_xres || yres > tt_yres) |
492 | return -EINVAL; | 639 | return -EINVAL; |
493 | if (bpp > 4) { | 640 | if (bpp > 4) { |
494 | if (xres > sttt_xres/2 || yres > tt_yres) | 641 | if (xres > sttt_xres / 2 || yres > tt_yres) |
495 | return -EINVAL; | 642 | return -EINVAL; |
496 | par->hw.tt.mode=TT_SHIFTER_TTLOW; | 643 | par->hw.tt.mode = TT_SHIFTER_TTLOW; |
497 | xres=sttt_xres/2; | 644 | xres = sttt_xres / 2; |
498 | yres=tt_yres; | 645 | yres = tt_yres; |
499 | bpp=8; | 646 | bpp = 8; |
500 | } | 647 | } else if (bpp > 2) { |
501 | else if (bpp > 2) { | ||
502 | if (xres > sttt_xres || yres > tt_yres) | 648 | if (xres > sttt_xres || yres > tt_yres) |
503 | return -EINVAL; | 649 | return -EINVAL; |
504 | if (xres > sttt_xres/2 || yres > st_yres/2) { | 650 | if (xres > sttt_xres / 2 || yres > st_yres / 2) { |
505 | par->hw.tt.mode=TT_SHIFTER_TTMID; | 651 | par->hw.tt.mode = TT_SHIFTER_TTMID; |
506 | xres=sttt_xres; | 652 | xres = sttt_xres; |
507 | yres=tt_yres; | 653 | yres = tt_yres; |
508 | bpp=4; | 654 | bpp = 4; |
509 | } | 655 | } else { |
510 | else { | 656 | par->hw.tt.mode = TT_SHIFTER_STLOW; |
511 | par->hw.tt.mode=TT_SHIFTER_STLOW; | 657 | xres = sttt_xres / 2; |
512 | xres=sttt_xres/2; | 658 | yres = st_yres / 2; |
513 | yres=st_yres/2; | 659 | bpp = 4; |
514 | bpp=4; | ||
515 | } | 660 | } |
516 | } | 661 | } else if (bpp > 1) { |
517 | else if (bpp > 1) { | 662 | if (xres > sttt_xres || yres > st_yres / 2) |
518 | if (xres > sttt_xres || yres > st_yres/2) | ||
519 | return -EINVAL; | 663 | return -EINVAL; |
520 | par->hw.tt.mode=TT_SHIFTER_STMID; | 664 | par->hw.tt.mode = TT_SHIFTER_STMID; |
521 | xres=sttt_xres; | 665 | xres = sttt_xres; |
522 | yres=st_yres/2; | 666 | yres = st_yres / 2; |
523 | bpp=2; | 667 | bpp = 2; |
524 | } | 668 | } else if (var->xres > sttt_xres || var->yres > st_yres) { |
525 | else if (var->xres > sttt_xres || var->yres > st_yres) { | ||
526 | return -EINVAL; | 669 | return -EINVAL; |
527 | } | 670 | } else { |
528 | else { | 671 | par->hw.tt.mode = TT_SHIFTER_STHIGH; |
529 | par->hw.tt.mode=TT_SHIFTER_STHIGH; | 672 | xres = sttt_xres; |
530 | xres=sttt_xres; | 673 | yres = st_yres; |
531 | yres=st_yres; | 674 | bpp = 1; |
532 | bpp=1; | ||
533 | } | 675 | } |
534 | } | 676 | } |
535 | if (yres_virtual <= 0) | 677 | if (yres_virtual <= 0) |
@@ -537,10 +679,10 @@ static int tt_decode_var( struct fb_var_screeninfo *var, | |||
537 | else if (yres_virtual < yres) | 679 | else if (yres_virtual < yres) |
538 | yres_virtual = yres; | 680 | yres_virtual = yres; |
539 | if (var->sync & FB_SYNC_EXT) | 681 | if (var->sync & FB_SYNC_EXT) |
540 | par->hw.tt.sync=0; | 682 | par->hw.tt.sync = 0; |
541 | else | 683 | else |
542 | par->hw.tt.sync=1; | 684 | par->hw.tt.sync = 1; |
543 | linelen=xres*bpp/8; | 685 | linelen = xres * bpp / 8; |
544 | if (yres_virtual * linelen > screen_len && screen_len) | 686 | if (yres_virtual * linelen > screen_len && screen_len) |
545 | return -EINVAL; | 687 | return -EINVAL; |
546 | if (yres * linelen > screen_len && screen_len) | 688 | if (yres * linelen > screen_len && screen_len) |
@@ -552,154 +694,123 @@ static int tt_decode_var( struct fb_var_screeninfo *var, | |||
552 | return 0; | 694 | return 0; |
553 | } | 695 | } |
554 | 696 | ||
555 | static int tt_encode_var( struct fb_var_screeninfo *var, | 697 | static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) |
556 | struct atafb_par *par ) | ||
557 | { | 698 | { |
558 | int linelen; | 699 | int linelen; |
559 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 700 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
560 | var->red.offset=0; | 701 | var->red.offset = 0; |
561 | var->red.length=4; | 702 | var->red.length = 4; |
562 | var->red.msb_right=0; | 703 | var->red.msb_right = 0; |
563 | var->grayscale=0; | 704 | var->grayscale = 0; |
564 | 705 | ||
565 | var->pixclock=31041; | 706 | var->pixclock = 31041; |
566 | var->left_margin=120; /* these may be incorrect */ | 707 | var->left_margin = 120; /* these may be incorrect */ |
567 | var->right_margin=100; | 708 | var->right_margin = 100; |
568 | var->upper_margin=8; | 709 | var->upper_margin = 8; |
569 | var->lower_margin=16; | 710 | var->lower_margin = 16; |
570 | var->hsync_len=140; | 711 | var->hsync_len = 140; |
571 | var->vsync_len=30; | 712 | var->vsync_len = 30; |
572 | 713 | ||
573 | var->height=-1; | 714 | var->height = -1; |
574 | var->width=-1; | 715 | var->width = -1; |
575 | 716 | ||
576 | if (par->hw.tt.sync & 1) | 717 | if (par->hw.tt.sync & 1) |
577 | var->sync=0; | 718 | var->sync = 0; |
578 | else | 719 | else |
579 | var->sync=FB_SYNC_EXT; | 720 | var->sync = FB_SYNC_EXT; |
580 | 721 | ||
581 | switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) { | 722 | switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) { |
582 | case TT_SHIFTER_STLOW: | 723 | case TT_SHIFTER_STLOW: |
583 | var->xres=sttt_xres/2; | 724 | var->xres = sttt_xres / 2; |
584 | var->xres_virtual=sttt_xres_virtual/2; | 725 | var->xres_virtual = sttt_xres_virtual / 2; |
585 | var->yres=st_yres/2; | 726 | var->yres = st_yres / 2; |
586 | var->bits_per_pixel=4; | 727 | var->bits_per_pixel = 4; |
587 | break; | 728 | break; |
588 | case TT_SHIFTER_STMID: | 729 | case TT_SHIFTER_STMID: |
589 | var->xres=sttt_xres; | 730 | var->xres = sttt_xres; |
590 | var->xres_virtual=sttt_xres_virtual; | 731 | var->xres_virtual = sttt_xres_virtual; |
591 | var->yres=st_yres/2; | 732 | var->yres = st_yres / 2; |
592 | var->bits_per_pixel=2; | 733 | var->bits_per_pixel = 2; |
593 | break; | 734 | break; |
594 | case TT_SHIFTER_STHIGH: | 735 | case TT_SHIFTER_STHIGH: |
595 | var->xres=sttt_xres; | 736 | var->xres = sttt_xres; |
596 | var->xres_virtual=sttt_xres_virtual; | 737 | var->xres_virtual = sttt_xres_virtual; |
597 | var->yres=st_yres; | 738 | var->yres = st_yres; |
598 | var->bits_per_pixel=1; | 739 | var->bits_per_pixel = 1; |
599 | break; | 740 | break; |
600 | case TT_SHIFTER_TTLOW: | 741 | case TT_SHIFTER_TTLOW: |
601 | var->xres=sttt_xres/2; | 742 | var->xres = sttt_xres / 2; |
602 | var->xres_virtual=sttt_xres_virtual/2; | 743 | var->xres_virtual = sttt_xres_virtual / 2; |
603 | var->yres=tt_yres; | 744 | var->yres = tt_yres; |
604 | var->bits_per_pixel=8; | 745 | var->bits_per_pixel = 8; |
605 | break; | 746 | break; |
606 | case TT_SHIFTER_TTMID: | 747 | case TT_SHIFTER_TTMID: |
607 | var->xres=sttt_xres; | 748 | var->xres = sttt_xres; |
608 | var->xres_virtual=sttt_xres_virtual; | 749 | var->xres_virtual = sttt_xres_virtual; |
609 | var->yres=tt_yres; | 750 | var->yres = tt_yres; |
610 | var->bits_per_pixel=4; | 751 | var->bits_per_pixel = 4; |
611 | break; | 752 | break; |
612 | case TT_SHIFTER_TTHIGH: | 753 | case TT_SHIFTER_TTHIGH: |
613 | var->red.length=0; | 754 | var->red.length = 0; |
614 | var->xres=sttt_xres*2; | 755 | var->xres = sttt_xres * 2; |
615 | var->xres_virtual=sttt_xres_virtual*2; | 756 | var->xres_virtual = sttt_xres_virtual * 2; |
616 | var->yres=tt_yres*2; | 757 | var->yres = tt_yres * 2; |
617 | var->bits_per_pixel=1; | 758 | var->bits_per_pixel = 1; |
618 | break; | 759 | break; |
619 | } | 760 | } |
620 | var->blue=var->green=var->red; | 761 | var->blue = var->green = var->red; |
621 | var->transp.offset=0; | 762 | var->transp.offset = 0; |
622 | var->transp.length=0; | 763 | var->transp.length = 0; |
623 | var->transp.msb_right=0; | 764 | var->transp.msb_right = 0; |
624 | linelen=var->xres_virtual * var->bits_per_pixel / 8; | 765 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
625 | if (! use_hwscroll) | 766 | if (!use_hwscroll) |
626 | var->yres_virtual=var->yres; | 767 | var->yres_virtual = var->yres; |
627 | else if (screen_len) { | 768 | else if (screen_len) { |
628 | if (par->yres_virtual) | 769 | if (par->yres_virtual) |
629 | var->yres_virtual = par->yres_virtual; | 770 | var->yres_virtual = par->yres_virtual; |
630 | else | 771 | else |
631 | /* yres_virtual==0 means use maximum */ | 772 | /* yres_virtual == 0 means use maximum */ |
632 | var->yres_virtual = screen_len / linelen; | 773 | var->yres_virtual = screen_len / linelen; |
633 | } else { | 774 | } else { |
634 | if (hwscroll < 0) | 775 | if (hwscroll < 0) |
635 | var->yres_virtual = 2 * var->yres; | 776 | var->yres_virtual = 2 * var->yres; |
636 | else | 777 | else |
637 | var->yres_virtual=var->yres+hwscroll * 16; | 778 | var->yres_virtual = var->yres + hwscroll * 16; |
638 | } | 779 | } |
639 | var->xoffset=0; | 780 | var->xoffset = 0; |
640 | if (screen_base) | 781 | if (screen_base) |
641 | var->yoffset=(par->screen_base - screen_base)/linelen; | 782 | var->yoffset = (par->screen_base - screen_base) / linelen; |
642 | else | 783 | else |
643 | var->yoffset=0; | 784 | var->yoffset = 0; |
644 | var->nonstd=0; | 785 | var->nonstd = 0; |
645 | var->activate=0; | 786 | var->activate = 0; |
646 | var->vmode=FB_VMODE_NONINTERLACED; | 787 | var->vmode = FB_VMODE_NONINTERLACED; |
647 | return 0; | 788 | return 0; |
648 | } | 789 | } |
649 | 790 | ||
650 | 791 | static void tt_get_par(struct atafb_par *par) | |
651 | static void tt_get_par( struct atafb_par *par ) | ||
652 | { | 792 | { |
653 | unsigned long addr; | 793 | unsigned long addr; |
654 | par->hw.tt.mode=shifter_tt.tt_shiftmode; | 794 | par->hw.tt.mode = shifter_tt.tt_shiftmode; |
655 | par->hw.tt.sync=shifter.syncmode; | 795 | par->hw.tt.sync = shifter.syncmode; |
656 | addr = ((shifter.bas_hi & 0xff) << 16) | | 796 | addr = ((shifter.bas_hi & 0xff) << 16) | |
657 | ((shifter.bas_md & 0xff) << 8) | | 797 | ((shifter.bas_md & 0xff) << 8) | |
658 | ((shifter.bas_lo & 0xff)); | 798 | ((shifter.bas_lo & 0xff)); |
659 | par->screen_base = phys_to_virt(addr); | 799 | par->screen_base = phys_to_virt(addr); |
660 | } | 800 | } |
661 | 801 | ||
662 | static void tt_set_par( struct atafb_par *par ) | 802 | static void tt_set_par(struct atafb_par *par) |
663 | { | 803 | { |
664 | shifter_tt.tt_shiftmode=par->hw.tt.mode; | 804 | shifter_tt.tt_shiftmode = par->hw.tt.mode; |
665 | shifter.syncmode=par->hw.tt.sync; | 805 | shifter.syncmode = par->hw.tt.sync; |
666 | /* only set screen_base if really necessary */ | 806 | /* only set screen_base if really necessary */ |
667 | if (current_par.screen_base != par->screen_base) | 807 | if (current_par.screen_base != par->screen_base) |
668 | fbhw->set_screen_base(par->screen_base); | 808 | fbhw->set_screen_base(par->screen_base); |
669 | } | 809 | } |
670 | 810 | ||
671 | 811 | static int tt_setcolreg(unsigned int regno, unsigned int red, | |
672 | static int tt_getcolreg(unsigned regno, unsigned *red, | 812 | unsigned int green, unsigned int blue, |
673 | unsigned *green, unsigned *blue, | 813 | unsigned int transp, struct fb_info *info) |
674 | unsigned *transp, struct fb_info *info) | ||
675 | { | ||
676 | int t, col; | ||
677 | |||
678 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) | ||
679 | regno += 254; | ||
680 | if (regno > 255) | ||
681 | return 1; | ||
682 | t = tt_palette[regno]; | ||
683 | col = t & 15; | ||
684 | col |= col << 4; | ||
685 | col |= col << 8; | ||
686 | *blue = col; | ||
687 | col = (t >> 4) & 15; | ||
688 | col |= col << 4; | ||
689 | col |= col << 8; | ||
690 | *green = col; | ||
691 | col = (t >> 8) & 15; | ||
692 | col |= col << 4; | ||
693 | col |= col << 8; | ||
694 | *red = col; | ||
695 | *transp = 0; | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | |||
700 | static int tt_setcolreg(unsigned regno, unsigned red, | ||
701 | unsigned green, unsigned blue, | ||
702 | unsigned transp, struct fb_info *info) | ||
703 | { | 814 | { |
704 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) | 815 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) |
705 | regno += 254; | 816 | regno += 254; |
@@ -708,15 +819,14 @@ static int tt_setcolreg(unsigned regno, unsigned red, | |||
708 | tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) | | 819 | tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) | |
709 | (blue >> 12)); | 820 | (blue >> 12)); |
710 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == | 821 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == |
711 | TT_SHIFTER_STHIGH && regno == 254) | 822 | TT_SHIFTER_STHIGH && regno == 254) |
712 | tt_palette[0] = 0; | 823 | tt_palette[0] = 0; |
713 | return 0; | 824 | return 0; |
714 | } | 825 | } |
715 | 826 | ||
716 | 827 | static int tt_detect(void) | |
717 | static int tt_detect( void ) | 828 | { |
718 | 829 | struct atafb_par par; | |
719 | { struct atafb_par par; | ||
720 | 830 | ||
721 | /* Determine the connected monitor: The DMA sound must be | 831 | /* Determine the connected monitor: The DMA sound must be |
722 | * disabled before reading the MFP GPIP, because the Sound | 832 | * disabled before reading the MFP GPIP, because the Sound |
@@ -726,9 +836,9 @@ static int tt_detect( void ) | |||
726 | * announced that the Eagle is TT compatible, but only the PCM is | 836 | * announced that the Eagle is TT compatible, but only the PCM is |
727 | * missing... | 837 | * missing... |
728 | */ | 838 | */ |
729 | if (ATARIHW_PRESENT(PCM_8BIT)) { | 839 | if (ATARIHW_PRESENT(PCM_8BIT)) { |
730 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; | 840 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; |
731 | udelay(20); /* wait a while for things to settle down */ | 841 | udelay(20); /* wait a while for things to settle down */ |
732 | } | 842 | } |
733 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; | 843 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; |
734 | 844 | ||
@@ -755,19 +865,24 @@ static struct pixel_clock { | |||
755 | unsigned long f; /* f/[Hz] */ | 865 | unsigned long f; /* f/[Hz] */ |
756 | unsigned long t; /* t/[ps] (=1/f) */ | 866 | unsigned long t; /* t/[ps] (=1/f) */ |
757 | int right, hsync, left; /* standard timing in clock cycles, not pixel */ | 867 | int right, hsync, left; /* standard timing in clock cycles, not pixel */ |
758 | /* hsync initialized in falcon_detect() */ | 868 | /* hsync initialized in falcon_detect() */ |
759 | int sync_mask; /* or-mask for hw.falcon.sync to set this clock */ | 869 | int sync_mask; /* or-mask for hw.falcon.sync to set this clock */ |
760 | int control_mask; /* ditto, for hw.falcon.vid_control */ | 870 | int control_mask; /* ditto, for hw.falcon.vid_control */ |
761 | } | 871 | } f25 = { |
762 | f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25}, | 872 | 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25 |
763 | f32 = {32000000, 31250, 18, 0, 42, 0x0, 0}, | 873 | }, f32 = { |
764 | fext = { 0, 0, 18, 0, 42, 0x1, 0}; | 874 | 32000000, 31250, 18, 0, 42, 0x0, 0 |
875 | }, fext = { | ||
876 | 0, 0, 18, 0, 42, 0x1, 0 | ||
877 | }; | ||
765 | 878 | ||
766 | /* VIDEL-prescale values [mon_type][pixel_length from VCO] */ | 879 | /* VIDEL-prescale values [mon_type][pixel_length from VCO] */ |
767 | static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}}; | 880 | static int vdl_prescale[4][3] = { |
881 | { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 } | ||
882 | }; | ||
768 | 883 | ||
769 | /* Default hsync timing [mon_type] in picoseconds */ | 884 | /* Default hsync timing [mon_type] in picoseconds */ |
770 | static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000}; | 885 | static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 }; |
771 | 886 | ||
772 | #ifdef FBCON_HAS_CFB16 | 887 | #ifdef FBCON_HAS_CFB16 |
773 | static u16 fbcon_cfb16_cmap[16]; | 888 | static u16 fbcon_cfb16_cmap[16]; |
@@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16]; | |||
775 | 890 | ||
776 | static inline int hxx_prescale(struct falcon_hw *hw) | 891 | static inline int hxx_prescale(struct falcon_hw *hw) |
777 | { | 892 | { |
778 | return hw->ste_mode ? 16 : | 893 | return hw->ste_mode ? 16 |
779 | vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; | 894 | : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; |
780 | } | 895 | } |
781 | 896 | ||
782 | static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | 897 | static int falcon_encode_fix(struct fb_fix_screeninfo *fix, |
783 | struct atafb_par *par ) | 898 | struct atafb_par *par) |
784 | { | 899 | { |
785 | strcpy(fix->id, "Atari Builtin"); | 900 | strcpy(fix->id, "Atari Builtin"); |
786 | fix->smem_start = (unsigned long)real_screen_base; | 901 | fix->smem_start = (unsigned long)real_screen_base; |
@@ -796,8 +911,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | |||
796 | fix->type_aux = 0; | 911 | fix->type_aux = 0; |
797 | /* no smooth scrolling with longword aligned video mem */ | 912 | /* no smooth scrolling with longword aligned video mem */ |
798 | fix->xpanstep = 32; | 913 | fix->xpanstep = 32; |
799 | } | 914 | } else if (par->hw.falcon.f_shift & 0x100) { |
800 | else if (par->hw.falcon.f_shift & 0x100) { | ||
801 | fix->type = FB_TYPE_PACKED_PIXELS; | 915 | fix->type = FB_TYPE_PACKED_PIXELS; |
802 | fix->type_aux = 0; | 916 | fix->type_aux = 0; |
803 | /* Is this ok or should it be DIRECTCOLOR? */ | 917 | /* Is this ok or should it be DIRECTCOLOR? */ |
@@ -809,9 +923,8 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | |||
809 | return 0; | 923 | return 0; |
810 | } | 924 | } |
811 | 925 | ||
812 | 926 | static int falcon_decode_var(struct fb_var_screeninfo *var, | |
813 | static int falcon_decode_var( struct fb_var_screeninfo *var, | 927 | struct atafb_par *par) |
814 | struct atafb_par *par ) | ||
815 | { | 928 | { |
816 | int bpp = var->bits_per_pixel; | 929 | int bpp = var->bits_per_pixel; |
817 | int xres = var->xres; | 930 | int xres = var->xres; |
@@ -823,17 +936,19 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
823 | int linelen; | 936 | int linelen; |
824 | int interlace = 0, doubleline = 0; | 937 | int interlace = 0, doubleline = 0; |
825 | struct pixel_clock *pclock; | 938 | struct pixel_clock *pclock; |
826 | int plen; /* width of pixel in clock cycles */ | 939 | int plen; /* width of pixel in clock cycles */ |
827 | int xstretch; | 940 | int xstretch; |
828 | int prescale; | 941 | int prescale; |
829 | int longoffset = 0; | 942 | int longoffset = 0; |
830 | int hfreq, vfreq; | 943 | int hfreq, vfreq; |
944 | int hdb_off, hde_off, base_off; | ||
945 | int gstart, gend1, gend2, align; | ||
831 | 946 | ||
832 | /* | 947 | /* |
833 | Get the video params out of 'var'. If a value doesn't fit, round | 948 | Get the video params out of 'var'. If a value doesn't fit, round |
834 | it up, if it's too big, return EINVAL. | 949 | it up, if it's too big, return EINVAL. |
835 | Round up in the following order: bits_per_pixel, xres, yres, | 950 | Round up in the following order: bits_per_pixel, xres, yres, |
836 | xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, | 951 | xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, |
837 | horizontal timing, vertical timing. | 952 | horizontal timing, vertical timing. |
838 | 953 | ||
839 | There is a maximum of screen resolution determined by pixelclock | 954 | There is a maximum of screen resolution determined by pixelclock |
@@ -843,11 +958,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
843 | Frequency range for multisync monitors is given via command line. | 958 | Frequency range for multisync monitors is given via command line. |
844 | For TV and SM124 both frequencies are fixed. | 959 | For TV and SM124 both frequencies are fixed. |
845 | 960 | ||
846 | X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0) | 961 | X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0) |
847 | Y % 16 == 0 to fit 8x16 font | 962 | Y % 16 == 0 to fit 8x16 font |
848 | Y % 8 == 0 if Y<400 | 963 | Y % 8 == 0 if Y<400 |
849 | 964 | ||
850 | Currently interlace and doubleline mode in var are ignored. | 965 | Currently interlace and doubleline mode in var are ignored. |
851 | On SM124 and TV only the standard resolutions can be used. | 966 | On SM124 and TV only the standard resolutions can be used. |
852 | */ | 967 | */ |
853 | 968 | ||
@@ -855,43 +970,38 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
855 | if (!xres || !yres || !bpp) | 970 | if (!xres || !yres || !bpp) |
856 | return -EINVAL; | 971 | return -EINVAL; |
857 | 972 | ||
858 | if (mon_type == F_MON_SM && bpp != 1) { | 973 | if (mon_type == F_MON_SM && bpp != 1) |
859 | return -EINVAL; | 974 | return -EINVAL; |
860 | } | 975 | |
861 | else if (bpp <= 1) { | 976 | if (bpp <= 1) { |
862 | bpp = 1; | 977 | bpp = 1; |
863 | par->hw.falcon.f_shift = 0x400; | 978 | par->hw.falcon.f_shift = 0x400; |
864 | par->hw.falcon.st_shift = 0x200; | 979 | par->hw.falcon.st_shift = 0x200; |
865 | } | 980 | } else if (bpp <= 2) { |
866 | else if (bpp <= 2) { | ||
867 | bpp = 2; | 981 | bpp = 2; |
868 | par->hw.falcon.f_shift = 0x000; | 982 | par->hw.falcon.f_shift = 0x000; |
869 | par->hw.falcon.st_shift = 0x100; | 983 | par->hw.falcon.st_shift = 0x100; |
870 | } | 984 | } else if (bpp <= 4) { |
871 | else if (bpp <= 4) { | ||
872 | bpp = 4; | 985 | bpp = 4; |
873 | par->hw.falcon.f_shift = 0x000; | 986 | par->hw.falcon.f_shift = 0x000; |
874 | par->hw.falcon.st_shift = 0x000; | 987 | par->hw.falcon.st_shift = 0x000; |
875 | } | 988 | } else if (bpp <= 8) { |
876 | else if (bpp <= 8) { | ||
877 | bpp = 8; | 989 | bpp = 8; |
878 | par->hw.falcon.f_shift = 0x010; | 990 | par->hw.falcon.f_shift = 0x010; |
879 | } | 991 | } else if (bpp <= 16) { |
880 | else if (bpp <= 16) { | 992 | bpp = 16; /* packed pixel mode */ |
881 | bpp = 16; /* packed pixel mode */ | 993 | par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ |
882 | par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ | 994 | } else |
883 | } | ||
884 | else | ||
885 | return -EINVAL; | 995 | return -EINVAL; |
886 | par->hw.falcon.bpp = bpp; | 996 | par->hw.falcon.bpp = bpp; |
887 | 997 | ||
888 | if (mon_type == F_MON_SM || DontCalcRes) { | 998 | if (mon_type == F_MON_SM || DontCalcRes) { |
889 | /* Skip all calculations. VGA/TV/SC1224 only supported. */ | 999 | /* Skip all calculations. VGA/TV/SC1224 only supported. */ |
890 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 1000 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
891 | 1001 | ||
892 | if (bpp > myvar->bits_per_pixel || | 1002 | if (bpp > myvar->bits_per_pixel || |
893 | var->xres > myvar->xres || | 1003 | var->xres > myvar->xres || |
894 | var->yres > myvar->yres) | 1004 | var->yres > myvar->yres) |
895 | return -EINVAL; | 1005 | return -EINVAL; |
896 | fbhw->get_par(par); /* Current par will be new par */ | 1006 | fbhw->get_par(par); /* Current par will be new par */ |
897 | goto set_screen_base; /* Don't forget this */ | 1007 | goto set_screen_base; /* Don't forget this */ |
@@ -910,8 +1020,8 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
910 | yres = 400; | 1020 | yres = 400; |
911 | 1021 | ||
912 | /* 2 planes must use STE compatibility mode */ | 1022 | /* 2 planes must use STE compatibility mode */ |
913 | par->hw.falcon.ste_mode = bpp==2; | 1023 | par->hw.falcon.ste_mode = bpp == 2; |
914 | par->hw.falcon.mono = bpp==1; | 1024 | par->hw.falcon.mono = bpp == 1; |
915 | 1025 | ||
916 | /* Total and visible scanline length must be a multiple of one longword, | 1026 | /* Total and visible scanline length must be a multiple of one longword, |
917 | * this and the console fontwidth yields the alignment for xres and | 1027 | * this and the console fontwidth yields the alignment for xres and |
@@ -967,8 +1077,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
967 | left_margin = hsync_len = 128 / plen; | 1077 | left_margin = hsync_len = 128 / plen; |
968 | right_margin = 0; | 1078 | right_margin = 0; |
969 | /* TODO set all margins */ | 1079 | /* TODO set all margins */ |
970 | } | 1080 | } else |
971 | else | ||
972 | #endif | 1081 | #endif |
973 | if (mon_type == F_MON_SC || mon_type == F_MON_TV) { | 1082 | if (mon_type == F_MON_SC || mon_type == F_MON_TV) { |
974 | plen = 2 * xstretch; | 1083 | plen = 2 * xstretch; |
@@ -1002,26 +1111,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1002 | vsync_len *= 2; | 1111 | vsync_len *= 2; |
1003 | } | 1112 | } |
1004 | } | 1113 | } |
1005 | } | 1114 | } else { /* F_MON_VGA */ |
1006 | else | ||
1007 | { /* F_MON_VGA */ | ||
1008 | if (bpp == 16) | 1115 | if (bpp == 16) |
1009 | xstretch = 2; /* Double pixel width only for hicolor */ | 1116 | xstretch = 2; /* Double pixel width only for hicolor */ |
1010 | /* Default values are used for vert./hor. timing if no pixelclock given. */ | 1117 | /* Default values are used for vert./hor. timing if no pixelclock given. */ |
1011 | if (var->pixclock == 0) { | 1118 | if (var->pixclock == 0) { |
1012 | int linesize; | 1119 | int linesize; |
1013 | 1120 | ||
1014 | /* Choose master pixelclock depending on hor. timing */ | 1121 | /* Choose master pixelclock depending on hor. timing */ |
1015 | plen = 1 * xstretch; | 1122 | plen = 1 * xstretch; |
1016 | if ((plen * xres + f25.right+f25.hsync+f25.left) * | 1123 | if ((plen * xres + f25.right + f25.hsync + f25.left) * |
1017 | fb_info.monspecs.hfmin < f25.f) | 1124 | fb_info.monspecs.hfmin < f25.f) |
1018 | pclock = &f25; | 1125 | pclock = &f25; |
1019 | else if ((plen * xres + f32.right+f32.hsync+f32.left) * | 1126 | else if ((plen * xres + f32.right + f32.hsync + |
1020 | fb_info.monspecs.hfmin < f32.f) | 1127 | f32.left) * fb_info.monspecs.hfmin < f32.f) |
1021 | pclock = &f32; | 1128 | pclock = &f32; |
1022 | else if ((plen * xres + fext.right+fext.hsync+fext.left) * | 1129 | else if ((plen * xres + fext.right + fext.hsync + |
1023 | fb_info.monspecs.hfmin < fext.f | 1130 | fext.left) * fb_info.monspecs.hfmin < fext.f && |
1024 | && fext.f) | 1131 | fext.f) |
1025 | pclock = &fext; | 1132 | pclock = &fext; |
1026 | else | 1133 | else |
1027 | return -EINVAL; | 1134 | return -EINVAL; |
@@ -1033,22 +1140,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1033 | upper_margin = 31; | 1140 | upper_margin = 31; |
1034 | lower_margin = 11; | 1141 | lower_margin = 11; |
1035 | vsync_len = 3; | 1142 | vsync_len = 3; |
1036 | } | 1143 | } else { |
1037 | else { | ||
1038 | /* Choose largest pixelclock <= wanted clock */ | 1144 | /* Choose largest pixelclock <= wanted clock */ |
1039 | int i; | 1145 | int i; |
1040 | unsigned long pcl = ULONG_MAX; | 1146 | unsigned long pcl = ULONG_MAX; |
1041 | pclock = 0; | 1147 | pclock = 0; |
1042 | for (i=1; i <= 4; i *= 2) { | 1148 | for (i = 1; i <= 4; i *= 2) { |
1043 | if (f25.t*i >= var->pixclock && f25.t*i < pcl) { | 1149 | if (f25.t * i >= var->pixclock && |
1150 | f25.t * i < pcl) { | ||
1044 | pcl = f25.t * i; | 1151 | pcl = f25.t * i; |
1045 | pclock = &f25; | 1152 | pclock = &f25; |
1046 | } | 1153 | } |
1047 | if (f32.t*i >= var->pixclock && f32.t*i < pcl) { | 1154 | if (f32.t * i >= var->pixclock && |
1155 | f32.t * i < pcl) { | ||
1048 | pcl = f32.t * i; | 1156 | pcl = f32.t * i; |
1049 | pclock = &f32; | 1157 | pclock = &f32; |
1050 | } | 1158 | } |
1051 | if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) { | 1159 | if (fext.t && fext.t * i >= var->pixclock && |
1160 | fext.t * i < pcl) { | ||
1052 | pcl = fext.t * i; | 1161 | pcl = fext.t * i; |
1053 | pclock = &fext; | 1162 | pclock = &fext; |
1054 | } | 1163 | } |
@@ -1070,8 +1179,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1070 | upper_margin = (upper_margin + 1) / 2; | 1179 | upper_margin = (upper_margin + 1) / 2; |
1071 | lower_margin = (lower_margin + 1) / 2; | 1180 | lower_margin = (lower_margin + 1) / 2; |
1072 | vsync_len = (vsync_len + 1) / 2; | 1181 | vsync_len = (vsync_len + 1) / 2; |
1073 | } | 1182 | } else if (var->vmode & FB_VMODE_DOUBLE) { |
1074 | else if (var->vmode & FB_VMODE_DOUBLE) { | ||
1075 | /* External unit is [double lines per frame] */ | 1183 | /* External unit is [double lines per frame] */ |
1076 | upper_margin *= 2; | 1184 | upper_margin *= 2; |
1077 | lower_margin *= 2; | 1185 | lower_margin *= 2; |
@@ -1079,7 +1187,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1079 | } | 1187 | } |
1080 | } | 1188 | } |
1081 | if (pclock == &fext) | 1189 | if (pclock == &fext) |
1082 | longoffset = 1; /* VIDEL doesn't synchronize on short offset */ | 1190 | longoffset = 1; /* VIDEL doesn't synchronize on short offset */ |
1083 | } | 1191 | } |
1084 | /* Is video bus bandwidth (32MB/s) too low for this resolution? */ | 1192 | /* Is video bus bandwidth (32MB/s) too low for this resolution? */ |
1085 | /* this is definitely wrong if bus clock != 32MHz */ | 1193 | /* this is definitely wrong if bus clock != 32MHz */ |
@@ -1098,7 +1206,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1098 | * between interlace and non-interlace without messing around | 1206 | * between interlace and non-interlace without messing around |
1099 | * with these. | 1207 | * with these. |
1100 | */ | 1208 | */ |
1101 | again: | 1209 | again: |
1102 | /* Set base_offset 128 and video bus width */ | 1210 | /* Set base_offset 128 and video bus width */ |
1103 | par->hw.falcon.vid_control = mon_type | f030_bus_width; | 1211 | par->hw.falcon.vid_control = mon_type | f030_bus_width; |
1104 | if (!longoffset) | 1212 | if (!longoffset) |
@@ -1112,37 +1220,34 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1112 | /* External or internal clock */ | 1220 | /* External or internal clock */ |
1113 | par->hw.falcon.sync = pclock->sync_mask | 0x2; | 1221 | par->hw.falcon.sync = pclock->sync_mask | 0x2; |
1114 | /* Pixellength and prescale */ | 1222 | /* Pixellength and prescale */ |
1115 | par->hw.falcon.vid_mode = (2/plen) << 2; | 1223 | par->hw.falcon.vid_mode = (2 / plen) << 2; |
1116 | if (doubleline) | 1224 | if (doubleline) |
1117 | par->hw.falcon.vid_mode |= VMO_DOUBLE; | 1225 | par->hw.falcon.vid_mode |= VMO_DOUBLE; |
1118 | if (interlace) | 1226 | if (interlace) |
1119 | par->hw.falcon.vid_mode |= VMO_INTER; | 1227 | par->hw.falcon.vid_mode |= VMO_INTER; |
1120 | 1228 | ||
1121 | /********************* | 1229 | /********************* |
1122 | Horizontal timing: unit = [master clock cycles] | 1230 | * Horizontal timing: unit = [master clock cycles] |
1123 | unit of hxx-registers: [master clock cycles * prescale] | 1231 | * unit of hxx-registers: [master clock cycles * prescale] |
1124 | Hxx-registers are 9 bit wide | 1232 | * Hxx-registers are 9 bit wide |
1125 | 1233 | * | |
1126 | 1 line = ((hht + 2) * 2 * prescale) clock cycles | 1234 | * 1 line = ((hht + 2) * 2 * prescale) clock cycles |
1127 | 1235 | * | |
1128 | graphic output = hdb & 0x200 ? | 1236 | * graphic output = hdb & 0x200 ? |
1129 | ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff: | 1237 | * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff: |
1130 | ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff | 1238 | * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff |
1131 | (this must be a multiple of plen*128/bpp, on VGA pixels | 1239 | * (this must be a multiple of plen*128/bpp, on VGA pixels |
1132 | to the right may be cut off with a bigger right margin) | 1240 | * to the right may be cut off with a bigger right margin) |
1133 | 1241 | * | |
1134 | start of graphics relative to start of 1st halfline = hdb & 0x200 ? | 1242 | * start of graphics relative to start of 1st halfline = hdb & 0x200 ? |
1135 | (hdb - hht - 2) * prescale + hdboff : | 1243 | * (hdb - hht - 2) * prescale + hdboff : |
1136 | hdb * prescale + hdboff | 1244 | * hdb * prescale + hdboff |
1137 | 1245 | * | |
1138 | end of graphics relative to start of 1st halfline = | 1246 | * end of graphics relative to start of 1st halfline = |
1139 | (hde + hht + 2) * prescale + hdeoff | 1247 | * (hde + hht + 2) * prescale + hdeoff |
1140 | *********************/ | 1248 | *********************/ |
1141 | /* Calculate VIDEL registers */ | 1249 | /* Calculate VIDEL registers */ |
1142 | { | 1250 | { |
1143 | int hdb_off, hde_off, base_off; | ||
1144 | int gstart, gend1, gend2, align; | ||
1145 | |||
1146 | prescale = hxx_prescale(&par->hw.falcon); | 1251 | prescale = hxx_prescale(&par->hw.falcon); |
1147 | base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128; | 1252 | base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128; |
1148 | 1253 | ||
@@ -1154,8 +1259,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1154 | align = 1; | 1259 | align = 1; |
1155 | hde_off = 0; | 1260 | hde_off = 0; |
1156 | hdb_off = (base_off + 16 * plen) + prescale; | 1261 | hdb_off = (base_off + 16 * plen) + prescale; |
1157 | } | 1262 | } else { |
1158 | else { | ||
1159 | align = 128 / bpp; | 1263 | align = 128 / bpp; |
1160 | hde_off = ((128 / bpp + 2) * plen); | 1264 | hde_off = ((128 / bpp + 2) * plen); |
1161 | if (par->hw.falcon.ste_mode) | 1265 | if (par->hw.falcon.ste_mode) |
@@ -1164,23 +1268,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1164 | hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale; | 1268 | hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale; |
1165 | } | 1269 | } |
1166 | 1270 | ||
1167 | gstart = (prescale/2 + plen * left_margin) / prescale; | 1271 | gstart = (prescale / 2 + plen * left_margin) / prescale; |
1168 | /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */ | 1272 | /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */ |
1169 | gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale; | 1273 | gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale; |
1170 | /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */ | 1274 | /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */ |
1171 | gend2 = gstart + xres * plen / prescale; | 1275 | gend2 = gstart + xres * plen / prescale; |
1172 | par->HHT = plen * (left_margin + xres + right_margin) / | 1276 | par->HHT = plen * (left_margin + xres + right_margin) / |
1173 | (2 * prescale) - 2; | 1277 | (2 * prescale) - 2; |
1174 | /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/ | 1278 | /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/ |
1175 | 1279 | ||
1176 | par->HDB = gstart - hdb_off/prescale; | 1280 | par->HDB = gstart - hdb_off / prescale; |
1177 | par->HBE = gstart; | 1281 | par->HBE = gstart; |
1178 | if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200; | 1282 | if (par->HDB < 0) |
1179 | par->HDE = gend1 - par->HHT - 2 - hde_off/prescale; | 1283 | par->HDB += par->HHT + 2 + 0x200; |
1284 | par->HDE = gend1 - par->HHT - 2 - hde_off / prescale; | ||
1180 | par->HBB = gend2 - par->HHT - 2; | 1285 | par->HBB = gend2 - par->HHT - 2; |
1181 | #if 0 | 1286 | #if 0 |
1182 | /* One more Videl constraint: data fetch of two lines must not overlap */ | 1287 | /* One more Videl constraint: data fetch of two lines must not overlap */ |
1183 | if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { | 1288 | if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { |
1184 | /* if this happens increase margins, decrease hfreq. */ | 1289 | /* if this happens increase margins, decrease hfreq. */ |
1185 | } | 1290 | } |
1186 | #endif | 1291 | #endif |
@@ -1189,11 +1294,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1189 | par->HSS = par->HHT + 2 - plen * hsync_len / prescale; | 1294 | par->HSS = par->HHT + 2 - plen * hsync_len / prescale; |
1190 | if (par->HSS < par->HBB) | 1295 | if (par->HSS < par->HBB) |
1191 | par->HSS = par->HBB; | 1296 | par->HSS = par->HBB; |
1192 | } | 1297 | } |
1193 | 1298 | ||
1194 | /* check hor. frequency */ | 1299 | /* check hor. frequency */ |
1195 | hfreq = pclock->f / ((par->HHT+2)*prescale*2); | 1300 | hfreq = pclock->f / ((par->HHT + 2) * prescale * 2); |
1196 | if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) { | 1301 | if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) { |
1197 | /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ | 1302 | /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ |
1198 | /* Too high -> enlarge margin */ | 1303 | /* Too high -> enlarge margin */ |
1199 | left_margin += 1; | 1304 | left_margin += 1; |
@@ -1213,12 +1318,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1213 | par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */ | 1318 | par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */ |
1214 | par->VDB = par->VBE; | 1319 | par->VDB = par->VBE; |
1215 | par->VDE = yres; | 1320 | par->VDE = yres; |
1216 | if (!interlace) par->VDE <<= 1; | 1321 | if (!interlace) |
1217 | if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */ | 1322 | par->VDE <<= 1; |
1323 | if (doubleline) | ||
1324 | par->VDE <<= 1; /* VDE now half lines per (half-)frame */ | ||
1218 | par->VDE += par->VDB; | 1325 | par->VDE += par->VDB; |
1219 | par->VBB = par->VDE; | 1326 | par->VBB = par->VDE; |
1220 | par->VFT = par->VBB + (lower_margin * 2 - 1) - 1; | 1327 | par->VFT = par->VBB + (lower_margin * 2 - 1) - 1; |
1221 | par->VSS = par->VFT+1 - (vsync_len * 2 - 1); | 1328 | par->VSS = par->VFT + 1 - (vsync_len * 2 - 1); |
1222 | /* vbb,vss,vft must be even in interlace mode */ | 1329 | /* vbb,vss,vft must be even in interlace mode */ |
1223 | if (interlace) { | 1330 | if (interlace) { |
1224 | par->VBB++; | 1331 | par->VBB++; |
@@ -1229,55 +1336,53 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1229 | /* V-frequency check, hope I didn't create any loop here. */ | 1336 | /* V-frequency check, hope I didn't create any loop here. */ |
1230 | /* Interlace and doubleline are mutually exclusive. */ | 1337 | /* Interlace and doubleline are mutually exclusive. */ |
1231 | vfreq = (hfreq * 2) / (par->VFT + 1); | 1338 | vfreq = (hfreq * 2) / (par->VFT + 1); |
1232 | if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { | 1339 | if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { |
1233 | /* Too high -> try again with doubleline */ | 1340 | /* Too high -> try again with doubleline */ |
1234 | doubleline = 1; | 1341 | doubleline = 1; |
1235 | goto again; | 1342 | goto again; |
1236 | } | 1343 | } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { |
1237 | else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { | ||
1238 | /* Too low -> try again with interlace */ | 1344 | /* Too low -> try again with interlace */ |
1239 | interlace = 1; | 1345 | interlace = 1; |
1240 | goto again; | 1346 | goto again; |
1241 | } | 1347 | } else if (vfreq < fb_info.monspecs.vfmin && doubleline) { |
1242 | else if (vfreq < fb_info.monspecs.vfmin && doubleline) { | ||
1243 | /* Doubleline too low -> clear doubleline and enlarge margins */ | 1348 | /* Doubleline too low -> clear doubleline and enlarge margins */ |
1244 | int lines; | 1349 | int lines; |
1245 | doubleline = 0; | 1350 | doubleline = 0; |
1246 | for (lines=0; | 1351 | for (lines = 0; |
1247 | (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax; | 1352 | (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) > |
1353 | fb_info.monspecs.vfmax; | ||
1248 | lines++) | 1354 | lines++) |
1249 | ; | 1355 | ; |
1250 | upper_margin += lines; | 1356 | upper_margin += lines; |
1251 | lower_margin += lines; | 1357 | lower_margin += lines; |
1252 | goto again; | 1358 | goto again; |
1253 | } | 1359 | } else if (vfreq > fb_info.monspecs.vfmax && doubleline) { |
1254 | else if (vfreq > fb_info.monspecs.vfmax && doubleline) { | ||
1255 | /* Doubleline too high -> enlarge margins */ | 1360 | /* Doubleline too high -> enlarge margins */ |
1256 | int lines; | 1361 | int lines; |
1257 | for (lines=0; | 1362 | for (lines = 0; |
1258 | (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; | 1363 | (hfreq * 2) / (par->VFT + 1 + 4 * lines) > |
1259 | lines+=2) | 1364 | fb_info.monspecs.vfmax; |
1365 | lines += 2) | ||
1260 | ; | 1366 | ; |
1261 | upper_margin += lines; | 1367 | upper_margin += lines; |
1262 | lower_margin += lines; | 1368 | lower_margin += lines; |
1263 | goto again; | 1369 | goto again; |
1264 | } | 1370 | } else if (vfreq > fb_info.monspecs.vfmax && interlace) { |
1265 | else if (vfreq > fb_info.monspecs.vfmax && interlace) { | ||
1266 | /* Interlace, too high -> enlarge margins */ | 1371 | /* Interlace, too high -> enlarge margins */ |
1267 | int lines; | 1372 | int lines; |
1268 | for (lines=0; | 1373 | for (lines = 0; |
1269 | (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; | 1374 | (hfreq * 2) / (par->VFT + 1 + 4 * lines) > |
1375 | fb_info.monspecs.vfmax; | ||
1270 | lines++) | 1376 | lines++) |
1271 | ; | 1377 | ; |
1272 | upper_margin += lines; | 1378 | upper_margin += lines; |
1273 | lower_margin += lines; | 1379 | lower_margin += lines; |
1274 | goto again; | 1380 | goto again; |
1275 | } | 1381 | } else if (vfreq < fb_info.monspecs.vfmin || |
1276 | else if (vfreq < fb_info.monspecs.vfmin || | 1382 | vfreq > fb_info.monspecs.vfmax) |
1277 | vfreq > fb_info.monspecs.vfmax) | ||
1278 | return -EINVAL; | 1383 | return -EINVAL; |
1279 | 1384 | ||
1280 | set_screen_base: | 1385 | set_screen_base: |
1281 | linelen = xres_virtual * bpp / 8; | 1386 | linelen = xres_virtual * bpp / 8; |
1282 | if (yres_virtual * linelen > screen_len && screen_len) | 1387 | if (yres_virtual * linelen > screen_len && screen_len) |
1283 | return -EINVAL; | 1388 | return -EINVAL; |
@@ -1289,11 +1394,20 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1289 | par->screen_base = screen_base + var->yoffset * linelen; | 1394 | par->screen_base = screen_base + var->yoffset * linelen; |
1290 | par->hw.falcon.xoffset = 0; | 1395 | par->hw.falcon.xoffset = 0; |
1291 | 1396 | ||
1397 | // FIXME!!! sort of works, no crash | ||
1398 | //par->next_line = linelen; | ||
1399 | //par->next_plane = yres_virtual * linelen; | ||
1400 | par->next_line = linelen; | ||
1401 | par->next_plane = 2; | ||
1402 | // crashes | ||
1403 | //par->next_plane = linelen; | ||
1404 | //par->next_line = yres_virtual * linelen; | ||
1405 | |||
1292 | return 0; | 1406 | return 0; |
1293 | } | 1407 | } |
1294 | 1408 | ||
1295 | static int falcon_encode_var( struct fb_var_screeninfo *var, | 1409 | static int falcon_encode_var(struct fb_var_screeninfo *var, |
1296 | struct atafb_par *par ) | 1410 | struct atafb_par *par) |
1297 | { | 1411 | { |
1298 | /* !!! only for VGA !!! */ | 1412 | /* !!! only for VGA !!! */ |
1299 | int linelen; | 1413 | int linelen; |
@@ -1306,10 +1420,10 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1306 | var->pixclock = hw->sync & 0x1 ? fext.t : | 1420 | var->pixclock = hw->sync & 0x1 ? fext.t : |
1307 | hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; | 1421 | hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; |
1308 | 1422 | ||
1309 | var->height=-1; | 1423 | var->height = -1; |
1310 | var->width=-1; | 1424 | var->width = -1; |
1311 | 1425 | ||
1312 | var->sync=0; | 1426 | var->sync = 0; |
1313 | if (hw->vid_control & VCO_HSYPOS) | 1427 | if (hw->vid_control & VCO_HSYPOS) |
1314 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 1428 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
1315 | if (hw->vid_control & VCO_VSYPOS) | 1429 | if (hw->vid_control & VCO_VSYPOS) |
@@ -1320,7 +1434,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1320 | var->vmode |= FB_VMODE_INTERLACED; | 1434 | var->vmode |= FB_VMODE_INTERLACED; |
1321 | if (hw->vid_mode & VMO_DOUBLE) | 1435 | if (hw->vid_mode & VMO_DOUBLE) |
1322 | var->vmode |= FB_VMODE_DOUBLE; | 1436 | var->vmode |= FB_VMODE_DOUBLE; |
1323 | 1437 | ||
1324 | /* visible y resolution: | 1438 | /* visible y resolution: |
1325 | * Graphics display starts at line VDB and ends at line | 1439 | * Graphics display starts at line VDB and ends at line |
1326 | * VDE. If interlace mode off unit of VC-registers is | 1440 | * VDE. If interlace mode off unit of VC-registers is |
@@ -1332,14 +1446,15 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1332 | if (var->vmode & FB_VMODE_DOUBLE) | 1446 | if (var->vmode & FB_VMODE_DOUBLE) |
1333 | var->yres >>= 1; | 1447 | var->yres >>= 1; |
1334 | 1448 | ||
1335 | /* to get bpp, we must examine f_shift and st_shift. | 1449 | /* |
1450 | * to get bpp, we must examine f_shift and st_shift. | ||
1336 | * f_shift is valid if any of bits no. 10, 8 or 4 | 1451 | * f_shift is valid if any of bits no. 10, 8 or 4 |
1337 | * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. | 1452 | * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. |
1338 | * if bit 10 set then bit 8 and bit 4 don't care... | 1453 | * if bit 10 set then bit 8 and bit 4 don't care... |
1339 | * If all these bits are 0 get display depth from st_shift | 1454 | * If all these bits are 0 get display depth from st_shift |
1340 | * (as for ST and STE) | 1455 | * (as for ST and STE) |
1341 | */ | 1456 | */ |
1342 | if (hw->f_shift & 0x400) /* 2 colors */ | 1457 | if (hw->f_shift & 0x400) /* 2 colors */ |
1343 | var->bits_per_pixel = 1; | 1458 | var->bits_per_pixel = 1; |
1344 | else if (hw->f_shift & 0x100) /* hicolor */ | 1459 | else if (hw->f_shift & 0x100) /* hicolor */ |
1345 | var->bits_per_pixel = 16; | 1460 | var->bits_per_pixel = 16; |
@@ -1349,7 +1464,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1349 | var->bits_per_pixel = 4; | 1464 | var->bits_per_pixel = 4; |
1350 | else if (hw->st_shift == 0x100) | 1465 | else if (hw->st_shift == 0x100) |
1351 | var->bits_per_pixel = 2; | 1466 | var->bits_per_pixel = 2; |
1352 | else /* if (hw->st_shift == 0x200) */ | 1467 | else /* if (hw->st_shift == 0x200) */ |
1353 | var->bits_per_pixel = 1; | 1468 | var->bits_per_pixel = 1; |
1354 | 1469 | ||
1355 | var->xres = hw->line_width * 16 / var->bits_per_pixel; | 1470 | var->xres = hw->line_width * 16 / var->bits_per_pixel; |
@@ -1358,42 +1473,42 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1358 | var->xres_virtual += 16; | 1473 | var->xres_virtual += 16; |
1359 | 1474 | ||
1360 | if (var->bits_per_pixel == 16) { | 1475 | if (var->bits_per_pixel == 16) { |
1361 | var->red.offset=11; | 1476 | var->red.offset = 11; |
1362 | var->red.length=5; | 1477 | var->red.length = 5; |
1363 | var->red.msb_right=0; | 1478 | var->red.msb_right = 0; |
1364 | var->green.offset=5; | 1479 | var->green.offset = 5; |
1365 | var->green.length=6; | 1480 | var->green.length = 6; |
1366 | var->green.msb_right=0; | 1481 | var->green.msb_right = 0; |
1367 | var->blue.offset=0; | 1482 | var->blue.offset = 0; |
1368 | var->blue.length=5; | 1483 | var->blue.length = 5; |
1369 | var->blue.msb_right=0; | 1484 | var->blue.msb_right = 0; |
1370 | } | 1485 | } else { |
1371 | else { | 1486 | var->red.offset = 0; |
1372 | var->red.offset=0; | ||
1373 | var->red.length = hw->ste_mode ? 4 : 6; | 1487 | var->red.length = hw->ste_mode ? 4 : 6; |
1374 | var->red.msb_right=0; | 1488 | if (var->red.length > var->bits_per_pixel) |
1375 | var->grayscale=0; | 1489 | var->red.length = var->bits_per_pixel; |
1376 | var->blue=var->green=var->red; | 1490 | var->red.msb_right = 0; |
1491 | var->grayscale = 0; | ||
1492 | var->blue = var->green = var->red; | ||
1377 | } | 1493 | } |
1378 | var->transp.offset=0; | 1494 | var->transp.offset = 0; |
1379 | var->transp.length=0; | 1495 | var->transp.length = 0; |
1380 | var->transp.msb_right=0; | 1496 | var->transp.msb_right = 0; |
1381 | 1497 | ||
1382 | linelen = var->xres_virtual * var->bits_per_pixel / 8; | 1498 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
1383 | if (screen_len) { | 1499 | if (screen_len) { |
1384 | if (par->yres_virtual) | 1500 | if (par->yres_virtual) |
1385 | var->yres_virtual = par->yres_virtual; | 1501 | var->yres_virtual = par->yres_virtual; |
1386 | else | 1502 | else |
1387 | /* yres_virtual==0 means use maximum */ | 1503 | /* yres_virtual == 0 means use maximum */ |
1388 | var->yres_virtual = screen_len / linelen; | 1504 | var->yres_virtual = screen_len / linelen; |
1389 | } | 1505 | } else { |
1390 | else { | ||
1391 | if (hwscroll < 0) | 1506 | if (hwscroll < 0) |
1392 | var->yres_virtual = 2 * var->yres; | 1507 | var->yres_virtual = 2 * var->yres; |
1393 | else | 1508 | else |
1394 | var->yres_virtual=var->yres+hwscroll * 16; | 1509 | var->yres_virtual = var->yres + hwscroll * 16; |
1395 | } | 1510 | } |
1396 | var->xoffset=0; /* TODO change this */ | 1511 | var->xoffset = 0; /* TODO change this */ |
1397 | 1512 | ||
1398 | /* hdX-offsets */ | 1513 | /* hdX-offsets */ |
1399 | prescale = hxx_prescale(hw); | 1514 | prescale = hxx_prescale(hw); |
@@ -1402,8 +1517,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1402 | if (hw->f_shift & 0x100) { | 1517 | if (hw->f_shift & 0x100) { |
1403 | hde_off = 0; | 1518 | hde_off = 0; |
1404 | hdb_off = (base_off + 16 * plen) + prescale; | 1519 | hdb_off = (base_off + 16 * plen) + prescale; |
1405 | } | 1520 | } else { |
1406 | else { | ||
1407 | hde_off = ((128 / var->bits_per_pixel + 2) * plen); | 1521 | hde_off = ((128 / var->bits_per_pixel + 2) * plen); |
1408 | if (hw->ste_mode) | 1522 | if (hw->ste_mode) |
1409 | hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) | 1523 | hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) |
@@ -1415,8 +1529,8 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1415 | 1529 | ||
1416 | /* Right margin includes hsync */ | 1530 | /* Right margin includes hsync */ |
1417 | var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - | 1531 | var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - |
1418 | (hw->hdb & 0x200 ? 2+hw->hht : 0)); | 1532 | (hw->hdb & 0x200 ? 2 + hw->hht : 0)); |
1419 | if (hw->ste_mode || mon_type!=F_MON_VGA) | 1533 | if (hw->ste_mode || mon_type != F_MON_VGA) |
1420 | var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; | 1534 | var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; |
1421 | else | 1535 | else |
1422 | /* can't use this in ste_mode, because hbb is +1 off */ | 1536 | /* can't use this in ste_mode, because hbb is +1 off */ |
@@ -1424,15 +1538,14 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1424 | var->hsync_len = prescale * (hw->hht + 2 - hw->hss); | 1538 | var->hsync_len = prescale * (hw->hht + 2 - hw->hss); |
1425 | 1539 | ||
1426 | /* Lower margin includes vsync */ | 1540 | /* Lower margin includes vsync */ |
1427 | var->upper_margin = hw->vdb / 2 ; /* round down to full lines */ | 1541 | var->upper_margin = hw->vdb / 2; /* round down to full lines */ |
1428 | var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */ | 1542 | var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */ |
1429 | var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */ | 1543 | var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */ |
1430 | if (var->vmode & FB_VMODE_INTERLACED) { | 1544 | if (var->vmode & FB_VMODE_INTERLACED) { |
1431 | var->upper_margin *= 2; | 1545 | var->upper_margin *= 2; |
1432 | var->lower_margin *= 2; | 1546 | var->lower_margin *= 2; |
1433 | var->vsync_len *= 2; | 1547 | var->vsync_len *= 2; |
1434 | } | 1548 | } else if (var->vmode & FB_VMODE_DOUBLE) { |
1435 | else if (var->vmode & FB_VMODE_DOUBLE) { | ||
1436 | var->upper_margin = (var->upper_margin + 1) / 2; | 1549 | var->upper_margin = (var->upper_margin + 1) / 2; |
1437 | var->lower_margin = (var->lower_margin + 1) / 2; | 1550 | var->lower_margin = (var->lower_margin + 1) / 2; |
1438 | var->vsync_len = (var->vsync_len + 1) / 2; | 1551 | var->vsync_len = (var->vsync_len + 1) / 2; |
@@ -1447,20 +1560,19 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1447 | var->lower_margin -= var->vsync_len; | 1560 | var->lower_margin -= var->vsync_len; |
1448 | 1561 | ||
1449 | if (screen_base) | 1562 | if (screen_base) |
1450 | var->yoffset=(par->screen_base - screen_base)/linelen; | 1563 | var->yoffset = (par->screen_base - screen_base) / linelen; |
1451 | else | 1564 | else |
1452 | var->yoffset=0; | 1565 | var->yoffset = 0; |
1453 | var->nonstd=0; /* what is this for? */ | 1566 | var->nonstd = 0; /* what is this for? */ |
1454 | var->activate=0; | 1567 | var->activate = 0; |
1455 | return 0; | 1568 | return 0; |
1456 | } | 1569 | } |
1457 | 1570 | ||
1458 | 1571 | static int f_change_mode; | |
1459 | static int f_change_mode = 0; | ||
1460 | static struct falcon_hw f_new_mode; | 1572 | static struct falcon_hw f_new_mode; |
1461 | static int f_pan_display = 0; | 1573 | static int f_pan_display; |
1462 | 1574 | ||
1463 | static void falcon_get_par( struct atafb_par *par ) | 1575 | static void falcon_get_par(struct atafb_par *par) |
1464 | { | 1576 | { |
1465 | unsigned long addr; | 1577 | unsigned long addr; |
1466 | struct falcon_hw *hw = &par->hw.falcon; | 1578 | struct falcon_hw *hw = &par->hw.falcon; |
@@ -1492,12 +1604,12 @@ static void falcon_get_par( struct atafb_par *par ) | |||
1492 | par->screen_base = phys_to_virt(addr); | 1604 | par->screen_base = phys_to_virt(addr); |
1493 | 1605 | ||
1494 | /* derived parameters */ | 1606 | /* derived parameters */ |
1495 | hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100; | 1607 | hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100; |
1496 | hw->mono = (hw->f_shift & 0x400) || | 1608 | hw->mono = (hw->f_shift & 0x400) || |
1497 | ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200); | 1609 | ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200); |
1498 | } | 1610 | } |
1499 | 1611 | ||
1500 | static void falcon_set_par( struct atafb_par *par ) | 1612 | static void falcon_set_par(struct atafb_par *par) |
1501 | { | 1613 | { |
1502 | f_change_mode = 0; | 1614 | f_change_mode = 0; |
1503 | 1615 | ||
@@ -1519,8 +1631,7 @@ static void falcon_set_par( struct atafb_par *par ) | |||
1519 | f_change_mode = 1; | 1631 | f_change_mode = 1; |
1520 | } | 1632 | } |
1521 | 1633 | ||
1522 | 1634 | static irqreturn_t falcon_vbl_switcher(int irq, void *dummy) | |
1523 | static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | ||
1524 | { | 1635 | { |
1525 | struct falcon_hw *hw = &f_new_mode; | 1636 | struct falcon_hw *hw = &f_new_mode; |
1526 | 1637 | ||
@@ -1529,11 +1640,10 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1529 | 1640 | ||
1530 | if (hw->sync & 0x1) { | 1641 | if (hw->sync & 0x1) { |
1531 | /* Enable external pixelclock. This code only for ScreenWonder */ | 1642 | /* Enable external pixelclock. This code only for ScreenWonder */ |
1532 | *(volatile unsigned short*)0xffff9202 = 0xffbf; | 1643 | *(volatile unsigned short *)0xffff9202 = 0xffbf; |
1533 | } | 1644 | } else { |
1534 | else { | ||
1535 | /* Turn off external clocks. Read sets all output bits to 1. */ | 1645 | /* Turn off external clocks. Read sets all output bits to 1. */ |
1536 | *(volatile unsigned short*)0xffff9202; | 1646 | *(volatile unsigned short *)0xffff9202; |
1537 | } | 1647 | } |
1538 | shifter.syncmode = hw->sync; | 1648 | shifter.syncmode = hw->sync; |
1539 | 1649 | ||
@@ -1550,15 +1660,14 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1550 | videl.vde = hw->vde; | 1660 | videl.vde = hw->vde; |
1551 | videl.vss = hw->vss; | 1661 | videl.vss = hw->vss; |
1552 | 1662 | ||
1553 | videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ | 1663 | videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ |
1554 | if (hw->ste_mode) { | 1664 | if (hw->ste_mode) { |
1555 | videl.st_shift = hw->st_shift; /* write enables STE palette */ | 1665 | videl.st_shift = hw->st_shift; /* write enables STE palette */ |
1556 | } | 1666 | } else { |
1557 | else { | ||
1558 | /* IMPORTANT: | 1667 | /* IMPORTANT: |
1559 | * set st_shift 0, so we can tell the screen-depth if f_shift==0. | 1668 | * set st_shift 0, so we can tell the screen-depth if f_shift == 0. |
1560 | * Writing 0 to f_shift enables 4 plane Falcon mode but | 1669 | * Writing 0 to f_shift enables 4 plane Falcon mode but |
1561 | * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible | 1670 | * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible |
1562 | * with Falcon palette. | 1671 | * with Falcon palette. |
1563 | */ | 1672 | */ |
1564 | videl.st_shift = 0; | 1673 | videl.st_shift = 0; |
@@ -1580,12 +1689,13 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1580 | return IRQ_HANDLED; | 1689 | return IRQ_HANDLED; |
1581 | } | 1690 | } |
1582 | 1691 | ||
1583 | 1692 | static int falcon_pan_display(struct fb_var_screeninfo *var, | |
1584 | static int falcon_pan_display( struct fb_var_screeninfo *var, | 1693 | struct fb_info *info) |
1585 | struct atafb_par *par ) | ||
1586 | { | 1694 | { |
1695 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
1696 | |||
1587 | int xoffset; | 1697 | int xoffset; |
1588 | int bpp = fb_display[fb_info.currcon].var.bits_per_pixel; | 1698 | int bpp = info->var.bits_per_pixel; |
1589 | 1699 | ||
1590 | if (bpp == 1) | 1700 | if (bpp == 1) |
1591 | var->xoffset = up(var->xoffset, 32); | 1701 | var->xoffset = up(var->xoffset, 32); |
@@ -1596,45 +1706,24 @@ static int falcon_pan_display( struct fb_var_screeninfo *var, | |||
1596 | var->xoffset = up(var->xoffset, 2); | 1706 | var->xoffset = up(var->xoffset, 2); |
1597 | } | 1707 | } |
1598 | par->hw.falcon.line_offset = bpp * | 1708 | par->hw.falcon.line_offset = bpp * |
1599 | (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16; | 1709 | (info->var.xres_virtual - info->var.xres) / 16; |
1600 | if (par->hw.falcon.xoffset) | 1710 | if (par->hw.falcon.xoffset) |
1601 | par->hw.falcon.line_offset -= bpp; | 1711 | par->hw.falcon.line_offset -= bpp; |
1602 | xoffset = var->xoffset - par->hw.falcon.xoffset; | 1712 | xoffset = var->xoffset - par->hw.falcon.xoffset; |
1603 | 1713 | ||
1604 | par->screen_base = screen_base + | 1714 | par->screen_base = screen_base + |
1605 | (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8; | 1715 | (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8; |
1606 | if (fbhw->set_screen_base) | 1716 | if (fbhw->set_screen_base) |
1607 | fbhw->set_screen_base (par->screen_base); | 1717 | fbhw->set_screen_base(par->screen_base); |
1608 | else | 1718 | else |
1609 | return -EINVAL; /* shouldn't happen */ | 1719 | return -EINVAL; /* shouldn't happen */ |
1610 | f_pan_display = 1; | 1720 | f_pan_display = 1; |
1611 | return 0; | 1721 | return 0; |
1612 | } | 1722 | } |
1613 | 1723 | ||
1614 | 1724 | static int falcon_setcolreg(unsigned int regno, unsigned int red, | |
1615 | static int falcon_getcolreg( unsigned regno, unsigned *red, | 1725 | unsigned int green, unsigned int blue, |
1616 | unsigned *green, unsigned *blue, | 1726 | unsigned int transp, struct fb_info *info) |
1617 | unsigned *transp, struct fb_info *info ) | ||
1618 | { unsigned long col; | ||
1619 | |||
1620 | if (regno > 255) | ||
1621 | return 1; | ||
1622 | /* This works in STE-mode (with 4bit/color) since f030_col-registers | ||
1623 | * hold up to 6bit/color. | ||
1624 | * Even with hicolor r/g/b=5/6/5 bit! | ||
1625 | */ | ||
1626 | col = f030_col[regno]; | ||
1627 | *red = (col >> 16) & 0xff00; | ||
1628 | *green = (col >> 8) & 0xff00; | ||
1629 | *blue = (col << 8) & 0xff00; | ||
1630 | *transp = 0; | ||
1631 | return 0; | ||
1632 | } | ||
1633 | |||
1634 | |||
1635 | static int falcon_setcolreg( unsigned regno, unsigned red, | ||
1636 | unsigned green, unsigned blue, | ||
1637 | unsigned transp, struct fb_info *info ) | ||
1638 | { | 1727 | { |
1639 | if (regno > 255) | 1728 | if (regno > 255) |
1640 | return 1; | 1729 | return 1; |
@@ -1655,13 +1744,12 @@ static int falcon_setcolreg( unsigned regno, unsigned red, | |||
1655 | return 0; | 1744 | return 0; |
1656 | } | 1745 | } |
1657 | 1746 | ||
1658 | 1747 | static int falcon_blank(int blank_mode) | |
1659 | static int falcon_blank( int blank_mode ) | ||
1660 | { | 1748 | { |
1661 | /* ++guenther: we can switch off graphics by changing VDB and VDE, | 1749 | /* ++guenther: we can switch off graphics by changing VDB and VDE, |
1662 | * so VIDEL doesn't hog the bus while saving. | 1750 | * so VIDEL doesn't hog the bus while saving. |
1663 | * (this may affect usleep()). | 1751 | * (this may affect usleep()). |
1664 | */ | 1752 | */ |
1665 | int vdb, vss, hbe, hss; | 1753 | int vdb, vss, hbe, hss; |
1666 | 1754 | ||
1667 | if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ | 1755 | if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ |
@@ -1694,14 +1782,13 @@ static int falcon_blank( int blank_mode ) | |||
1694 | return 0; | 1782 | return 0; |
1695 | } | 1783 | } |
1696 | 1784 | ||
1697 | 1785 | static int falcon_detect(void) | |
1698 | static int falcon_detect( void ) | ||
1699 | { | 1786 | { |
1700 | struct atafb_par par; | 1787 | struct atafb_par par; |
1701 | unsigned char fhw; | 1788 | unsigned char fhw; |
1702 | 1789 | ||
1703 | /* Determine connected monitor and set monitor parameters */ | 1790 | /* Determine connected monitor and set monitor parameters */ |
1704 | fhw = *(unsigned char*)0xffff8006; | 1791 | fhw = *(unsigned char *)0xffff8006; |
1705 | mon_type = fhw >> 6 & 0x3; | 1792 | mon_type = fhw >> 6 & 0x3; |
1706 | /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ | 1793 | /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ |
1707 | f030_bus_width = fhw << 6 & 0x80; | 1794 | f030_bus_width = fhw << 6 & 0x80; |
@@ -1715,7 +1802,7 @@ static int falcon_detect( void ) | |||
1715 | case F_MON_SC: | 1802 | case F_MON_SC: |
1716 | case F_MON_TV: | 1803 | case F_MON_TV: |
1717 | /* PAL...NTSC */ | 1804 | /* PAL...NTSC */ |
1718 | fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ | 1805 | fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ |
1719 | fb_info.monspecs.vfmax = 60; | 1806 | fb_info.monspecs.vfmax = 60; |
1720 | fb_info.monspecs.hfmin = 15620; | 1807 | fb_info.monspecs.hfmin = 15620; |
1721 | fb_info.monspecs.hfmax = 15755; | 1808 | fb_info.monspecs.hfmax = 15755; |
@@ -1740,13 +1827,12 @@ static int falcon_detect( void ) | |||
1740 | 1827 | ||
1741 | #ifdef ATAFB_STE | 1828 | #ifdef ATAFB_STE |
1742 | 1829 | ||
1743 | static int stste_encode_fix( struct fb_fix_screeninfo *fix, | 1830 | static int stste_encode_fix(struct fb_fix_screeninfo *fix, |
1744 | struct atafb_par *par ) | 1831 | struct atafb_par *par) |
1745 | |||
1746 | { | 1832 | { |
1747 | int mode; | 1833 | int mode; |
1748 | 1834 | ||
1749 | strcpy(fix->id,"Atari Builtin"); | 1835 | strcpy(fix->id, "Atari Builtin"); |
1750 | fix->smem_start = (unsigned long)real_screen_base; | 1836 | fix->smem_start = (unsigned long)real_screen_base; |
1751 | fix->smem_len = screen_len; | 1837 | fix->smem_len = screen_len; |
1752 | fix->type = FB_TYPE_INTERLEAVED_PLANES; | 1838 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
@@ -1771,43 +1857,40 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, | |||
1771 | return 0; | 1857 | return 0; |
1772 | } | 1858 | } |
1773 | 1859 | ||
1774 | 1860 | static int stste_decode_var(struct fb_var_screeninfo *var, | |
1775 | static int stste_decode_var( struct fb_var_screeninfo *var, | 1861 | struct atafb_par *par) |
1776 | struct atafb_par *par ) | ||
1777 | { | 1862 | { |
1778 | int xres=var->xres; | 1863 | int xres = var->xres; |
1779 | int yres=var->yres; | 1864 | int yres = var->yres; |
1780 | int bpp=var->bits_per_pixel; | 1865 | int bpp = var->bits_per_pixel; |
1781 | int linelen; | 1866 | int linelen; |
1782 | int yres_virtual = var->yres_virtual; | 1867 | int yres_virtual = var->yres_virtual; |
1783 | 1868 | ||
1784 | if (mono_moni) { | 1869 | if (mono_moni) { |
1785 | if (bpp > 1 || xres > sttt_xres || yres > st_yres) | 1870 | if (bpp > 1 || xres > sttt_xres || yres > st_yres) |
1786 | return -EINVAL; | 1871 | return -EINVAL; |
1787 | par->hw.st.mode=ST_HIGH; | 1872 | par->hw.st.mode = ST_HIGH; |
1788 | xres=sttt_xres; | 1873 | xres = sttt_xres; |
1789 | yres=st_yres; | 1874 | yres = st_yres; |
1790 | bpp=1; | 1875 | bpp = 1; |
1791 | } else { | 1876 | } else { |
1792 | if (bpp > 4 || xres > sttt_xres || yres > st_yres) | 1877 | if (bpp > 4 || xres > sttt_xres || yres > st_yres) |
1793 | return -EINVAL; | 1878 | return -EINVAL; |
1794 | if (bpp > 2) { | 1879 | if (bpp > 2) { |
1795 | if (xres > sttt_xres/2 || yres > st_yres/2) | 1880 | if (xres > sttt_xres / 2 || yres > st_yres / 2) |
1796 | return -EINVAL; | 1881 | return -EINVAL; |
1797 | par->hw.st.mode=ST_LOW; | 1882 | par->hw.st.mode = ST_LOW; |
1798 | xres=sttt_xres/2; | 1883 | xres = sttt_xres / 2; |
1799 | yres=st_yres/2; | 1884 | yres = st_yres / 2; |
1800 | bpp=4; | 1885 | bpp = 4; |
1801 | } | 1886 | } else if (bpp > 1) { |
1802 | else if (bpp > 1) { | 1887 | if (xres > sttt_xres || yres > st_yres / 2) |
1803 | if (xres > sttt_xres || yres > st_yres/2) | ||
1804 | return -EINVAL; | 1888 | return -EINVAL; |
1805 | par->hw.st.mode=ST_MID; | 1889 | par->hw.st.mode = ST_MID; |
1806 | xres=sttt_xres; | 1890 | xres = sttt_xres; |
1807 | yres=st_yres/2; | 1891 | yres = st_yres / 2; |
1808 | bpp=2; | 1892 | bpp = 2; |
1809 | } | 1893 | } else |
1810 | else | ||
1811 | return -EINVAL; | 1894 | return -EINVAL; |
1812 | } | 1895 | } |
1813 | if (yres_virtual <= 0) | 1896 | if (yres_virtual <= 0) |
@@ -1815,10 +1898,10 @@ static int stste_decode_var( struct fb_var_screeninfo *var, | |||
1815 | else if (yres_virtual < yres) | 1898 | else if (yres_virtual < yres) |
1816 | yres_virtual = yres; | 1899 | yres_virtual = yres; |
1817 | if (var->sync & FB_SYNC_EXT) | 1900 | if (var->sync & FB_SYNC_EXT) |
1818 | par->hw.st.sync=(par->hw.st.sync & ~1) | 1; | 1901 | par->hw.st.sync = (par->hw.st.sync & ~1) | 1; |
1819 | else | 1902 | else |
1820 | par->hw.st.sync=(par->hw.st.sync & ~1); | 1903 | par->hw.st.sync = (par->hw.st.sync & ~1); |
1821 | linelen=xres*bpp/8; | 1904 | linelen = xres * bpp / 8; |
1822 | if (yres_virtual * linelen > screen_len && screen_len) | 1905 | if (yres_virtual * linelen > screen_len && screen_len) |
1823 | return -EINVAL; | 1906 | return -EINVAL; |
1824 | if (yres * linelen > screen_len && screen_len) | 1907 | if (yres * linelen > screen_len && screen_len) |
@@ -1826,93 +1909,91 @@ static int stste_decode_var( struct fb_var_screeninfo *var, | |||
1826 | if (var->yoffset + yres > yres_virtual && yres_virtual) | 1909 | if (var->yoffset + yres > yres_virtual && yres_virtual) |
1827 | return -EINVAL; | 1910 | return -EINVAL; |
1828 | par->yres_virtual = yres_virtual; | 1911 | par->yres_virtual = yres_virtual; |
1829 | par->screen_base=screen_base+ var->yoffset*linelen; | 1912 | par->screen_base = screen_base + var->yoffset * linelen; |
1830 | return 0; | 1913 | return 0; |
1831 | } | 1914 | } |
1832 | 1915 | ||
1833 | static int stste_encode_var( struct fb_var_screeninfo *var, | 1916 | static int stste_encode_var(struct fb_var_screeninfo *var, |
1834 | struct atafb_par *par ) | 1917 | struct atafb_par *par) |
1835 | { | 1918 | { |
1836 | int linelen; | 1919 | int linelen; |
1837 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 1920 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
1838 | var->red.offset=0; | 1921 | var->red.offset = 0; |
1839 | var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; | 1922 | var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; |
1840 | var->red.msb_right=0; | 1923 | var->red.msb_right = 0; |
1841 | var->grayscale=0; | 1924 | var->grayscale = 0; |
1842 | 1925 | ||
1843 | var->pixclock=31041; | 1926 | var->pixclock = 31041; |
1844 | var->left_margin=120; /* these are incorrect */ | 1927 | var->left_margin = 120; /* these are incorrect */ |
1845 | var->right_margin=100; | 1928 | var->right_margin = 100; |
1846 | var->upper_margin=8; | 1929 | var->upper_margin = 8; |
1847 | var->lower_margin=16; | 1930 | var->lower_margin = 16; |
1848 | var->hsync_len=140; | 1931 | var->hsync_len = 140; |
1849 | var->vsync_len=30; | 1932 | var->vsync_len = 30; |
1850 | 1933 | ||
1851 | var->height=-1; | 1934 | var->height = -1; |
1852 | var->width=-1; | 1935 | var->width = -1; |
1853 | 1936 | ||
1854 | if (!(par->hw.st.sync & 1)) | 1937 | if (!(par->hw.st.sync & 1)) |
1855 | var->sync=0; | 1938 | var->sync = 0; |
1856 | else | 1939 | else |
1857 | var->sync=FB_SYNC_EXT; | 1940 | var->sync = FB_SYNC_EXT; |
1858 | 1941 | ||
1859 | switch (par->hw.st.mode & 3) { | 1942 | switch (par->hw.st.mode & 3) { |
1860 | case ST_LOW: | 1943 | case ST_LOW: |
1861 | var->xres=sttt_xres/2; | 1944 | var->xres = sttt_xres / 2; |
1862 | var->yres=st_yres/2; | 1945 | var->yres = st_yres / 2; |
1863 | var->bits_per_pixel=4; | 1946 | var->bits_per_pixel = 4; |
1864 | break; | 1947 | break; |
1865 | case ST_MID: | 1948 | case ST_MID: |
1866 | var->xres=sttt_xres; | 1949 | var->xres = sttt_xres; |
1867 | var->yres=st_yres/2; | 1950 | var->yres = st_yres / 2; |
1868 | var->bits_per_pixel=2; | 1951 | var->bits_per_pixel = 2; |
1869 | break; | 1952 | break; |
1870 | case ST_HIGH: | 1953 | case ST_HIGH: |
1871 | var->xres=sttt_xres; | 1954 | var->xres = sttt_xres; |
1872 | var->yres=st_yres; | 1955 | var->yres = st_yres; |
1873 | var->bits_per_pixel=1; | 1956 | var->bits_per_pixel = 1; |
1874 | break; | 1957 | break; |
1875 | } | 1958 | } |
1876 | var->blue=var->green=var->red; | 1959 | var->blue = var->green = var->red; |
1877 | var->transp.offset=0; | 1960 | var->transp.offset = 0; |
1878 | var->transp.length=0; | 1961 | var->transp.length = 0; |
1879 | var->transp.msb_right=0; | 1962 | var->transp.msb_right = 0; |
1880 | var->xres_virtual=sttt_xres_virtual; | 1963 | var->xres_virtual = sttt_xres_virtual; |
1881 | linelen=var->xres_virtual * var->bits_per_pixel / 8; | 1964 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
1882 | ovsc_addlen=linelen*(sttt_yres_virtual - st_yres); | 1965 | ovsc_addlen = linelen * (sttt_yres_virtual - st_yres); |
1883 | 1966 | ||
1884 | if (! use_hwscroll) | 1967 | if (!use_hwscroll) |
1885 | var->yres_virtual=var->yres; | 1968 | var->yres_virtual = var->yres; |
1886 | else if (screen_len) { | 1969 | else if (screen_len) { |
1887 | if (par->yres_virtual) | 1970 | if (par->yres_virtual) |
1888 | var->yres_virtual = par->yres_virtual; | 1971 | var->yres_virtual = par->yres_virtual; |
1889 | else | 1972 | else |
1890 | /* yres_virtual==0 means use maximum */ | 1973 | /* yres_virtual == 0 means use maximum */ |
1891 | var->yres_virtual = screen_len / linelen; | 1974 | var->yres_virtual = screen_len / linelen; |
1892 | } | 1975 | } else { |
1893 | else { | ||
1894 | if (hwscroll < 0) | 1976 | if (hwscroll < 0) |
1895 | var->yres_virtual = 2 * var->yres; | 1977 | var->yres_virtual = 2 * var->yres; |
1896 | else | 1978 | else |
1897 | var->yres_virtual=var->yres+hwscroll * 16; | 1979 | var->yres_virtual = var->yres + hwscroll * 16; |
1898 | } | 1980 | } |
1899 | var->xoffset=0; | 1981 | var->xoffset = 0; |
1900 | if (screen_base) | 1982 | if (screen_base) |
1901 | var->yoffset=(par->screen_base - screen_base)/linelen; | 1983 | var->yoffset = (par->screen_base - screen_base) / linelen; |
1902 | else | 1984 | else |
1903 | var->yoffset=0; | 1985 | var->yoffset = 0; |
1904 | var->nonstd=0; | 1986 | var->nonstd = 0; |
1905 | var->activate=0; | 1987 | var->activate = 0; |
1906 | var->vmode=FB_VMODE_NONINTERLACED; | 1988 | var->vmode = FB_VMODE_NONINTERLACED; |
1907 | return 0; | 1989 | return 0; |
1908 | } | 1990 | } |
1909 | 1991 | ||
1910 | 1992 | static void stste_get_par(struct atafb_par *par) | |
1911 | static void stste_get_par( struct atafb_par *par ) | ||
1912 | { | 1993 | { |
1913 | unsigned long addr; | 1994 | unsigned long addr; |
1914 | par->hw.st.mode=shifter_tt.st_shiftmode; | 1995 | par->hw.st.mode = shifter_tt.st_shiftmode; |
1915 | par->hw.st.sync=shifter.syncmode; | 1996 | par->hw.st.sync = shifter.syncmode; |
1916 | addr = ((shifter.bas_hi & 0xff) << 16) | | 1997 | addr = ((shifter.bas_hi & 0xff) << 16) | |
1917 | ((shifter.bas_md & 0xff) << 8); | 1998 | ((shifter.bas_md & 0xff) << 8); |
1918 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) | 1999 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) |
@@ -1920,55 +2001,18 @@ static void stste_get_par( struct atafb_par *par ) | |||
1920 | par->screen_base = phys_to_virt(addr); | 2001 | par->screen_base = phys_to_virt(addr); |
1921 | } | 2002 | } |
1922 | 2003 | ||
1923 | static void stste_set_par( struct atafb_par *par ) | 2004 | static void stste_set_par(struct atafb_par *par) |
1924 | { | 2005 | { |
1925 | shifter_tt.st_shiftmode=par->hw.st.mode; | 2006 | shifter_tt.st_shiftmode = par->hw.st.mode; |
1926 | shifter.syncmode=par->hw.st.sync; | 2007 | shifter.syncmode = par->hw.st.sync; |
1927 | /* only set screen_base if really necessary */ | 2008 | /* only set screen_base if really necessary */ |
1928 | if (current_par.screen_base != par->screen_base) | 2009 | if (current_par.screen_base != par->screen_base) |
1929 | fbhw->set_screen_base(par->screen_base); | 2010 | fbhw->set_screen_base(par->screen_base); |
1930 | } | 2011 | } |
1931 | 2012 | ||
1932 | 2013 | static int stste_setcolreg(unsigned int regno, unsigned int red, | |
1933 | static int stste_getcolreg(unsigned regno, unsigned *red, | 2014 | unsigned int green, unsigned int blue, |
1934 | unsigned *green, unsigned *blue, | 2015 | unsigned int transp, struct fb_info *info) |
1935 | unsigned *transp, struct fb_info *info) | ||
1936 | { | ||
1937 | unsigned col, t; | ||
1938 | |||
1939 | if (regno > 15) | ||
1940 | return 1; | ||
1941 | col = shifter_tt.color_reg[regno]; | ||
1942 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
1943 | t = ((col >> 7) & 0xe) | ((col >> 11) & 1); | ||
1944 | t |= t << 4; | ||
1945 | *red = t | (t << 8); | ||
1946 | t = ((col >> 3) & 0xe) | ((col >> 7) & 1); | ||
1947 | t |= t << 4; | ||
1948 | *green = t | (t << 8); | ||
1949 | t = ((col << 1) & 0xe) | ((col >> 3) & 1); | ||
1950 | t |= t << 4; | ||
1951 | *blue = t | (t << 8); | ||
1952 | } | ||
1953 | else { | ||
1954 | t = (col >> 7) & 0xe; | ||
1955 | t |= t << 4; | ||
1956 | *red = t | (t << 8); | ||
1957 | t = (col >> 3) & 0xe; | ||
1958 | t |= t << 4; | ||
1959 | *green = t | (t << 8); | ||
1960 | t = (col << 1) & 0xe; | ||
1961 | t |= t << 4; | ||
1962 | *blue = t | (t << 8); | ||
1963 | } | ||
1964 | *transp = 0; | ||
1965 | return 0; | ||
1966 | } | ||
1967 | |||
1968 | |||
1969 | static int stste_setcolreg(unsigned regno, unsigned red, | ||
1970 | unsigned green, unsigned blue, | ||
1971 | unsigned transp, struct fb_info *info) | ||
1972 | { | 2016 | { |
1973 | if (regno > 15) | 2017 | if (regno > 15) |
1974 | return 1; | 2018 | return 1; |
@@ -1988,10 +2032,9 @@ static int stste_setcolreg(unsigned regno, unsigned red, | |||
1988 | return 0; | 2032 | return 0; |
1989 | } | 2033 | } |
1990 | 2034 | ||
1991 | 2035 | static int stste_detect(void) | |
1992 | static int stste_detect( void ) | 2036 | { |
1993 | 2037 | struct atafb_par par; | |
1994 | { struct atafb_par par; | ||
1995 | 2038 | ||
1996 | /* Determine the connected monitor: The DMA sound must be | 2039 | /* Determine the connected monitor: The DMA sound must be |
1997 | * disabled before reading the MFP GPIP, because the Sound | 2040 | * disabled before reading the MFP GPIP, because the Sound |
@@ -1999,7 +2042,7 @@ static int stste_detect( void ) | |||
1999 | */ | 2042 | */ |
2000 | if (ATARIHW_PRESENT(PCM_8BIT)) { | 2043 | if (ATARIHW_PRESENT(PCM_8BIT)) { |
2001 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; | 2044 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; |
2002 | udelay(20); /* wait a while for things to settle down */ | 2045 | udelay(20); /* wait a while for things to settle down */ |
2003 | } | 2046 | } |
2004 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; | 2047 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; |
2005 | 2048 | ||
@@ -2014,12 +2057,12 @@ static int stste_detect( void ) | |||
2014 | static void stste_set_screen_base(void *s_base) | 2057 | static void stste_set_screen_base(void *s_base) |
2015 | { | 2058 | { |
2016 | unsigned long addr; | 2059 | unsigned long addr; |
2017 | addr= virt_to_phys(s_base); | 2060 | addr = virt_to_phys(s_base); |
2018 | /* Setup Screen Memory */ | 2061 | /* Setup Screen Memory */ |
2019 | shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); | 2062 | shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); |
2020 | shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); | 2063 | shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); |
2021 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) | 2064 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) |
2022 | shifter.bas_lo=(unsigned char) (addr & 0x0000ff); | 2065 | shifter.bas_lo = (unsigned char)(addr & 0x0000ff); |
2023 | } | 2066 | } |
2024 | 2067 | ||
2025 | #endif /* ATAFB_STE */ | 2068 | #endif /* ATAFB_STE */ |
@@ -2045,51 +2088,49 @@ static void stste_set_screen_base(void *s_base) | |||
2045 | /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ | 2088 | /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ |
2046 | static void st_ovsc_switch(void) | 2089 | static void st_ovsc_switch(void) |
2047 | { | 2090 | { |
2048 | unsigned long flags; | 2091 | unsigned long flags; |
2049 | register unsigned char old, new; | 2092 | register unsigned char old, new; |
2050 | 2093 | ||
2051 | if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) | 2094 | if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) |
2052 | return; | 2095 | return; |
2053 | local_irq_save(flags); | 2096 | local_irq_save(flags); |
2054 | 2097 | ||
2055 | mfp.tim_ct_b = 0x10; | 2098 | mfp.tim_ct_b = 0x10; |
2056 | mfp.active_edge |= 8; | 2099 | mfp.active_edge |= 8; |
2057 | mfp.tim_ct_b = 0; | 2100 | mfp.tim_ct_b = 0; |
2058 | mfp.tim_dt_b = 0xf0; | 2101 | mfp.tim_dt_b = 0xf0; |
2059 | mfp.tim_ct_b = 8; | 2102 | mfp.tim_ct_b = 8; |
2060 | while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ | 2103 | while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ |
2061 | ; | 2104 | ; |
2062 | new = mfp.tim_dt_b; | ||
2063 | do { | ||
2064 | udelay(LINE_DELAY); | ||
2065 | old = new; | ||
2066 | new = mfp.tim_dt_b; | 2105 | new = mfp.tim_dt_b; |
2067 | } while (old != new); | 2106 | do { |
2068 | mfp.tim_ct_b = 0x10; | 2107 | udelay(LINE_DELAY); |
2069 | udelay(SYNC_DELAY); | 2108 | old = new; |
2070 | 2109 | new = mfp.tim_dt_b; | |
2071 | if (atari_switches & ATARI_SWITCH_OVSC_IKBD) | 2110 | } while (old != new); |
2072 | acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; | 2111 | mfp.tim_ct_b = 0x10; |
2073 | if (atari_switches & ATARI_SWITCH_OVSC_MIDI) | 2112 | udelay(SYNC_DELAY); |
2074 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; | 2113 | |
2075 | if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { | 2114 | if (atari_switches & ATARI_SWITCH_OVSC_IKBD) |
2076 | sound_ym.rd_data_reg_sel = 14; | 2115 | acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; |
2077 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | | 2116 | if (atari_switches & ATARI_SWITCH_OVSC_MIDI) |
2078 | ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | | 2117 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; |
2079 | ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0); | 2118 | if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { |
2080 | } | 2119 | sound_ym.rd_data_reg_sel = 14; |
2081 | local_irq_restore(flags); | 2120 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | |
2121 | ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | | ||
2122 | ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0); | ||
2123 | } | ||
2124 | local_irq_restore(flags); | ||
2082 | } | 2125 | } |
2083 | 2126 | ||
2084 | /* ------------------- External Video ---------------------- */ | 2127 | /* ------------------- External Video ---------------------- */ |
2085 | 2128 | ||
2086 | #ifdef ATAFB_EXT | 2129 | #ifdef ATAFB_EXT |
2087 | 2130 | ||
2088 | static int ext_encode_fix( struct fb_fix_screeninfo *fix, | 2131 | static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) |
2089 | struct atafb_par *par ) | ||
2090 | |||
2091 | { | 2132 | { |
2092 | strcpy(fix->id,"Unknown Extern"); | 2133 | strcpy(fix->id, "Unknown Extern"); |
2093 | fix->smem_start = (unsigned long)external_addr; | 2134 | fix->smem_start = (unsigned long)external_addr; |
2094 | fix->smem_len = PAGE_ALIGN(external_len); | 2135 | fix->smem_len = PAGE_ALIGN(external_len); |
2095 | if (external_depth == 1) { | 2136 | if (external_depth == 1) { |
@@ -2099,31 +2140,29 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, | |||
2099 | fix->visual = | 2140 | fix->visual = |
2100 | (external_pmode == FB_TYPE_INTERLEAVED_PLANES || | 2141 | (external_pmode == FB_TYPE_INTERLEAVED_PLANES || |
2101 | external_pmode == FB_TYPE_PACKED_PIXELS) ? | 2142 | external_pmode == FB_TYPE_PACKED_PIXELS) ? |
2102 | FB_VISUAL_MONO10 : | 2143 | FB_VISUAL_MONO10 : FB_VISUAL_MONO01; |
2103 | FB_VISUAL_MONO01; | 2144 | } else { |
2104 | } | ||
2105 | else { | ||
2106 | /* Use STATIC if we don't know how to access color registers */ | 2145 | /* Use STATIC if we don't know how to access color registers */ |
2107 | int visual = external_vgaiobase ? | 2146 | int visual = external_vgaiobase ? |
2108 | FB_VISUAL_PSEUDOCOLOR : | 2147 | FB_VISUAL_PSEUDOCOLOR : |
2109 | FB_VISUAL_STATIC_PSEUDOCOLOR; | 2148 | FB_VISUAL_STATIC_PSEUDOCOLOR; |
2110 | switch (external_pmode) { | 2149 | switch (external_pmode) { |
2111 | case -1: /* truecolor */ | 2150 | case -1: /* truecolor */ |
2112 | fix->type=FB_TYPE_PACKED_PIXELS; | 2151 | fix->type = FB_TYPE_PACKED_PIXELS; |
2113 | fix->visual=FB_VISUAL_TRUECOLOR; | 2152 | fix->visual = FB_VISUAL_TRUECOLOR; |
2114 | break; | 2153 | break; |
2115 | case FB_TYPE_PACKED_PIXELS: | 2154 | case FB_TYPE_PACKED_PIXELS: |
2116 | fix->type=FB_TYPE_PACKED_PIXELS; | 2155 | fix->type = FB_TYPE_PACKED_PIXELS; |
2117 | fix->visual=visual; | 2156 | fix->visual = visual; |
2118 | break; | 2157 | break; |
2119 | case FB_TYPE_PLANES: | 2158 | case FB_TYPE_PLANES: |
2120 | fix->type=FB_TYPE_PLANES; | 2159 | fix->type = FB_TYPE_PLANES; |
2121 | fix->visual=visual; | 2160 | fix->visual = visual; |
2122 | break; | 2161 | break; |
2123 | case FB_TYPE_INTERLEAVED_PLANES: | 2162 | case FB_TYPE_INTERLEAVED_PLANES: |
2124 | fix->type=FB_TYPE_INTERLEAVED_PLANES; | 2163 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
2125 | fix->type_aux=2; | 2164 | fix->type_aux = 2; |
2126 | fix->visual=visual; | 2165 | fix->visual = visual; |
2127 | break; | 2166 | break; |
2128 | } | 2167 | } |
2129 | } | 2168 | } |
@@ -2134,137 +2173,112 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, | |||
2134 | return 0; | 2173 | return 0; |
2135 | } | 2174 | } |
2136 | 2175 | ||
2137 | 2176 | static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
2138 | static int ext_decode_var( struct fb_var_screeninfo *var, | ||
2139 | struct atafb_par *par ) | ||
2140 | { | 2177 | { |
2141 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 2178 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
2142 | 2179 | ||
2143 | if (var->bits_per_pixel > myvar->bits_per_pixel || | 2180 | if (var->bits_per_pixel > myvar->bits_per_pixel || |
2144 | var->xres > myvar->xres || | 2181 | var->xres > myvar->xres || |
2145 | var->xres_virtual > myvar->xres_virtual || | 2182 | var->xres_virtual > myvar->xres_virtual || |
2146 | var->yres > myvar->yres || | 2183 | var->yres > myvar->yres || |
2147 | var->xoffset > 0 || | 2184 | var->xoffset > 0 || |
2148 | var->yoffset > 0) | 2185 | var->yoffset > 0) |
2149 | return -EINVAL; | 2186 | return -EINVAL; |
2150 | return 0; | 2187 | return 0; |
2151 | } | 2188 | } |
2152 | 2189 | ||
2153 | 2190 | static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
2154 | static int ext_encode_var( struct fb_var_screeninfo *var, | ||
2155 | struct atafb_par *par ) | ||
2156 | { | 2191 | { |
2157 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 2192 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
2158 | var->red.offset=0; | 2193 | var->red.offset = 0; |
2159 | var->red.length=(external_pmode == -1) ? external_depth/3 : | 2194 | var->red.length = (external_pmode == -1) ? external_depth / 3 : |
2160 | (external_vgaiobase ? external_bitspercol : 0); | 2195 | (external_vgaiobase ? external_bitspercol : 0); |
2161 | var->red.msb_right=0; | 2196 | var->red.msb_right = 0; |
2162 | var->grayscale=0; | 2197 | var->grayscale = 0; |
2163 | 2198 | ||
2164 | var->pixclock=31041; | 2199 | var->pixclock = 31041; |
2165 | var->left_margin=120; /* these are surely incorrect */ | 2200 | var->left_margin = 120; /* these are surely incorrect */ |
2166 | var->right_margin=100; | 2201 | var->right_margin = 100; |
2167 | var->upper_margin=8; | 2202 | var->upper_margin = 8; |
2168 | var->lower_margin=16; | 2203 | var->lower_margin = 16; |
2169 | var->hsync_len=140; | 2204 | var->hsync_len = 140; |
2170 | var->vsync_len=30; | 2205 | var->vsync_len = 30; |
2171 | 2206 | ||
2172 | var->height=-1; | 2207 | var->height = -1; |
2173 | var->width=-1; | 2208 | var->width = -1; |
2174 | 2209 | ||
2175 | var->sync=0; | 2210 | var->sync = 0; |
2176 | 2211 | ||
2177 | var->xres = external_xres; | 2212 | var->xres = external_xres; |
2178 | var->yres = external_yres; | 2213 | var->yres = external_yres; |
2179 | var->xres_virtual = external_xres_virtual; | 2214 | var->xres_virtual = external_xres_virtual; |
2180 | var->bits_per_pixel = external_depth; | 2215 | var->bits_per_pixel = external_depth; |
2181 | 2216 | ||
2182 | var->blue=var->green=var->red; | 2217 | var->blue = var->green = var->red; |
2183 | var->transp.offset=0; | 2218 | var->transp.offset = 0; |
2184 | var->transp.length=0; | 2219 | var->transp.length = 0; |
2185 | var->transp.msb_right=0; | 2220 | var->transp.msb_right = 0; |
2186 | var->yres_virtual=var->yres; | 2221 | var->yres_virtual = var->yres; |
2187 | var->xoffset=0; | 2222 | var->xoffset = 0; |
2188 | var->yoffset=0; | 2223 | var->yoffset = 0; |
2189 | var->nonstd=0; | 2224 | var->nonstd = 0; |
2190 | var->activate=0; | 2225 | var->activate = 0; |
2191 | var->vmode=FB_VMODE_NONINTERLACED; | 2226 | var->vmode = FB_VMODE_NONINTERLACED; |
2192 | return 0; | 2227 | return 0; |
2193 | } | 2228 | } |
2194 | 2229 | ||
2195 | 2230 | static void ext_get_par(struct atafb_par *par) | |
2196 | static void ext_get_par( struct atafb_par *par ) | ||
2197 | { | 2231 | { |
2198 | par->screen_base = external_addr; | 2232 | par->screen_base = external_addr; |
2199 | } | 2233 | } |
2200 | 2234 | ||
2201 | static void ext_set_par( struct atafb_par *par ) | 2235 | static void ext_set_par(struct atafb_par *par) |
2202 | { | 2236 | { |
2203 | } | 2237 | } |
2204 | 2238 | ||
2205 | #define OUTB(port,val) \ | 2239 | #define OUTB(port,val) \ |
2206 | *((unsigned volatile char *) ((port)+external_vgaiobase))=(val) | 2240 | *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val) |
2207 | #define INB(port) \ | 2241 | #define INB(port) \ |
2208 | (*((unsigned volatile char *) ((port)+external_vgaiobase))) | 2242 | (*((unsigned volatile char *) ((port)+external_vgaiobase))) |
2209 | #define DACDelay \ | 2243 | #define DACDelay \ |
2210 | do { \ | 2244 | do { \ |
2211 | unsigned char tmp=INB(0x3da); \ | 2245 | unsigned char tmp = INB(0x3da); \ |
2212 | tmp=INB(0x3da); \ | 2246 | tmp = INB(0x3da); \ |
2213 | } while (0) | 2247 | } while (0) |
2214 | 2248 | ||
2215 | static int ext_getcolreg( unsigned regno, unsigned *red, | 2249 | static int ext_setcolreg(unsigned int regno, unsigned int red, |
2216 | unsigned *green, unsigned *blue, | 2250 | unsigned int green, unsigned int blue, |
2217 | unsigned *transp, struct fb_info *info ) | 2251 | unsigned int transp, struct fb_info *info) |
2218 | { | 2252 | { |
2219 | if (! external_vgaiobase) | 2253 | unsigned char colmask = (1 << external_bitspercol) - 1; |
2254 | |||
2255 | if (!external_vgaiobase) | ||
2220 | return 1; | 2256 | return 1; |
2221 | 2257 | ||
2222 | *red = ext_color[regno].red; | 2258 | switch (external_card_type) { |
2223 | *green = ext_color[regno].green; | 2259 | case IS_VGA: |
2224 | *blue = ext_color[regno].blue; | 2260 | OUTB(0x3c8, regno); |
2225 | *transp=0; | 2261 | DACDelay; |
2226 | return 0; | 2262 | OUTB(0x3c9, red & colmask); |
2227 | } | 2263 | DACDelay; |
2228 | 2264 | OUTB(0x3c9, green & colmask); | |
2229 | static int ext_setcolreg( unsigned regno, unsigned red, | 2265 | DACDelay; |
2230 | unsigned green, unsigned blue, | 2266 | OUTB(0x3c9, blue & colmask); |
2231 | unsigned transp, struct fb_info *info ) | 2267 | DACDelay; |
2268 | return 0; | ||
2232 | 2269 | ||
2233 | { unsigned char colmask = (1 << external_bitspercol) - 1; | 2270 | case IS_MV300: |
2271 | OUTB((MV300_reg[regno] << 2) + 1, red); | ||
2272 | OUTB((MV300_reg[regno] << 2) + 1, green); | ||
2273 | OUTB((MV300_reg[regno] << 2) + 1, blue); | ||
2274 | return 0; | ||
2234 | 2275 | ||
2235 | if (! external_vgaiobase) | 2276 | default: |
2236 | return 1; | 2277 | return 1; |
2237 | 2278 | } | |
2238 | ext_color[regno].red = red; | ||
2239 | ext_color[regno].green = green; | ||
2240 | ext_color[regno].blue = blue; | ||
2241 | |||
2242 | switch (external_card_type) { | ||
2243 | case IS_VGA: | ||
2244 | OUTB(0x3c8, regno); | ||
2245 | DACDelay; | ||
2246 | OUTB(0x3c9, red & colmask); | ||
2247 | DACDelay; | ||
2248 | OUTB(0x3c9, green & colmask); | ||
2249 | DACDelay; | ||
2250 | OUTB(0x3c9, blue & colmask); | ||
2251 | DACDelay; | ||
2252 | return 0; | ||
2253 | |||
2254 | case IS_MV300: | ||
2255 | OUTB((MV300_reg[regno] << 2)+1, red); | ||
2256 | OUTB((MV300_reg[regno] << 2)+1, green); | ||
2257 | OUTB((MV300_reg[regno] << 2)+1, blue); | ||
2258 | return 0; | ||
2259 | |||
2260 | default: | ||
2261 | return 1; | ||
2262 | } | ||
2263 | } | 2279 | } |
2264 | |||
2265 | |||
2266 | static int ext_detect( void ) | ||
2267 | 2280 | ||
2281 | static int ext_detect(void) | ||
2268 | { | 2282 | { |
2269 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 2283 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
2270 | struct atafb_par dummy_par; | 2284 | struct atafb_par dummy_par; |
@@ -2284,213 +2298,182 @@ static int ext_detect( void ) | |||
2284 | static void set_screen_base(void *s_base) | 2298 | static void set_screen_base(void *s_base) |
2285 | { | 2299 | { |
2286 | unsigned long addr; | 2300 | unsigned long addr; |
2287 | addr= virt_to_phys(s_base); | 2301 | |
2302 | addr = virt_to_phys(s_base); | ||
2288 | /* Setup Screen Memory */ | 2303 | /* Setup Screen Memory */ |
2289 | shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); | 2304 | shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); |
2290 | shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); | 2305 | shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); |
2291 | shifter.bas_lo=(unsigned char) (addr & 0x0000ff); | 2306 | shifter.bas_lo = (unsigned char)(addr & 0x0000ff); |
2292 | } | 2307 | } |
2293 | 2308 | ||
2294 | 2309 | static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |
2295 | static int pan_display( struct fb_var_screeninfo *var, | ||
2296 | struct atafb_par *par ) | ||
2297 | { | 2310 | { |
2311 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2312 | |||
2298 | if (!fbhw->set_screen_base || | 2313 | if (!fbhw->set_screen_base || |
2299 | (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) | 2314 | (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) |
2300 | return -EINVAL; | 2315 | return -EINVAL; |
2301 | var->xoffset = up(var->xoffset, 16); | 2316 | var->xoffset = up(var->xoffset, 16); |
2302 | par->screen_base = screen_base + | 2317 | par->screen_base = screen_base + |
2303 | (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset) | 2318 | (var->yoffset * info->var.xres_virtual + var->xoffset) |
2304 | * fb_display[fb_info.currcon].var.bits_per_pixel / 8; | 2319 | * info->var.bits_per_pixel / 8; |
2305 | fbhw->set_screen_base (par->screen_base); | 2320 | fbhw->set_screen_base(par->screen_base); |
2306 | return 0; | 2321 | return 0; |
2307 | } | 2322 | } |
2308 | 2323 | ||
2309 | |||
2310 | /* ------------ Interfaces to hardware functions ------------ */ | 2324 | /* ------------ Interfaces to hardware functions ------------ */ |
2311 | 2325 | ||
2312 | |||
2313 | #ifdef ATAFB_TT | 2326 | #ifdef ATAFB_TT |
2314 | static struct fb_hwswitch tt_switch = { | 2327 | static struct fb_hwswitch tt_switch = { |
2315 | tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var, | 2328 | .detect = tt_detect, |
2316 | tt_get_par, tt_set_par, tt_getcolreg, | 2329 | .encode_fix = tt_encode_fix, |
2317 | set_screen_base, NULL, pan_display | 2330 | .decode_var = tt_decode_var, |
2331 | .encode_var = tt_encode_var, | ||
2332 | .get_par = tt_get_par, | ||
2333 | .set_par = tt_set_par, | ||
2334 | .set_screen_base = set_screen_base, | ||
2335 | .pan_display = pan_display, | ||
2318 | }; | 2336 | }; |
2319 | #endif | 2337 | #endif |
2320 | 2338 | ||
2321 | #ifdef ATAFB_FALCON | 2339 | #ifdef ATAFB_FALCON |
2322 | static struct fb_hwswitch falcon_switch = { | 2340 | static struct fb_hwswitch falcon_switch = { |
2323 | falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var, | 2341 | .detect = falcon_detect, |
2324 | falcon_get_par, falcon_set_par, falcon_getcolreg, | 2342 | .encode_fix = falcon_encode_fix, |
2325 | set_screen_base, falcon_blank, falcon_pan_display | 2343 | .decode_var = falcon_decode_var, |
2344 | .encode_var = falcon_encode_var, | ||
2345 | .get_par = falcon_get_par, | ||
2346 | .set_par = falcon_set_par, | ||
2347 | .set_screen_base = set_screen_base, | ||
2348 | .blank = falcon_blank, | ||
2349 | .pan_display = falcon_pan_display, | ||
2326 | }; | 2350 | }; |
2327 | #endif | 2351 | #endif |
2328 | 2352 | ||
2329 | #ifdef ATAFB_STE | 2353 | #ifdef ATAFB_STE |
2330 | static struct fb_hwswitch st_switch = { | 2354 | static struct fb_hwswitch st_switch = { |
2331 | stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var, | 2355 | .detect = stste_detect, |
2332 | stste_get_par, stste_set_par, stste_getcolreg, | 2356 | .encode_fix = stste_encode_fix, |
2333 | stste_set_screen_base, NULL, pan_display | 2357 | .decode_var = stste_decode_var, |
2358 | .encode_var = stste_encode_var, | ||
2359 | .get_par = stste_get_par, | ||
2360 | .set_par = stste_set_par, | ||
2361 | .set_screen_base = stste_set_screen_base, | ||
2362 | .pan_display = pan_display | ||
2334 | }; | 2363 | }; |
2335 | #endif | 2364 | #endif |
2336 | 2365 | ||
2337 | #ifdef ATAFB_EXT | 2366 | #ifdef ATAFB_EXT |
2338 | static struct fb_hwswitch ext_switch = { | 2367 | static struct fb_hwswitch ext_switch = { |
2339 | ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var, | 2368 | .detect = ext_detect, |
2340 | ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL | 2369 | .encode_fix = ext_encode_fix, |
2370 | .decode_var = ext_decode_var, | ||
2371 | .encode_var = ext_encode_var, | ||
2372 | .get_par = ext_get_par, | ||
2373 | .set_par = ext_set_par, | ||
2341 | }; | 2374 | }; |
2342 | #endif | 2375 | #endif |
2343 | 2376 | ||
2344 | 2377 | static void ata_get_par(struct atafb_par *par) | |
2345 | |||
2346 | static void atafb_get_par( struct atafb_par *par ) | ||
2347 | { | 2378 | { |
2348 | if (current_par_valid) { | 2379 | if (current_par_valid) |
2349 | *par=current_par; | 2380 | *par = current_par; |
2350 | } | ||
2351 | else | 2381 | else |
2352 | fbhw->get_par(par); | 2382 | fbhw->get_par(par); |
2353 | } | 2383 | } |
2354 | 2384 | ||
2355 | 2385 | static void ata_set_par(struct atafb_par *par) | |
2356 | static void atafb_set_par( struct atafb_par *par ) | ||
2357 | { | 2386 | { |
2358 | fbhw->set_par(par); | 2387 | fbhw->set_par(par); |
2359 | current_par=*par; | 2388 | current_par = *par; |
2360 | current_par_valid=1; | 2389 | current_par_valid = 1; |
2361 | } | 2390 | } |
2362 | 2391 | ||
2363 | 2392 | ||
2364 | |||
2365 | /* =========================================================== */ | 2393 | /* =========================================================== */ |
2366 | /* ============== Hardware Independent Functions ============= */ | 2394 | /* ============== Hardware Independent Functions ============= */ |
2367 | /* =========================================================== */ | 2395 | /* =========================================================== */ |
2368 | 2396 | ||
2369 | |||
2370 | /* used for hardware scrolling */ | 2397 | /* used for hardware scrolling */ |
2371 | 2398 | ||
2372 | static int | 2399 | static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) |
2373 | fb_update_var(int con, struct fb_info *info) | ||
2374 | { | ||
2375 | int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual* | ||
2376 | fb_display[con].var.bits_per_pixel>>3; | ||
2377 | |||
2378 | current_par.screen_base=screen_base + off; | ||
2379 | |||
2380 | if (fbhw->set_screen_base) | ||
2381 | fbhw->set_screen_base(current_par.screen_base); | ||
2382 | return 0; | ||
2383 | } | ||
2384 | |||
2385 | static int | ||
2386 | do_fb_set_var(struct fb_var_screeninfo *var, int isactive) | ||
2387 | { | 2400 | { |
2388 | int err,activate; | 2401 | int err, activate; |
2389 | struct atafb_par par; | 2402 | struct atafb_par par; |
2390 | if ((err=fbhw->decode_var(var, &par))) | 2403 | |
2404 | err = fbhw->decode_var(var, &par); | ||
2405 | if (err) | ||
2391 | return err; | 2406 | return err; |
2392 | activate=var->activate; | 2407 | activate = var->activate; |
2393 | if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) | 2408 | if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) |
2394 | atafb_set_par(&par); | 2409 | ata_set_par(&par); |
2395 | fbhw->encode_var(var, &par); | 2410 | fbhw->encode_var(var, &par); |
2396 | var->activate=activate; | 2411 | var->activate = activate; |
2397 | return 0; | 2412 | return 0; |
2398 | } | 2413 | } |
2399 | 2414 | ||
2400 | static int | 2415 | static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) |
2401 | atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | ||
2402 | { | 2416 | { |
2403 | struct atafb_par par; | 2417 | struct atafb_par par; |
2404 | if (con == -1) | 2418 | int err; |
2405 | atafb_get_par(&par); | 2419 | // Get fix directly (case con == -1 before)?? |
2406 | else { | 2420 | err = fbhw->decode_var(&info->var, &par); |
2407 | int err; | 2421 | if (err) |
2408 | if ((err=fbhw->decode_var(&fb_display[con].var,&par))) | 2422 | return err; |
2409 | return err; | ||
2410 | } | ||
2411 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 2423 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
2412 | return fbhw->encode_fix(fix, &par); | 2424 | return fbhw->encode_fix(fix, &par); |
2413 | } | 2425 | } |
2414 | 2426 | ||
2415 | static int | 2427 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) |
2416 | atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | ||
2417 | { | 2428 | { |
2418 | struct atafb_par par; | 2429 | struct atafb_par par; |
2419 | if (con == -1) { | 2430 | |
2420 | atafb_get_par(&par); | 2431 | ata_get_par(&par); |
2421 | fbhw->encode_var(var, &par); | 2432 | fbhw->encode_var(var, &par); |
2422 | } | 2433 | |
2423 | else | ||
2424 | *var=fb_display[con].var; | ||
2425 | return 0; | 2434 | return 0; |
2426 | } | 2435 | } |
2427 | 2436 | ||
2428 | static void | 2437 | // No longer called by fbcon! |
2429 | atafb_set_disp(int con, struct fb_info *info) | 2438 | // Still called by set_var internally |
2439 | |||
2440 | static void atafb_set_disp(struct fb_info *info) | ||
2430 | { | 2441 | { |
2431 | struct fb_fix_screeninfo fix; | 2442 | atafb_get_var(&info->var, info); |
2432 | struct fb_var_screeninfo var; | 2443 | atafb_get_fix(&info->fix, info); |
2433 | struct display *display; | ||
2434 | 2444 | ||
2435 | if (con >= 0) | 2445 | info->screen_base = (void *)info->fix.smem_start; |
2436 | display = &fb_display[con]; | 2446 | |
2437 | else | 2447 | switch (info->fix.type) { |
2438 | display = &disp; /* used during initialization */ | 2448 | case FB_TYPE_INTERLEAVED_PLANES: |
2439 | 2449 | switch (info->var.bits_per_pixel) { | |
2440 | atafb_get_fix(&fix, con, info); | 2450 | case 2: |
2441 | atafb_get_var(&var, con, info); | 2451 | // display->dispsw = &fbcon_iplan2p2; |
2442 | if (con == -1) | ||
2443 | con=0; | ||
2444 | info->screen_base = (void *)fix.smem_start; | ||
2445 | display->visual = fix.visual; | ||
2446 | display->type = fix.type; | ||
2447 | display->type_aux = fix.type_aux; | ||
2448 | display->ypanstep = fix.ypanstep; | ||
2449 | display->ywrapstep = fix.ywrapstep; | ||
2450 | display->line_length = fix.line_length; | ||
2451 | if (fix.visual != FB_VISUAL_PSEUDOCOLOR && | ||
2452 | fix.visual != FB_VISUAL_DIRECTCOLOR) | ||
2453 | display->can_soft_blank = 0; | ||
2454 | else | ||
2455 | display->can_soft_blank = 1; | ||
2456 | display->inverse = | ||
2457 | (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); | ||
2458 | switch (fix.type) { | ||
2459 | case FB_TYPE_INTERLEAVED_PLANES: | ||
2460 | switch (var.bits_per_pixel) { | ||
2461 | #ifdef FBCON_HAS_IPLAN2P2 | ||
2462 | case 2: | ||
2463 | display->dispsw = &fbcon_iplan2p2; | ||
2464 | break; | 2452 | break; |
2465 | #endif | 2453 | case 4: |
2466 | #ifdef FBCON_HAS_IPLAN2P4 | 2454 | // display->dispsw = &fbcon_iplan2p4; |
2467 | case 4: | ||
2468 | display->dispsw = &fbcon_iplan2p4; | ||
2469 | break; | 2455 | break; |
2470 | #endif | 2456 | case 8: |
2471 | #ifdef FBCON_HAS_IPLAN2P8 | 2457 | // display->dispsw = &fbcon_iplan2p8; |
2472 | case 8: | ||
2473 | display->dispsw = &fbcon_iplan2p8; | ||
2474 | break; | 2458 | break; |
2475 | #endif | ||
2476 | } | 2459 | } |
2477 | break; | 2460 | break; |
2478 | case FB_TYPE_PACKED_PIXELS: | 2461 | case FB_TYPE_PACKED_PIXELS: |
2479 | switch (var.bits_per_pixel) { | 2462 | switch (info->var.bits_per_pixel) { |
2480 | #ifdef FBCON_HAS_MFB | 2463 | #ifdef FBCON_HAS_MFB |
2481 | case 1: | 2464 | case 1: |
2482 | display->dispsw = &fbcon_mfb; | 2465 | // display->dispsw = &fbcon_mfb; |
2483 | break; | 2466 | break; |
2484 | #endif | 2467 | #endif |
2485 | #ifdef FBCON_HAS_CFB8 | 2468 | #ifdef FBCON_HAS_CFB8 |
2486 | case 8: | 2469 | case 8: |
2487 | display->dispsw = &fbcon_cfb8; | 2470 | // display->dispsw = &fbcon_cfb8; |
2488 | break; | 2471 | break; |
2489 | #endif | 2472 | #endif |
2490 | #ifdef FBCON_HAS_CFB16 | 2473 | #ifdef FBCON_HAS_CFB16 |
2491 | case 16: | 2474 | case 16: |
2492 | display->dispsw = &fbcon_cfb16; | 2475 | // display->dispsw = &fbcon_cfb16; |
2493 | display->dispsw_data = fbcon_cfb16_cmap; | 2476 | // display->dispsw_data = fbcon_cfb16_cmap; |
2494 | break; | 2477 | break; |
2495 | #endif | 2478 | #endif |
2496 | } | 2479 | } |
@@ -2498,74 +2481,203 @@ atafb_set_disp(int con, struct fb_info *info) | |||
2498 | } | 2481 | } |
2499 | } | 2482 | } |
2500 | 2483 | ||
2484 | static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
2485 | u_int transp, struct fb_info *info) | ||
2486 | { | ||
2487 | red >>= 8; | ||
2488 | green >>= 8; | ||
2489 | blue >>= 8; | ||
2490 | |||
2491 | return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info); | ||
2492 | } | ||
2493 | |||
2501 | static int | 2494 | static int |
2502 | atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | 2495 | atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
2503 | { | 2496 | { |
2504 | int err,oldxres,oldyres,oldbpp,oldxres_virtual, | 2497 | int xoffset = var->xoffset; |
2505 | oldyres_virtual,oldyoffset; | 2498 | int yoffset = var->yoffset; |
2506 | if ((err=do_fb_set_var(var, con==info->currcon))) | 2499 | int err; |
2507 | return err; | 2500 | |
2508 | if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { | 2501 | if (var->vmode & FB_VMODE_YWRAP) { |
2509 | oldxres=fb_display[con].var.xres; | 2502 | if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset) |
2510 | oldyres=fb_display[con].var.yres; | 2503 | return -EINVAL; |
2511 | oldxres_virtual=fb_display[con].var.xres_virtual; | 2504 | } else { |
2512 | oldyres_virtual=fb_display[con].var.yres_virtual; | 2505 | if (xoffset + info->var.xres > info->var.xres_virtual || |
2513 | oldbpp=fb_display[con].var.bits_per_pixel; | 2506 | yoffset + info->var.yres > info->var.yres_virtual) |
2514 | oldyoffset=fb_display[con].var.yoffset; | 2507 | return -EINVAL; |
2515 | fb_display[con].var=*var; | ||
2516 | if (oldxres != var->xres || oldyres != var->yres | ||
2517 | || oldxres_virtual != var->xres_virtual | ||
2518 | || oldyres_virtual != var->yres_virtual | ||
2519 | || oldbpp != var->bits_per_pixel | ||
2520 | || oldyoffset != var->yoffset) { | ||
2521 | atafb_set_disp(con, info); | ||
2522 | (*fb_info.changevar)(con); | ||
2523 | fb_alloc_cmap(&fb_display[con].cmap, 0, 0); | ||
2524 | do_install_cmap(con, info); | ||
2525 | } | ||
2526 | } | 2508 | } |
2527 | var->activate=0; | 2509 | |
2510 | if (fbhw->pan_display) { | ||
2511 | err = fbhw->pan_display(var, info); | ||
2512 | if (err) | ||
2513 | return err; | ||
2514 | } else | ||
2515 | return -EINVAL; | ||
2516 | |||
2517 | info->var.xoffset = xoffset; | ||
2518 | info->var.yoffset = yoffset; | ||
2519 | |||
2520 | if (var->vmode & FB_VMODE_YWRAP) | ||
2521 | info->var.vmode |= FB_VMODE_YWRAP; | ||
2522 | else | ||
2523 | info->var.vmode &= ~FB_VMODE_YWRAP; | ||
2524 | |||
2528 | return 0; | 2525 | return 0; |
2529 | } | 2526 | } |
2530 | 2527 | ||
2528 | /* | ||
2529 | * generic drawing routines; imageblit needs updating for image depth > 1 | ||
2530 | */ | ||
2531 | 2531 | ||
2532 | #if BITS_PER_LONG == 32 | ||
2533 | #define BYTES_PER_LONG 4 | ||
2534 | #define SHIFT_PER_LONG 5 | ||
2535 | #elif BITS_PER_LONG == 64 | ||
2536 | #define BYTES_PER_LONG 8 | ||
2537 | #define SHIFT_PER_LONG 6 | ||
2538 | #else | ||
2539 | #define Please update me | ||
2540 | #endif | ||
2532 | 2541 | ||
2533 | static int | 2542 | |
2534 | atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) | 2543 | static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
2535 | { | 2544 | { |
2536 | if (con == info->currcon) /* current console ? */ | 2545 | struct atafb_par *par = (struct atafb_par *)info->par; |
2537 | return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info); | 2546 | int x2, y2; |
2547 | u32 width, height; | ||
2548 | |||
2549 | if (!rect->width || !rect->height) | ||
2550 | return; | ||
2551 | |||
2552 | /* | ||
2553 | * We could use hardware clipping but on many cards you get around | ||
2554 | * hardware clipping by writing to framebuffer directly. | ||
2555 | * */ | ||
2556 | x2 = rect->dx + rect->width; | ||
2557 | y2 = rect->dy + rect->height; | ||
2558 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2559 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2560 | width = x2 - rect->dx; | ||
2561 | height = y2 - rect->dy; | ||
2562 | |||
2563 | if (info->var.bits_per_pixel == 1) | ||
2564 | atafb_mfb_fillrect(info, par->next_line, rect->color, | ||
2565 | rect->dy, rect->dx, height, width); | ||
2566 | else if (info->var.bits_per_pixel == 2) | ||
2567 | atafb_iplan2p2_fillrect(info, par->next_line, rect->color, | ||
2568 | rect->dy, rect->dx, height, width); | ||
2569 | else if (info->var.bits_per_pixel == 4) | ||
2570 | atafb_iplan2p4_fillrect(info, par->next_line, rect->color, | ||
2571 | rect->dy, rect->dx, height, width); | ||
2538 | else | 2572 | else |
2539 | if (fb_display[con].cmap.len) /* non default colormap ? */ | 2573 | atafb_iplan2p8_fillrect(info, par->next_line, rect->color, |
2540 | fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); | 2574 | rect->dy, rect->dx, height, width); |
2541 | else | 2575 | |
2542 | fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), | 2576 | return; |
2543 | cmap, kspc ? 0 : 2); | ||
2544 | return 0; | ||
2545 | } | 2577 | } |
2546 | 2578 | ||
2547 | static int | 2579 | static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) |
2548 | atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) | ||
2549 | { | 2580 | { |
2550 | int xoffset = var->xoffset; | 2581 | struct atafb_par *par = (struct atafb_par *)info->par; |
2551 | int yoffset = var->yoffset; | 2582 | int x2, y2; |
2552 | int err; | 2583 | u32 dx, dy, sx, sy, width, height; |
2584 | int rev_copy = 0; | ||
2585 | |||
2586 | /* clip the destination */ | ||
2587 | x2 = area->dx + area->width; | ||
2588 | y2 = area->dy + area->height; | ||
2589 | dx = area->dx > 0 ? area->dx : 0; | ||
2590 | dy = area->dy > 0 ? area->dy : 0; | ||
2591 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2592 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2593 | width = x2 - dx; | ||
2594 | height = y2 - dy; | ||
2595 | |||
2596 | /* update sx,sy */ | ||
2597 | sx = area->sx + (dx - area->dx); | ||
2598 | sy = area->sy + (dy - area->dy); | ||
2599 | |||
2600 | /* the source must be completely inside the virtual screen */ | ||
2601 | if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || | ||
2602 | (sy + height) > info->var.yres_virtual) | ||
2603 | return; | ||
2553 | 2604 | ||
2554 | if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual | 2605 | if (dy > sy || (dy == sy && dx > sx)) { |
2555 | || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual) | 2606 | dy += height; |
2556 | return -EINVAL; | 2607 | sy += height; |
2608 | rev_copy = 1; | ||
2609 | } | ||
2610 | |||
2611 | if (info->var.bits_per_pixel == 1) | ||
2612 | atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2613 | else if (info->var.bits_per_pixel == 2) | ||
2614 | atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2615 | else if (info->var.bits_per_pixel == 4) | ||
2616 | atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2617 | else | ||
2618 | atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2557 | 2619 | ||
2558 | if (con == info->currcon) { | 2620 | return; |
2559 | if (fbhw->pan_display) { | 2621 | } |
2560 | if ((err = fbhw->pan_display(var, ¤t_par))) | 2622 | |
2561 | return err; | 2623 | static void atafb_imageblit(struct fb_info *info, const struct fb_image *image) |
2624 | { | ||
2625 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2626 | int x2, y2; | ||
2627 | unsigned long *dst; | ||
2628 | int dst_idx; | ||
2629 | const char *src; | ||
2630 | u32 dx, dy, width, height, pitch; | ||
2631 | |||
2632 | /* | ||
2633 | * We could use hardware clipping but on many cards you get around | ||
2634 | * hardware clipping by writing to framebuffer directly like we are | ||
2635 | * doing here. | ||
2636 | */ | ||
2637 | x2 = image->dx + image->width; | ||
2638 | y2 = image->dy + image->height; | ||
2639 | dx = image->dx; | ||
2640 | dy = image->dy; | ||
2641 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2642 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2643 | width = x2 - dx; | ||
2644 | height = y2 - dy; | ||
2645 | |||
2646 | if (image->depth == 1) { | ||
2647 | // used for font data | ||
2648 | dst = (unsigned long *) | ||
2649 | ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); | ||
2650 | dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; | ||
2651 | dst_idx += dy * par->next_line * 8 + dx; | ||
2652 | src = image->data; | ||
2653 | pitch = (image->width + 7) / 8; | ||
2654 | while (height--) { | ||
2655 | |||
2656 | if (info->var.bits_per_pixel == 1) | ||
2657 | atafb_mfb_linefill(info, par->next_line, | ||
2658 | dy, dx, width, src, | ||
2659 | image->bg_color, image->fg_color); | ||
2660 | else if (info->var.bits_per_pixel == 2) | ||
2661 | atafb_iplan2p2_linefill(info, par->next_line, | ||
2662 | dy, dx, width, src, | ||
2663 | image->bg_color, image->fg_color); | ||
2664 | else if (info->var.bits_per_pixel == 4) | ||
2665 | atafb_iplan2p4_linefill(info, par->next_line, | ||
2666 | dy, dx, width, src, | ||
2667 | image->bg_color, image->fg_color); | ||
2668 | else | ||
2669 | atafb_iplan2p8_linefill(info, par->next_line, | ||
2670 | dy, dx, width, src, | ||
2671 | image->bg_color, image->fg_color); | ||
2672 | dy++; | ||
2673 | src += pitch; | ||
2562 | } | 2674 | } |
2563 | else | 2675 | } else { |
2564 | return -EINVAL; | 2676 | // only used for logo; broken |
2677 | c2p(info->screen_base, image->data, dx, dy, width, height, | ||
2678 | par->next_line, par->next_plane, image->width, | ||
2679 | info->var.bits_per_pixel); | ||
2565 | } | 2680 | } |
2566 | fb_display[con].var.xoffset = var->xoffset; | ||
2567 | fb_display[con].var.yoffset = var->yoffset; | ||
2568 | return 0; | ||
2569 | } | 2681 | } |
2570 | 2682 | ||
2571 | static int | 2683 | static int |
@@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |||
2584 | if (copy_from_user((void *)¤t_par, (void *)arg, | 2696 | if (copy_from_user((void *)¤t_par, (void *)arg, |
2585 | sizeof(struct atafb_par))) | 2697 | sizeof(struct atafb_par))) |
2586 | return -EFAULT; | 2698 | return -EFAULT; |
2587 | atafb_set_par(¤t_par); | 2699 | ata_set_par(¤t_par); |
2588 | return 0; | 2700 | return 0; |
2589 | #endif | 2701 | #endif |
2590 | } | 2702 | } |
@@ -2598,42 +2710,82 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |||
2598 | * 3 = suspend hsync | 2710 | * 3 = suspend hsync |
2599 | * 4 = off | 2711 | * 4 = off |
2600 | */ | 2712 | */ |
2601 | static int | 2713 | static int atafb_blank(int blank, struct fb_info *info) |
2602 | atafb_blank(int blank, struct fb_info *info) | ||
2603 | { | 2714 | { |
2604 | unsigned short black[16]; | 2715 | unsigned short black[16]; |
2605 | struct fb_cmap cmap; | 2716 | struct fb_cmap cmap; |
2606 | if (fbhw->blank && !fbhw->blank(blank)) | 2717 | if (fbhw->blank && !fbhw->blank(blank)) |
2607 | return 1; | 2718 | return 1; |
2608 | if (blank) { | 2719 | if (blank) { |
2609 | memset(black, 0, 16*sizeof(unsigned short)); | 2720 | memset(black, 0, 16 * sizeof(unsigned short)); |
2610 | cmap.red=black; | 2721 | cmap.red = black; |
2611 | cmap.green=black; | 2722 | cmap.green = black; |
2612 | cmap.blue=black; | 2723 | cmap.blue = black; |
2613 | cmap.transp=NULL; | 2724 | cmap.transp = NULL; |
2614 | cmap.start=0; | 2725 | cmap.start = 0; |
2615 | cmap.len=16; | 2726 | cmap.len = 16; |
2616 | fb_set_cmap(&cmap, 1, info); | 2727 | fb_set_cmap(&cmap, info); |
2617 | } | 2728 | } |
2729 | #if 0 | ||
2618 | else | 2730 | else |
2619 | do_install_cmap(info->currcon, info); | 2731 | do_install_cmap(info); |
2732 | #endif | ||
2733 | return 0; | ||
2734 | } | ||
2735 | |||
2736 | /* | ||
2737 | * New fbcon interface ... | ||
2738 | */ | ||
2739 | |||
2740 | /* check var by decoding var into hw par, rounding if necessary, | ||
2741 | * then encoding hw par back into new, validated var */ | ||
2742 | static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
2743 | { | ||
2744 | int err; | ||
2745 | struct atafb_par par; | ||
2746 | |||
2747 | /* Validate wanted screen parameters */ | ||
2748 | // if ((err = ata_decode_var(var, &par))) | ||
2749 | err = fbhw->decode_var(var, &par); | ||
2750 | if (err) | ||
2751 | return err; | ||
2752 | |||
2753 | /* Encode (possibly rounded) screen parameters */ | ||
2754 | fbhw->encode_var(var, &par); | ||
2755 | return 0; | ||
2756 | } | ||
2757 | |||
2758 | /* actually set hw par by decoding var, then setting hardware from | ||
2759 | * hw par just decoded */ | ||
2760 | static int atafb_set_par(struct fb_info *info) | ||
2761 | { | ||
2762 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2763 | |||
2764 | /* Decode wanted screen parameters */ | ||
2765 | fbhw->decode_var(&info->var, par); | ||
2766 | fbhw->encode_fix(&info->fix, par); | ||
2767 | |||
2768 | /* Set new videomode */ | ||
2769 | ata_set_par(par); | ||
2770 | |||
2620 | return 0; | 2771 | return 0; |
2621 | } | 2772 | } |
2622 | 2773 | ||
2774 | |||
2623 | static struct fb_ops atafb_ops = { | 2775 | static struct fb_ops atafb_ops = { |
2624 | .owner = THIS_MODULE, | 2776 | .owner = THIS_MODULE, |
2625 | .fb_get_fix = atafb_get_fix, | 2777 | .fb_check_var = atafb_check_var, |
2626 | .fb_get_var = atafb_get_var, | 2778 | .fb_set_par = atafb_set_par, |
2627 | .fb_set_var = atafb_set_var, | 2779 | .fb_setcolreg = atafb_setcolreg, |
2628 | .fb_get_cmap = atafb_get_cmap, | ||
2629 | .fb_set_cmap = gen_set_cmap, | ||
2630 | .fb_pan_display =atafb_pan_display, | ||
2631 | .fb_blank = atafb_blank, | 2780 | .fb_blank = atafb_blank, |
2781 | .fb_pan_display = atafb_pan_display, | ||
2782 | .fb_fillrect = atafb_fillrect, | ||
2783 | .fb_copyarea = atafb_copyarea, | ||
2784 | .fb_imageblit = atafb_imageblit, | ||
2632 | .fb_ioctl = atafb_ioctl, | 2785 | .fb_ioctl = atafb_ioctl, |
2633 | }; | 2786 | }; |
2634 | 2787 | ||
2635 | static void | 2788 | static void check_default_par(int detected_mode) |
2636 | check_default_par( int detected_mode ) | ||
2637 | { | 2789 | { |
2638 | char default_name[10]; | 2790 | char default_name[10]; |
2639 | int i; | 2791 | int i; |
@@ -2642,199 +2794,41 @@ check_default_par( int detected_mode ) | |||
2642 | 2794 | ||
2643 | /* First try the user supplied mode */ | 2795 | /* First try the user supplied mode */ |
2644 | if (default_par) { | 2796 | if (default_par) { |
2645 | var=atafb_predefined[default_par-1]; | 2797 | var = atafb_predefined[default_par - 1]; |
2646 | var.activate = FB_ACTIVATE_TEST; | 2798 | var.activate = FB_ACTIVATE_TEST; |
2647 | if (do_fb_set_var(&var,1)) | 2799 | if (do_fb_set_var(&var, 1)) |
2648 | default_par=0; /* failed */ | 2800 | default_par = 0; /* failed */ |
2649 | } | 2801 | } |
2650 | /* Next is the autodetected one */ | 2802 | /* Next is the autodetected one */ |
2651 | if (! default_par) { | 2803 | if (!default_par) { |
2652 | var=atafb_predefined[detected_mode-1]; /* autodetect */ | 2804 | var = atafb_predefined[detected_mode - 1]; /* autodetect */ |
2653 | var.activate = FB_ACTIVATE_TEST; | 2805 | var.activate = FB_ACTIVATE_TEST; |
2654 | if (!do_fb_set_var(&var,1)) | 2806 | if (!do_fb_set_var(&var, 1)) |
2655 | default_par=detected_mode; | 2807 | default_par = detected_mode; |
2656 | } | 2808 | } |
2657 | /* If that also failed, try some default modes... */ | 2809 | /* If that also failed, try some default modes... */ |
2658 | if (! default_par) { | 2810 | if (!default_par) { |
2659 | /* try default1, default2... */ | 2811 | /* try default1, default2... */ |
2660 | for (i=1 ; i < 10 ; i++) { | 2812 | for (i = 1; i < 10; i++) { |
2661 | sprintf(default_name,"default%d",i); | 2813 | sprintf(default_name,"default%d", i); |
2662 | default_par=get_video_mode(default_name); | 2814 | default_par = get_video_mode(default_name); |
2663 | if (! default_par) | 2815 | if (!default_par) |
2664 | panic("can't set default video mode"); | 2816 | panic("can't set default video mode"); |
2665 | var=atafb_predefined[default_par-1]; | 2817 | var = atafb_predefined[default_par - 1]; |
2666 | var.activate = FB_ACTIVATE_TEST; | 2818 | var.activate = FB_ACTIVATE_TEST; |
2667 | if (! do_fb_set_var(&var,1)) | 2819 | if (!do_fb_set_var(&var,1)) |
2668 | break; /* ok */ | 2820 | break; /* ok */ |
2669 | } | 2821 | } |
2670 | } | 2822 | } |
2671 | min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8; | 2823 | min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8; |
2672 | if (default_mem_req < min_mem) | 2824 | if (default_mem_req < min_mem) |
2673 | default_mem_req=min_mem; | 2825 | default_mem_req = min_mem; |
2674 | } | ||
2675 | |||
2676 | static int | ||
2677 | atafb_switch(int con, struct fb_info *info) | ||
2678 | { | ||
2679 | /* Do we have to save the colormap ? */ | ||
2680 | if (fb_display[info->currcon].cmap.len) | ||
2681 | fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg, | ||
2682 | info); | ||
2683 | do_fb_set_var(&fb_display[con].var,1); | ||
2684 | info->currcon=con; | ||
2685 | /* Install new colormap */ | ||
2686 | do_install_cmap(con, info); | ||
2687 | return 0; | ||
2688 | } | ||
2689 | |||
2690 | int __init atafb_init(void) | ||
2691 | { | ||
2692 | int pad; | ||
2693 | int detected_mode; | ||
2694 | unsigned long mem_req; | ||
2695 | |||
2696 | if (!MACH_IS_ATARI) | ||
2697 | return -ENXIO; | ||
2698 | |||
2699 | do { | ||
2700 | #ifdef ATAFB_EXT | ||
2701 | if (external_addr) { | ||
2702 | fbhw = &ext_switch; | ||
2703 | atafb_ops.fb_setcolreg = &ext_setcolreg; | ||
2704 | break; | ||
2705 | } | ||
2706 | #endif | ||
2707 | #ifdef ATAFB_TT | ||
2708 | if (ATARIHW_PRESENT(TT_SHIFTER)) { | ||
2709 | fbhw = &tt_switch; | ||
2710 | atafb_ops.fb_setcolreg = &tt_setcolreg; | ||
2711 | break; | ||
2712 | } | ||
2713 | #endif | ||
2714 | #ifdef ATAFB_FALCON | ||
2715 | if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { | ||
2716 | fbhw = &falcon_switch; | ||
2717 | atafb_ops.fb_setcolreg = &falcon_setcolreg; | ||
2718 | request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, | ||
2719 | "framebuffer/modeswitch", falcon_vbl_switcher); | ||
2720 | break; | ||
2721 | } | ||
2722 | #endif | ||
2723 | #ifdef ATAFB_STE | ||
2724 | if (ATARIHW_PRESENT(STND_SHIFTER) || | ||
2725 | ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
2726 | fbhw = &st_switch; | ||
2727 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
2728 | break; | ||
2729 | } | ||
2730 | fbhw = &st_switch; | ||
2731 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
2732 | printk("Cannot determine video hardware; defaulting to ST(e)\n"); | ||
2733 | #else /* ATAFB_STE */ | ||
2734 | /* no default driver included */ | ||
2735 | /* Nobody will ever see this message :-) */ | ||
2736 | panic("Cannot initialize video hardware"); | ||
2737 | #endif | ||
2738 | } while (0); | ||
2739 | |||
2740 | /* Multisync monitor capabilities */ | ||
2741 | /* Atari-TOS defaults if no boot option present */ | ||
2742 | if (fb_info.monspecs.hfmin == 0) { | ||
2743 | fb_info.monspecs.hfmin = 31000; | ||
2744 | fb_info.monspecs.hfmax = 32000; | ||
2745 | fb_info.monspecs.vfmin = 58; | ||
2746 | fb_info.monspecs.vfmax = 62; | ||
2747 | } | ||
2748 | |||
2749 | detected_mode = fbhw->detect(); | ||
2750 | check_default_par(detected_mode); | ||
2751 | #ifdef ATAFB_EXT | ||
2752 | if (!external_addr) { | ||
2753 | #endif /* ATAFB_EXT */ | ||
2754 | mem_req = default_mem_req + ovsc_offset + ovsc_addlen; | ||
2755 | mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; | ||
2756 | screen_base = atari_stram_alloc(mem_req, "atafb"); | ||
2757 | if (!screen_base) | ||
2758 | panic("Cannot allocate screen memory"); | ||
2759 | memset(screen_base, 0, mem_req); | ||
2760 | pad = -(unsigned long)screen_base & (PAGE_SIZE-1); | ||
2761 | screen_base+=pad; | ||
2762 | real_screen_base=screen_base+ovsc_offset; | ||
2763 | screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; | ||
2764 | st_ovsc_switch(); | ||
2765 | if (CPU_IS_040_OR_060) { | ||
2766 | /* On a '040+, the cache mode of video RAM must be set to | ||
2767 | * write-through also for internal video hardware! */ | ||
2768 | cache_push(virt_to_phys(screen_base), screen_len); | ||
2769 | kernel_set_cachemode(screen_base, screen_len, | ||
2770 | IOMAP_WRITETHROUGH); | ||
2771 | } | ||
2772 | #ifdef ATAFB_EXT | ||
2773 | } | ||
2774 | else { | ||
2775 | /* Map the video memory (physical address given) to somewhere | ||
2776 | * in the kernel address space. | ||
2777 | */ | ||
2778 | external_addr = | ||
2779 | ioremap_writethrough((unsigned long)external_addr, | ||
2780 | external_len); | ||
2781 | if (external_vgaiobase) | ||
2782 | external_vgaiobase = | ||
2783 | (unsigned long)ioremap(external_vgaiobase, 0x10000); | ||
2784 | screen_base = | ||
2785 | real_screen_base = external_addr; | ||
2786 | screen_len = external_len & PAGE_MASK; | ||
2787 | memset (screen_base, 0, external_len); | ||
2788 | } | ||
2789 | #endif /* ATAFB_EXT */ | ||
2790 | |||
2791 | strcpy(fb_info.modename, "Atari Builtin "); | ||
2792 | fb_info.changevar = NULL; | ||
2793 | fb_info.fbops = &atafb_ops; | ||
2794 | fb_info.disp = &disp; | ||
2795 | fb_info.currcon = -1; | ||
2796 | fb_info.switch_con = &atafb_switch; | ||
2797 | fb_info.updatevar = &fb_update_var; | ||
2798 | fb_info.flags = FBINFO_FLAG_DEFAULT; | ||
2799 | do_fb_set_var(&atafb_predefined[default_par-1], 1); | ||
2800 | strcat(fb_info.modename, fb_var_names[default_par-1][0]); | ||
2801 | |||
2802 | atafb_get_var(&disp.var, -1, &fb_info); | ||
2803 | atafb_set_disp(-1, &fb_info); | ||
2804 | do_install_cmap(0, &fb_info); | ||
2805 | |||
2806 | if (register_framebuffer(&fb_info) < 0) { | ||
2807 | #ifdef ATAFB_EXT | ||
2808 | if (external_addr) { | ||
2809 | iounmap(external_addr); | ||
2810 | external_addr = NULL; | ||
2811 | } | ||
2812 | if (external_vgaiobase) { | ||
2813 | iounmap((void*)external_vgaiobase); | ||
2814 | external_vgaiobase = 0; | ||
2815 | } | ||
2816 | #endif | ||
2817 | return -EINVAL; | ||
2818 | } | ||
2819 | |||
2820 | printk("Determined %dx%d, depth %d\n", | ||
2821 | disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); | ||
2822 | if ((disp.var.xres != disp.var.xres_virtual) || | ||
2823 | (disp.var.yres != disp.var.yres_virtual)) | ||
2824 | printk(" virtual %dx%d\n", | ||
2825 | disp.var.xres_virtual, disp.var.yres_virtual); | ||
2826 | printk("fb%d: %s frame buffer device, using %dK of video memory\n", | ||
2827 | fb_info.node, fb_info.modename, screen_len>>10); | ||
2828 | |||
2829 | /* TODO: This driver cannot be unloaded yet */ | ||
2830 | return 0; | ||
2831 | } | 2826 | } |
2832 | 2827 | ||
2833 | |||
2834 | #ifdef ATAFB_EXT | 2828 | #ifdef ATAFB_EXT |
2835 | static void __init atafb_setup_ext(char *spec) | 2829 | static void __init atafb_setup_ext(char *spec) |
2836 | { | 2830 | { |
2837 | int xres, xres_virtual, yres, depth, planes; | 2831 | int xres, xres_virtual, yres, depth, planes; |
2838 | unsigned long addr, len; | 2832 | unsigned long addr, len; |
2839 | char *p; | 2833 | char *p; |
2840 | 2834 | ||
@@ -2848,27 +2842,31 @@ static void __init atafb_setup_ext(char *spec) | |||
2848 | * | 2842 | * |
2849 | * Even xres_virtual is available, we neither support panning nor hw-scrolling! | 2843 | * Even xres_virtual is available, we neither support panning nor hw-scrolling! |
2850 | */ | 2844 | */ |
2851 | if (!(p = strsep(&spec, ";")) || !*p) | 2845 | p = strsep(&spec, ";"); |
2852 | return; | 2846 | if (!p || !*p) |
2847 | return; | ||
2853 | xres_virtual = xres = simple_strtoul(p, NULL, 10); | 2848 | xres_virtual = xres = simple_strtoul(p, NULL, 10); |
2854 | if (xres <= 0) | 2849 | if (xres <= 0) |
2855 | return; | 2850 | return; |
2856 | 2851 | ||
2857 | if (!(p = strsep(&spec, ";")) || !*p) | 2852 | p = strsep(&spec, ";"); |
2858 | return; | 2853 | if (!p || !*p) |
2854 | return; | ||
2859 | yres = simple_strtoul(p, NULL, 10); | 2855 | yres = simple_strtoul(p, NULL, 10); |
2860 | if (yres <= 0) | 2856 | if (yres <= 0) |
2861 | return; | 2857 | return; |
2862 | 2858 | ||
2863 | if (!(p = strsep(&spec, ";")) || !*p) | 2859 | p = strsep(&spec, ";"); |
2864 | return; | 2860 | if (!p || !*p) |
2861 | return; | ||
2865 | depth = simple_strtoul(p, NULL, 10); | 2862 | depth = simple_strtoul(p, NULL, 10); |
2866 | if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && | 2863 | if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && |
2867 | depth != 16 && depth != 24) | 2864 | depth != 16 && depth != 24) |
2868 | return; | 2865 | return; |
2869 | 2866 | ||
2870 | if (!(p = strsep(&spec, ";")) || !*p) | 2867 | p = strsep(&spec, ";"); |
2871 | return; | 2868 | if (!p || !*p) |
2869 | return; | ||
2872 | if (*p == 'i') | 2870 | if (*p == 'i') |
2873 | planes = FB_TYPE_INTERLEAVED_PLANES; | 2871 | planes = FB_TYPE_INTERLEAVED_PLANES; |
2874 | else if (*p == 'p') | 2872 | else if (*p == 'p') |
@@ -2876,25 +2874,27 @@ static void __init atafb_setup_ext(char *spec) | |||
2876 | else if (*p == 'n') | 2874 | else if (*p == 'n') |
2877 | planes = FB_TYPE_PLANES; | 2875 | planes = FB_TYPE_PLANES; |
2878 | else if (*p == 't') | 2876 | else if (*p == 't') |
2879 | planes = -1; /* true color */ | 2877 | planes = -1; /* true color */ |
2880 | else | 2878 | else |
2881 | return; | 2879 | return; |
2882 | 2880 | ||
2883 | 2881 | p = strsep(&spec, ";"); | |
2884 | if (!(p = strsep(&spec, ";")) || !*p) | 2882 | if (!p || !*p) |
2885 | return; | 2883 | return; |
2886 | addr = simple_strtoul(p, NULL, 0); | 2884 | addr = simple_strtoul(p, NULL, 0); |
2887 | 2885 | ||
2888 | if (!(p = strsep(&spec, ";")) || !*p) | 2886 | p = strsep(&spec, ";"); |
2889 | len = xres*yres*depth/8; | 2887 | if (!p || !*p) |
2888 | len = xres * yres * depth / 8; | ||
2890 | else | 2889 | else |
2891 | len = simple_strtoul(p, NULL, 0); | 2890 | len = simple_strtoul(p, NULL, 0); |
2892 | 2891 | ||
2893 | if ((p = strsep(&spec, ";")) && *p) { | 2892 | p = strsep(&spec, ";"); |
2894 | external_vgaiobase=simple_strtoul(p, NULL, 0); | 2893 | if (p && *p) |
2895 | } | 2894 | external_vgaiobase = simple_strtoul(p, NULL, 0); |
2896 | 2895 | ||
2897 | if ((p = strsep(&spec, ";")) && *p) { | 2896 | p = strsep(&spec, ";"); |
2897 | if (p && *p) { | ||
2898 | external_bitspercol = simple_strtoul(p, NULL, 0); | 2898 | external_bitspercol = simple_strtoul(p, NULL, 0); |
2899 | if (external_bitspercol > 8) | 2899 | if (external_bitspercol > 8) |
2900 | external_bitspercol = 8; | 2900 | external_bitspercol = 8; |
@@ -2902,59 +2902,61 @@ static void __init atafb_setup_ext(char *spec) | |||
2902 | external_bitspercol = 1; | 2902 | external_bitspercol = 1; |
2903 | } | 2903 | } |
2904 | 2904 | ||
2905 | if ((p = strsep(&spec, ";")) && *p) { | 2905 | p = strsep(&spec, ";"); |
2906 | if (p && *p) { | ||
2906 | if (!strcmp(p, "vga")) | 2907 | if (!strcmp(p, "vga")) |
2907 | external_card_type = IS_VGA; | 2908 | external_card_type = IS_VGA; |
2908 | if (!strcmp(p, "mv300")) | 2909 | if (!strcmp(p, "mv300")) |
2909 | external_card_type = IS_MV300; | 2910 | external_card_type = IS_MV300; |
2910 | } | 2911 | } |
2911 | 2912 | ||
2912 | if ((p = strsep(&spec, ";")) && *p) { | 2913 | p = strsep(&spec, ";"); |
2914 | if (p && *p) { | ||
2913 | xres_virtual = simple_strtoul(p, NULL, 10); | 2915 | xres_virtual = simple_strtoul(p, NULL, 10); |
2914 | if (xres_virtual < xres) | 2916 | if (xres_virtual < xres) |
2915 | xres_virtual = xres; | 2917 | xres_virtual = xres; |
2916 | if (xres_virtual*yres*depth/8 > len) | 2918 | if (xres_virtual * yres * depth / 8 > len) |
2917 | len=xres_virtual*yres*depth/8; | 2919 | len = xres_virtual * yres * depth / 8; |
2918 | } | 2920 | } |
2919 | 2921 | ||
2920 | external_xres = xres; | 2922 | external_xres = xres; |
2921 | external_xres_virtual = xres_virtual; | 2923 | external_xres_virtual = xres_virtual; |
2922 | external_yres = yres; | 2924 | external_yres = yres; |
2923 | external_depth = depth; | 2925 | external_depth = depth; |
2924 | external_pmode = planes; | 2926 | external_pmode = planes; |
2925 | external_addr = (void *)addr; | 2927 | external_addr = (void *)addr; |
2926 | external_len = len; | 2928 | external_len = len; |
2927 | 2929 | ||
2928 | if (external_card_type == IS_MV300) | 2930 | if (external_card_type == IS_MV300) { |
2929 | switch (external_depth) { | 2931 | switch (external_depth) { |
2930 | case 1: | 2932 | case 1: |
2931 | MV300_reg = MV300_reg_1bit; | 2933 | MV300_reg = MV300_reg_1bit; |
2932 | break; | 2934 | break; |
2933 | case 4: | 2935 | case 4: |
2934 | MV300_reg = MV300_reg_4bit; | 2936 | MV300_reg = MV300_reg_4bit; |
2935 | break; | 2937 | break; |
2936 | case 8: | 2938 | case 8: |
2937 | MV300_reg = MV300_reg_8bit; | 2939 | MV300_reg = MV300_reg_8bit; |
2938 | break; | 2940 | break; |
2939 | } | 2941 | } |
2942 | } | ||
2940 | } | 2943 | } |
2941 | #endif /* ATAFB_EXT */ | 2944 | #endif /* ATAFB_EXT */ |
2942 | 2945 | ||
2943 | |||
2944 | static void __init atafb_setup_int(char *spec) | 2946 | static void __init atafb_setup_int(char *spec) |
2945 | { | 2947 | { |
2946 | /* Format to config extended internal video hardware like OverScan: | 2948 | /* Format to config extended internal video hardware like OverScan: |
2947 | "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" | 2949 | * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" |
2948 | Explanation: | 2950 | * Explanation: |
2949 | <xres>: x-resolution | 2951 | * <xres>: x-resolution |
2950 | <yres>: y-resolution | 2952 | * <yres>: y-resolution |
2951 | The following are only needed if you have an overscan which | 2953 | * The following are only needed if you have an overscan which |
2952 | needs a black border: | 2954 | * needs a black border: |
2953 | <xres_max>: max. length of a line in pixels your OverScan hardware would allow | 2955 | * <xres_max>: max. length of a line in pixels your OverScan hardware would allow |
2954 | <yres_max>: max. number of lines your OverScan hardware would allow | 2956 | * <yres_max>: max. number of lines your OverScan hardware would allow |
2955 | <offset>: Offset from physical beginning to visible beginning | 2957 | * <offset>: Offset from physical beginning to visible beginning |
2956 | of screen in bytes | 2958 | * of screen in bytes |
2957 | */ | 2959 | */ |
2958 | int xres; | 2960 | int xres; |
2959 | char *p; | 2961 | char *p; |
2960 | 2962 | ||
@@ -2963,23 +2965,19 @@ static void __init atafb_setup_int(char *spec) | |||
2963 | xres = simple_strtoul(p, NULL, 10); | 2965 | xres = simple_strtoul(p, NULL, 10); |
2964 | if (!(p = strsep(&spec, ";")) || !*p) | 2966 | if (!(p = strsep(&spec, ";")) || !*p) |
2965 | return; | 2967 | return; |
2966 | sttt_xres=xres; | 2968 | sttt_xres = xres; |
2967 | tt_yres=st_yres=simple_strtoul(p, NULL, 10); | 2969 | tt_yres = st_yres = simple_strtoul(p, NULL, 10); |
2968 | if ((p=strsep(&spec, ";")) && *p) { | 2970 | if ((p = strsep(&spec, ";")) && *p) |
2969 | sttt_xres_virtual=simple_strtoul(p, NULL, 10); | 2971 | sttt_xres_virtual = simple_strtoul(p, NULL, 10); |
2970 | } | 2972 | if ((p = strsep(&spec, ";")) && *p) |
2971 | if ((p=strsep(&spec, ";")) && *p) { | 2973 | sttt_yres_virtual = simple_strtoul(p, NULL, 0); |
2972 | sttt_yres_virtual=simple_strtoul(p, NULL, 0); | 2974 | if ((p = strsep(&spec, ";")) && *p) |
2973 | } | 2975 | ovsc_offset = simple_strtoul(p, NULL, 0); |
2974 | if ((p=strsep(&spec, ";")) && *p) { | ||
2975 | ovsc_offset=simple_strtoul(p, NULL, 0); | ||
2976 | } | ||
2977 | 2976 | ||
2978 | if (ovsc_offset || (sttt_yres_virtual != st_yres)) | 2977 | if (ovsc_offset || (sttt_yres_virtual != st_yres)) |
2979 | use_hwscroll=0; | 2978 | use_hwscroll = 0; |
2980 | } | 2979 | } |
2981 | 2980 | ||
2982 | |||
2983 | #ifdef ATAFB_FALCON | 2981 | #ifdef ATAFB_FALCON |
2984 | static void __init atafb_setup_mcap(char *spec) | 2982 | static void __init atafb_setup_mcap(char *spec) |
2985 | { | 2983 | { |
@@ -3018,7 +3016,6 @@ static void __init atafb_setup_mcap(char *spec) | |||
3018 | } | 3016 | } |
3019 | #endif /* ATAFB_FALCON */ | 3017 | #endif /* ATAFB_FALCON */ |
3020 | 3018 | ||
3021 | |||
3022 | static void __init atafb_setup_user(char *spec) | 3019 | static void __init atafb_setup_user(char *spec) |
3023 | { | 3020 | { |
3024 | /* Format of user defined video mode is: <xres>;<yres>;<depth> | 3021 | /* Format of user defined video mode is: <xres>;<yres>;<depth> |
@@ -3026,81 +3023,257 @@ static void __init atafb_setup_user(char *spec) | |||
3026 | char *p; | 3023 | char *p; |
3027 | int xres, yres, depth, temp; | 3024 | int xres, yres, depth, temp; |
3028 | 3025 | ||
3029 | if (!(p = strsep(&spec, ";")) || !*p) | 3026 | p = strsep(&spec, ";"); |
3027 | if (!p || !*p) | ||
3030 | return; | 3028 | return; |
3031 | xres = simple_strtoul(p, NULL, 10); | 3029 | xres = simple_strtoul(p, NULL, 10); |
3032 | if (!(p = strsep(&spec, ";")) || !*p) | 3030 | p = strsep(&spec, ";"); |
3031 | if (!p || !*p) | ||
3033 | return; | 3032 | return; |
3034 | yres = simple_strtoul(p, NULL, 10); | 3033 | yres = simple_strtoul(p, NULL, 10); |
3035 | if (!(p = strsep(&spec, "")) || !*p) | 3034 | p = strsep(&spec, ""); |
3035 | if (!p || !*p) | ||
3036 | return; | 3036 | return; |
3037 | depth = simple_strtoul(p, NULL, 10); | 3037 | depth = simple_strtoul(p, NULL, 10); |
3038 | if ((temp=get_video_mode("user0"))) { | 3038 | temp = get_video_mode("user0"); |
3039 | default_par=temp; | 3039 | if (temp) { |
3040 | atafb_predefined[default_par-1].xres = xres; | 3040 | default_par = temp; |
3041 | atafb_predefined[default_par-1].yres = yres; | 3041 | atafb_predefined[default_par - 1].xres = xres; |
3042 | atafb_predefined[default_par-1].bits_per_pixel = depth; | 3042 | atafb_predefined[default_par - 1].yres = yres; |
3043 | atafb_predefined[default_par - 1].bits_per_pixel = depth; | ||
3043 | } | 3044 | } |
3044 | } | 3045 | } |
3045 | 3046 | ||
3046 | int __init atafb_setup( char *options ) | 3047 | int __init atafb_setup(char *options) |
3047 | { | 3048 | { |
3048 | char *this_opt; | 3049 | char *this_opt; |
3049 | int temp; | 3050 | int temp; |
3050 | |||
3051 | fb_info.fontname[0] = '\0'; | ||
3052 | 3051 | ||
3053 | if (!options || !*options) | 3052 | if (!options || !*options) |
3054 | return 0; | 3053 | return 0; |
3055 | 3054 | ||
3056 | while ((this_opt = strsep(&options, ",")) != NULL) { | 3055 | while ((this_opt = strsep(&options, ",")) != NULL) { |
3057 | if (!*this_opt) continue; | 3056 | if (!*this_opt) |
3058 | if ((temp=get_video_mode(this_opt))) | 3057 | continue; |
3059 | default_par=temp; | 3058 | if ((temp = get_video_mode(this_opt))) { |
3060 | else if (! strcmp(this_opt, "inverse")) | 3059 | default_par = temp; |
3061 | inverse=1; | 3060 | mode_option = this_opt; |
3062 | else if (!strncmp(this_opt, "font:", 5)) | 3061 | } else if (!strcmp(this_opt, "inverse")) |
3063 | strcpy(fb_info.fontname, this_opt+5); | 3062 | inverse = 1; |
3064 | else if (! strncmp(this_opt, "hwscroll_",9)) { | 3063 | else if (!strncmp(this_opt, "hwscroll_", 9)) { |
3065 | hwscroll=simple_strtoul(this_opt+9, NULL, 10); | 3064 | hwscroll = simple_strtoul(this_opt + 9, NULL, 10); |
3066 | if (hwscroll < 0) | 3065 | if (hwscroll < 0) |
3067 | hwscroll = 0; | 3066 | hwscroll = 0; |
3068 | if (hwscroll > 200) | 3067 | if (hwscroll > 200) |
3069 | hwscroll = 200; | 3068 | hwscroll = 200; |
3070 | } | 3069 | } |
3071 | #ifdef ATAFB_EXT | 3070 | #ifdef ATAFB_EXT |
3072 | else if (!strcmp(this_opt,"mv300")) { | 3071 | else if (!strcmp(this_opt, "mv300")) { |
3073 | external_bitspercol = 8; | 3072 | external_bitspercol = 8; |
3074 | external_card_type = IS_MV300; | 3073 | external_card_type = IS_MV300; |
3074 | } else if (!strncmp(this_opt, "external:", 9)) | ||
3075 | atafb_setup_ext(this_opt + 9); | ||
3076 | #endif | ||
3077 | else if (!strncmp(this_opt, "internal:", 9)) | ||
3078 | atafb_setup_int(this_opt + 9); | ||
3079 | #ifdef ATAFB_FALCON | ||
3080 | else if (!strncmp(this_opt, "eclock:", 7)) { | ||
3081 | fext.f = simple_strtoul(this_opt + 7, NULL, 10); | ||
3082 | /* external pixelclock in kHz --> ps */ | ||
3083 | fext.t = 1000000000 / fext.f; | ||
3084 | fext.f *= 1000; | ||
3085 | } else if (!strncmp(this_opt, "monitorcap:", 11)) | ||
3086 | atafb_setup_mcap(this_opt + 11); | ||
3087 | #endif | ||
3088 | else if (!strcmp(this_opt, "keep")) | ||
3089 | DontCalcRes = 1; | ||
3090 | else if (!strncmp(this_opt, "R", 1)) | ||
3091 | atafb_setup_user(this_opt + 1); | ||
3075 | } | 3092 | } |
3076 | else if (!strncmp(this_opt,"external:",9)) | 3093 | return 0; |
3077 | atafb_setup_ext(this_opt+9); | 3094 | } |
3095 | |||
3096 | int __init atafb_init(void) | ||
3097 | { | ||
3098 | int pad; | ||
3099 | int detected_mode; | ||
3100 | unsigned int defmode = 0; | ||
3101 | unsigned long mem_req; | ||
3102 | |||
3103 | #ifndef MODULE | ||
3104 | char *option = NULL; | ||
3105 | |||
3106 | if (fb_get_options("atafb", &option)) | ||
3107 | return -ENODEV; | ||
3108 | atafb_setup(option); | ||
3109 | #endif | ||
3110 | printk("atafb_init: start\n"); | ||
3111 | |||
3112 | if (!MACH_IS_ATARI) | ||
3113 | return -ENXIO; | ||
3114 | |||
3115 | do { | ||
3116 | #ifdef ATAFB_EXT | ||
3117 | if (external_addr) { | ||
3118 | printk("atafb_init: initializing external hw\n"); | ||
3119 | fbhw = &ext_switch; | ||
3120 | atafb_ops.fb_setcolreg = &ext_setcolreg; | ||
3121 | defmode = DEFMODE_EXT; | ||
3122 | break; | ||
3123 | } | ||
3124 | #endif | ||
3125 | #ifdef ATAFB_TT | ||
3126 | if (ATARIHW_PRESENT(TT_SHIFTER)) { | ||
3127 | printk("atafb_init: initializing TT hw\n"); | ||
3128 | fbhw = &tt_switch; | ||
3129 | atafb_ops.fb_setcolreg = &tt_setcolreg; | ||
3130 | defmode = DEFMODE_TT; | ||
3131 | break; | ||
3132 | } | ||
3078 | #endif | 3133 | #endif |
3079 | else if (!strncmp(this_opt,"internal:",9)) | ||
3080 | atafb_setup_int(this_opt+9); | ||
3081 | #ifdef ATAFB_FALCON | 3134 | #ifdef ATAFB_FALCON |
3082 | else if (!strncmp(this_opt, "eclock:", 7)) { | 3135 | if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { |
3083 | fext.f = simple_strtoul(this_opt+7, NULL, 10); | 3136 | printk("atafb_init: initializing Falcon hw\n"); |
3084 | /* external pixelclock in kHz --> ps */ | 3137 | fbhw = &falcon_switch; |
3085 | fext.t = 1000000000/fext.f; | 3138 | atafb_ops.fb_setcolreg = &falcon_setcolreg; |
3086 | fext.f *= 1000; | 3139 | request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, |
3140 | "framebuffer/modeswitch", falcon_vbl_switcher); | ||
3141 | defmode = DEFMODE_F30; | ||
3142 | break; | ||
3143 | } | ||
3144 | #endif | ||
3145 | #ifdef ATAFB_STE | ||
3146 | if (ATARIHW_PRESENT(STND_SHIFTER) || | ||
3147 | ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
3148 | printk("atafb_init: initializing ST/E hw\n"); | ||
3149 | fbhw = &st_switch; | ||
3150 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
3151 | defmode = DEFMODE_STE; | ||
3152 | break; | ||
3153 | } | ||
3154 | fbhw = &st_switch; | ||
3155 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
3156 | printk("Cannot determine video hardware; defaulting to ST(e)\n"); | ||
3157 | #else /* ATAFB_STE */ | ||
3158 | /* no default driver included */ | ||
3159 | /* Nobody will ever see this message :-) */ | ||
3160 | panic("Cannot initialize video hardware"); | ||
3161 | #endif | ||
3162 | } while (0); | ||
3163 | |||
3164 | /* Multisync monitor capabilities */ | ||
3165 | /* Atari-TOS defaults if no boot option present */ | ||
3166 | if (fb_info.monspecs.hfmin == 0) { | ||
3167 | fb_info.monspecs.hfmin = 31000; | ||
3168 | fb_info.monspecs.hfmax = 32000; | ||
3169 | fb_info.monspecs.vfmin = 58; | ||
3170 | fb_info.monspecs.vfmax = 62; | ||
3087 | } | 3171 | } |
3088 | else if (!strncmp(this_opt, "monitorcap:", 11)) | 3172 | |
3089 | atafb_setup_mcap(this_opt+11); | 3173 | detected_mode = fbhw->detect(); |
3174 | check_default_par(detected_mode); | ||
3175 | #ifdef ATAFB_EXT | ||
3176 | if (!external_addr) { | ||
3177 | #endif /* ATAFB_EXT */ | ||
3178 | mem_req = default_mem_req + ovsc_offset + ovsc_addlen; | ||
3179 | mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; | ||
3180 | screen_base = atari_stram_alloc(mem_req, "atafb"); | ||
3181 | if (!screen_base) | ||
3182 | panic("Cannot allocate screen memory"); | ||
3183 | memset(screen_base, 0, mem_req); | ||
3184 | pad = -(unsigned long)screen_base & (PAGE_SIZE - 1); | ||
3185 | screen_base += pad; | ||
3186 | real_screen_base = screen_base + ovsc_offset; | ||
3187 | screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; | ||
3188 | st_ovsc_switch(); | ||
3189 | if (CPU_IS_040_OR_060) { | ||
3190 | /* On a '040+, the cache mode of video RAM must be set to | ||
3191 | * write-through also for internal video hardware! */ | ||
3192 | cache_push(virt_to_phys(screen_base), screen_len); | ||
3193 | kernel_set_cachemode(screen_base, screen_len, | ||
3194 | IOMAP_WRITETHROUGH); | ||
3195 | } | ||
3196 | printk("atafb: screen_base %p real_screen_base %p screen_len %d\n", | ||
3197 | screen_base, real_screen_base, screen_len); | ||
3198 | #ifdef ATAFB_EXT | ||
3199 | } else { | ||
3200 | /* Map the video memory (physical address given) to somewhere | ||
3201 | * in the kernel address space. | ||
3202 | */ | ||
3203 | external_addr = ioremap_writethrough((unsigned long)external_addr, | ||
3204 | external_len); | ||
3205 | if (external_vgaiobase) | ||
3206 | external_vgaiobase = | ||
3207 | (unsigned long)ioremap(external_vgaiobase, 0x10000); | ||
3208 | screen_base = | ||
3209 | real_screen_base = external_addr; | ||
3210 | screen_len = external_len & PAGE_MASK; | ||
3211 | memset (screen_base, 0, external_len); | ||
3212 | } | ||
3213 | #endif /* ATAFB_EXT */ | ||
3214 | |||
3215 | // strcpy(fb_info.mode->name, "Atari Builtin "); | ||
3216 | fb_info.fbops = &atafb_ops; | ||
3217 | // try to set default (detected; requested) var | ||
3218 | do_fb_set_var(&atafb_predefined[default_par - 1], 1); | ||
3219 | // reads hw state into current par, which may not be sane yet | ||
3220 | ata_get_par(¤t_par); | ||
3221 | fb_info.par = ¤t_par; | ||
3222 | // tries to read from HW which may not be initialized yet | ||
3223 | // so set sane var first, then call atafb_set_par | ||
3224 | atafb_get_var(&fb_info.var, &fb_info); | ||
3225 | fb_info.flags = FBINFO_FLAG_DEFAULT; | ||
3226 | |||
3227 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb, | ||
3228 | NUM_TOTAL_MODES, &atafb_modedb[defmode], | ||
3229 | fb_info.var.bits_per_pixel)) { | ||
3230 | return -EINVAL; | ||
3231 | } | ||
3232 | |||
3233 | atafb_set_disp(&fb_info); | ||
3234 | |||
3235 | fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); | ||
3236 | |||
3237 | |||
3238 | printk("Determined %dx%d, depth %d\n", | ||
3239 | fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel); | ||
3240 | if ((fb_info.var.xres != fb_info.var.xres_virtual) || | ||
3241 | (fb_info.var.yres != fb_info.var.yres_virtual)) | ||
3242 | printk(" virtual %dx%d\n", fb_info.var.xres_virtual, | ||
3243 | fb_info.var.yres_virtual); | ||
3244 | |||
3245 | if (register_framebuffer(&fb_info) < 0) { | ||
3246 | #ifdef ATAFB_EXT | ||
3247 | if (external_addr) { | ||
3248 | iounmap(external_addr); | ||
3249 | external_addr = NULL; | ||
3250 | } | ||
3251 | if (external_vgaiobase) { | ||
3252 | iounmap((void*)external_vgaiobase); | ||
3253 | external_vgaiobase = 0; | ||
3254 | } | ||
3090 | #endif | 3255 | #endif |
3091 | else if (!strcmp(this_opt, "keep")) | 3256 | return -EINVAL; |
3092 | DontCalcRes = 1; | 3257 | } |
3093 | else if (!strncmp(this_opt, "R", 1)) | 3258 | |
3094 | atafb_setup_user(this_opt+1); | 3259 | // FIXME: mode needs setting! |
3095 | } | 3260 | //printk("fb%d: %s frame buffer device, using %dK of video memory\n", |
3096 | return 0; | 3261 | // fb_info.node, fb_info.mode->name, screen_len>>10); |
3262 | printk("fb%d: frame buffer device, using %dK of video memory\n", | ||
3263 | fb_info.node, screen_len >> 10); | ||
3264 | |||
3265 | /* TODO: This driver cannot be unloaded yet */ | ||
3266 | return 0; | ||
3097 | } | 3267 | } |
3098 | 3268 | ||
3269 | module_init(atafb_init); | ||
3270 | |||
3099 | #ifdef MODULE | 3271 | #ifdef MODULE |
3100 | MODULE_LICENSE("GPL"); | 3272 | MODULE_LICENSE("GPL"); |
3101 | 3273 | ||
3102 | int init_module(void) | 3274 | int cleanup_module(void) |
3103 | { | 3275 | { |
3104 | return atafb_init(); | 3276 | unregister_framebuffer(&fb_info); |
3277 | return atafb_deinit(); | ||
3105 | } | 3278 | } |
3106 | #endif /* MODULE */ | 3279 | #endif /* MODULE */ |
diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h new file mode 100644 index 000000000000..014e05906cb1 --- /dev/null +++ b/drivers/video/atafb.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _VIDEO_ATAFB_H | ||
2 | #define _VIDEO_ATAFB_H | ||
3 | |||
4 | void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
5 | int dx, int height, int width); | ||
6 | void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
7 | int sy, int sx, int height, int width); | ||
8 | void atafb_mfb_linefill(struct fb_info *info, u_long next_line, | ||
9 | int dy, int dx, u32 width, | ||
10 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
11 | |||
12 | void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
13 | int dx, int height, int width); | ||
14 | void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
15 | int sy, int sx, int height, int width); | ||
16 | void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, | ||
17 | int dy, int dx, u32 width, | ||
18 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
19 | |||
20 | void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
21 | int dx, int height, int width); | ||
22 | void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
23 | int sy, int sx, int height, int width); | ||
24 | void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, | ||
25 | int dy, int dx, u32 width, | ||
26 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
27 | |||
28 | void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
29 | int dx, int height, int width); | ||
30 | void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
31 | int sy, int sx, int height, int width); | ||
32 | void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, | ||
33 | int dy, int dx, u32 width, | ||
34 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
35 | |||
36 | #endif /* _VIDEO_ATAFB_H */ | ||
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c new file mode 100644 index 000000000000..8cc9c50379d0 --- /dev/null +++ b/drivers/video/atafb_iplan2p2.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (2 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 2 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | /* bmove() has to distinguish two major cases: If both, source and | ||
29 | * destination, start at even addresses or both are at odd | ||
30 | * addresses, just the first odd and last even column (if present) | ||
31 | * require special treatment (memmove_col()). The rest between | ||
32 | * then can be copied by normal operations, because all adjacent | ||
33 | * bytes are affected and are to be stored in the same order. | ||
34 | * The pathological case is when the move should go from an odd | ||
35 | * address to an even or vice versa. Since the bytes in the plane | ||
36 | * words must be assembled in new order, it seems wisest to make | ||
37 | * all movements by memmove_col(). | ||
38 | */ | ||
39 | |||
40 | u8 *src, *dst; | ||
41 | u32 *s, *d; | ||
42 | int w, l , i, j; | ||
43 | u_int colsize; | ||
44 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
45 | |||
46 | colsize = height; | ||
47 | if (!((sx ^ dx) & 15)) { | ||
48 | /* odd->odd or even->even */ | ||
49 | |||
50 | if (upwards) { | ||
51 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
52 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
53 | if (sx & 15) { | ||
54 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
55 | src += BPL * 2; | ||
56 | dst += BPL * 2; | ||
57 | width -= 8; | ||
58 | } | ||
59 | w = width >> 4; | ||
60 | if (w) { | ||
61 | s = (u32 *)src; | ||
62 | d = (u32 *)dst; | ||
63 | w *= BPL / 2; | ||
64 | l = next_line - w * 4; | ||
65 | for (j = height; j > 0; j--) { | ||
66 | for (i = w; i > 0; i--) | ||
67 | *d++ = *s++; | ||
68 | s = (u32 *)((u8 *)s + l); | ||
69 | d = (u32 *)((u8 *)d + l); | ||
70 | } | ||
71 | } | ||
72 | if (width & 15) | ||
73 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
74 | 0xff00ff00, height, next_line - BPL * 2); | ||
75 | } else { | ||
76 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
77 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
78 | |||
79 | if ((sx + width) & 15) { | ||
80 | src -= BPL * 2; | ||
81 | dst -= BPL * 2; | ||
82 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
83 | width -= 8; | ||
84 | } | ||
85 | w = width >> 4; | ||
86 | if (w) { | ||
87 | s = (u32 *)src; | ||
88 | d = (u32 *)dst; | ||
89 | w *= BPL / 2; | ||
90 | l = next_line - w * 4; | ||
91 | for (j = height; j > 0; j--) { | ||
92 | for (i = w; i > 0; i--) | ||
93 | *--d = *--s; | ||
94 | s = (u32 *)((u8 *)s - l); | ||
95 | d = (u32 *)((u8 *)d - l); | ||
96 | } | ||
97 | } | ||
98 | if (sx & 15) | ||
99 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
100 | src - (width - 16) / (8 / BPL), | ||
101 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
102 | } | ||
103 | } else { | ||
104 | /* odd->even or even->odd */ | ||
105 | if (upwards) { | ||
106 | u32 *src32, *dst32; | ||
107 | u32 pval[4], v, v1, mask; | ||
108 | int i, j, w, f; | ||
109 | |||
110 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
111 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
112 | |||
113 | mask = 0xff00ff00; | ||
114 | f = 0; | ||
115 | w = width; | ||
116 | if (sx & 15) { | ||
117 | f = 1; | ||
118 | w += 8; | ||
119 | } | ||
120 | if ((sx + width) & 15) | ||
121 | f |= 2; | ||
122 | w >>= 4; | ||
123 | for (i = height; i; i--) { | ||
124 | src32 = (u32 *)src; | ||
125 | dst32 = (u32 *)dst; | ||
126 | |||
127 | if (f & 1) { | ||
128 | pval[0] = (*src32++ << 8) & mask; | ||
129 | } else { | ||
130 | pval[0] = dst32[0] & mask; | ||
131 | } | ||
132 | |||
133 | for (j = w; j > 0; j--) { | ||
134 | v = *src32++; | ||
135 | v1 = v & mask; | ||
136 | *dst32++ = pval[0] | (v1 >> 8); | ||
137 | pval[0] = (v ^ v1) << 8; | ||
138 | } | ||
139 | |||
140 | if (f & 2) { | ||
141 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
142 | } | ||
143 | |||
144 | src += next_line; | ||
145 | dst += next_line; | ||
146 | } | ||
147 | } else { | ||
148 | u32 *src32, *dst32; | ||
149 | u32 pval[4], v, v1, mask; | ||
150 | int i, j, w, f; | ||
151 | |||
152 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
153 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
154 | |||
155 | mask = 0xff00ff; | ||
156 | f = 0; | ||
157 | w = width; | ||
158 | if ((dx + width) & 15) | ||
159 | f = 1; | ||
160 | if (sx & 15) { | ||
161 | f |= 2; | ||
162 | w += 8; | ||
163 | } | ||
164 | w >>= 4; | ||
165 | for (i = height; i; i--) { | ||
166 | src32 = (u32 *)src; | ||
167 | dst32 = (u32 *)dst; | ||
168 | |||
169 | if (f & 1) { | ||
170 | pval[0] = dst32[-1] & mask; | ||
171 | } else { | ||
172 | pval[0] = (*--src32 >> 8) & mask; | ||
173 | } | ||
174 | |||
175 | for (j = w; j > 0; j--) { | ||
176 | v = *--src32; | ||
177 | v1 = v & mask; | ||
178 | *--dst32 = pval[0] | (v1 << 8); | ||
179 | pval[0] = (v ^ v1) >> 8; | ||
180 | } | ||
181 | |||
182 | if (!(f & 2)) { | ||
183 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
184 | } | ||
185 | |||
186 | src -= next_line; | ||
187 | dst -= next_line; | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
193 | void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
194 | int sy, int sx, int height, int width) | ||
195 | { | ||
196 | u32 *dest; | ||
197 | int rows, i; | ||
198 | u32 cval[4]; | ||
199 | |||
200 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
201 | if (sx & 15) { | ||
202 | u8 *dest8 = (u8 *)dest + 1; | ||
203 | |||
204 | expand8_col2mask(color, cval); | ||
205 | |||
206 | for (i = height; i; i--) { | ||
207 | fill8_col(dest8, cval); | ||
208 | dest8 += next_line; | ||
209 | } | ||
210 | dest += BPL / 2; | ||
211 | width -= 8; | ||
212 | } | ||
213 | |||
214 | expand16_col2mask(color, cval); | ||
215 | rows = width >> 4; | ||
216 | if (rows) { | ||
217 | u32 *d = dest; | ||
218 | u32 off = next_line - rows * BPL * 2; | ||
219 | for (i = height; i; i--) { | ||
220 | d = fill16_col(d, rows, cval); | ||
221 | d = (u32 *)((long)d + off); | ||
222 | } | ||
223 | dest += rows * BPL / 2; | ||
224 | width &= 15; | ||
225 | } | ||
226 | |||
227 | if (width) { | ||
228 | u8 *dest8 = (u8 *)dest; | ||
229 | |||
230 | expand8_col2mask(color, cval); | ||
231 | |||
232 | for (i = height; i; i--) { | ||
233 | fill8_col(dest8, cval); | ||
234 | dest8 += next_line; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, | ||
240 | int dy, int dx, u32 width, | ||
241 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
242 | { | ||
243 | u32 *dest; | ||
244 | const u16 *data16; | ||
245 | int rows; | ||
246 | u32 fgm[4], bgm[4], m; | ||
247 | |||
248 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
249 | if (dx & 15) { | ||
250 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
251 | dest += BPL / 2; | ||
252 | width -= 8; | ||
253 | } | ||
254 | |||
255 | if (width >= 16) { | ||
256 | data16 = (const u16 *)data; | ||
257 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
258 | |||
259 | for (rows = width / 16; rows; rows--) { | ||
260 | u16 d = *data16++; | ||
261 | m = d | ((u32)d << 16); | ||
262 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
263 | } | ||
264 | |||
265 | data = (const u8 *)data16; | ||
266 | width &= 15; | ||
267 | } | ||
268 | |||
269 | if (width) | ||
270 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
271 | } | ||
272 | |||
273 | #ifdef MODULE | ||
274 | MODULE_LICENSE("GPL"); | ||
275 | |||
276 | int init_module(void) | ||
277 | { | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | void cleanup_module(void) | ||
282 | { | ||
283 | } | ||
284 | #endif /* MODULE */ | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Visible symbols for modules | ||
289 | */ | ||
290 | |||
291 | EXPORT_SYMBOL(atafb_iplan2p2_copyarea); | ||
292 | EXPORT_SYMBOL(atafb_iplan2p2_fillrect); | ||
293 | EXPORT_SYMBOL(atafb_iplan2p2_linefill); | ||
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c new file mode 100644 index 000000000000..bee0d89463f7 --- /dev/null +++ b/drivers/video/atafb_iplan2p4.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (4 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 4 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | /* bmove() has to distinguish two major cases: If both, source and | ||
29 | * destination, start at even addresses or both are at odd | ||
30 | * addresses, just the first odd and last even column (if present) | ||
31 | * require special treatment (memmove_col()). The rest between | ||
32 | * then can be copied by normal operations, because all adjacent | ||
33 | * bytes are affected and are to be stored in the same order. | ||
34 | * The pathological case is when the move should go from an odd | ||
35 | * address to an even or vice versa. Since the bytes in the plane | ||
36 | * words must be assembled in new order, it seems wisest to make | ||
37 | * all movements by memmove_col(). | ||
38 | */ | ||
39 | |||
40 | u8 *src, *dst; | ||
41 | u32 *s, *d; | ||
42 | int w, l , i, j; | ||
43 | u_int colsize; | ||
44 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
45 | |||
46 | colsize = height; | ||
47 | if (!((sx ^ dx) & 15)) { | ||
48 | /* odd->odd or even->even */ | ||
49 | |||
50 | if (upwards) { | ||
51 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
52 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
53 | if (sx & 15) { | ||
54 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
55 | src += BPL * 2; | ||
56 | dst += BPL * 2; | ||
57 | width -= 8; | ||
58 | } | ||
59 | w = width >> 4; | ||
60 | if (w) { | ||
61 | s = (u32 *)src; | ||
62 | d = (u32 *)dst; | ||
63 | w *= BPL / 2; | ||
64 | l = next_line - w * 4; | ||
65 | for (j = height; j > 0; j--) { | ||
66 | for (i = w; i > 0; i--) | ||
67 | *d++ = *s++; | ||
68 | s = (u32 *)((u8 *)s + l); | ||
69 | d = (u32 *)((u8 *)d + l); | ||
70 | } | ||
71 | } | ||
72 | if (width & 15) | ||
73 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
74 | 0xff00ff00, height, next_line - BPL * 2); | ||
75 | } else { | ||
76 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
77 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
78 | |||
79 | if ((sx + width) & 15) { | ||
80 | src -= BPL * 2; | ||
81 | dst -= BPL * 2; | ||
82 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
83 | width -= 8; | ||
84 | } | ||
85 | w = width >> 4; | ||
86 | if (w) { | ||
87 | s = (u32 *)src; | ||
88 | d = (u32 *)dst; | ||
89 | w *= BPL / 2; | ||
90 | l = next_line - w * 4; | ||
91 | for (j = height; j > 0; j--) { | ||
92 | for (i = w; i > 0; i--) | ||
93 | *--d = *--s; | ||
94 | s = (u32 *)((u8 *)s - l); | ||
95 | d = (u32 *)((u8 *)d - l); | ||
96 | } | ||
97 | } | ||
98 | if (sx & 15) | ||
99 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
100 | src - (width - 16) / (8 / BPL), | ||
101 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
102 | } | ||
103 | } else { | ||
104 | /* odd->even or even->odd */ | ||
105 | if (upwards) { | ||
106 | u32 *src32, *dst32; | ||
107 | u32 pval[4], v, v1, mask; | ||
108 | int i, j, w, f; | ||
109 | |||
110 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
111 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
112 | |||
113 | mask = 0xff00ff00; | ||
114 | f = 0; | ||
115 | w = width; | ||
116 | if (sx & 15) { | ||
117 | f = 1; | ||
118 | w += 8; | ||
119 | } | ||
120 | if ((sx + width) & 15) | ||
121 | f |= 2; | ||
122 | w >>= 4; | ||
123 | for (i = height; i; i--) { | ||
124 | src32 = (u32 *)src; | ||
125 | dst32 = (u32 *)dst; | ||
126 | |||
127 | if (f & 1) { | ||
128 | pval[0] = (*src32++ << 8) & mask; | ||
129 | pval[1] = (*src32++ << 8) & mask; | ||
130 | } else { | ||
131 | pval[0] = dst32[0] & mask; | ||
132 | pval[1] = dst32[1] & mask; | ||
133 | } | ||
134 | |||
135 | for (j = w; j > 0; j--) { | ||
136 | v = *src32++; | ||
137 | v1 = v & mask; | ||
138 | *dst32++ = pval[0] | (v1 >> 8); | ||
139 | pval[0] = (v ^ v1) << 8; | ||
140 | v = *src32++; | ||
141 | v1 = v & mask; | ||
142 | *dst32++ = pval[1] | (v1 >> 8); | ||
143 | pval[1] = (v ^ v1) << 8; | ||
144 | } | ||
145 | |||
146 | if (f & 2) { | ||
147 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
148 | dst32[1] = (dst32[1] & mask) | pval[1]; | ||
149 | } | ||
150 | |||
151 | src += next_line; | ||
152 | dst += next_line; | ||
153 | } | ||
154 | } else { | ||
155 | u32 *src32, *dst32; | ||
156 | u32 pval[4], v, v1, mask; | ||
157 | int i, j, w, f; | ||
158 | |||
159 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
160 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
161 | |||
162 | mask = 0xff00ff; | ||
163 | f = 0; | ||
164 | w = width; | ||
165 | if ((dx + width) & 15) | ||
166 | f = 1; | ||
167 | if (sx & 15) { | ||
168 | f |= 2; | ||
169 | w += 8; | ||
170 | } | ||
171 | w >>= 4; | ||
172 | for (i = height; i; i--) { | ||
173 | src32 = (u32 *)src; | ||
174 | dst32 = (u32 *)dst; | ||
175 | |||
176 | if (f & 1) { | ||
177 | pval[0] = dst32[-1] & mask; | ||
178 | pval[1] = dst32[-2] & mask; | ||
179 | } else { | ||
180 | pval[0] = (*--src32 >> 8) & mask; | ||
181 | pval[1] = (*--src32 >> 8) & mask; | ||
182 | } | ||
183 | |||
184 | for (j = w; j > 0; j--) { | ||
185 | v = *--src32; | ||
186 | v1 = v & mask; | ||
187 | *--dst32 = pval[0] | (v1 << 8); | ||
188 | pval[0] = (v ^ v1) >> 8; | ||
189 | v = *--src32; | ||
190 | v1 = v & mask; | ||
191 | *--dst32 = pval[1] | (v1 << 8); | ||
192 | pval[1] = (v ^ v1) >> 8; | ||
193 | } | ||
194 | |||
195 | if (!(f & 2)) { | ||
196 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
197 | dst32[-2] = (dst32[-2] & mask) | pval[1]; | ||
198 | } | ||
199 | |||
200 | src -= next_line; | ||
201 | dst -= next_line; | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
208 | int sy, int sx, int height, int width) | ||
209 | { | ||
210 | u32 *dest; | ||
211 | int rows, i; | ||
212 | u32 cval[4]; | ||
213 | |||
214 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
215 | if (sx & 15) { | ||
216 | u8 *dest8 = (u8 *)dest + 1; | ||
217 | |||
218 | expand8_col2mask(color, cval); | ||
219 | |||
220 | for (i = height; i; i--) { | ||
221 | fill8_col(dest8, cval); | ||
222 | dest8 += next_line; | ||
223 | } | ||
224 | dest += BPL / 2; | ||
225 | width -= 8; | ||
226 | } | ||
227 | |||
228 | expand16_col2mask(color, cval); | ||
229 | rows = width >> 4; | ||
230 | if (rows) { | ||
231 | u32 *d = dest; | ||
232 | u32 off = next_line - rows * BPL * 2; | ||
233 | for (i = height; i; i--) { | ||
234 | d = fill16_col(d, rows, cval); | ||
235 | d = (u32 *)((long)d + off); | ||
236 | } | ||
237 | dest += rows * BPL / 2; | ||
238 | width &= 15; | ||
239 | } | ||
240 | |||
241 | if (width) { | ||
242 | u8 *dest8 = (u8 *)dest; | ||
243 | |||
244 | expand8_col2mask(color, cval); | ||
245 | |||
246 | for (i = height; i; i--) { | ||
247 | fill8_col(dest8, cval); | ||
248 | dest8 += next_line; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, | ||
254 | int dy, int dx, u32 width, | ||
255 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
256 | { | ||
257 | u32 *dest; | ||
258 | const u16 *data16; | ||
259 | int rows; | ||
260 | u32 fgm[4], bgm[4], m; | ||
261 | |||
262 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
263 | if (dx & 15) { | ||
264 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
265 | dest += BPL / 2; | ||
266 | width -= 8; | ||
267 | } | ||
268 | |||
269 | if (width >= 16) { | ||
270 | data16 = (const u16 *)data; | ||
271 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
272 | |||
273 | for (rows = width / 16; rows; rows--) { | ||
274 | u16 d = *data16++; | ||
275 | m = d | ((u32)d << 16); | ||
276 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
277 | *dest++ = (m & fgm[1]) ^ bgm[1]; | ||
278 | } | ||
279 | |||
280 | data = (const u8 *)data16; | ||
281 | width &= 15; | ||
282 | } | ||
283 | |||
284 | if (width) | ||
285 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
286 | } | ||
287 | |||
288 | #ifdef MODULE | ||
289 | MODULE_LICENSE("GPL"); | ||
290 | |||
291 | int init_module(void) | ||
292 | { | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | void cleanup_module(void) | ||
297 | { | ||
298 | } | ||
299 | #endif /* MODULE */ | ||
300 | |||
301 | |||
302 | /* | ||
303 | * Visible symbols for modules | ||
304 | */ | ||
305 | |||
306 | EXPORT_SYMBOL(atafb_iplan2p4_copyarea); | ||
307 | EXPORT_SYMBOL(atafb_iplan2p4_fillrect); | ||
308 | EXPORT_SYMBOL(atafb_iplan2p4_linefill); | ||
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c new file mode 100644 index 000000000000..356fb52ce443 --- /dev/null +++ b/drivers/video/atafb_iplan2p8.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (8 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 8 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | |||
25 | /* Copies a 8 plane column from 's', height 'h', to 'd'. */ | ||
26 | |||
27 | /* This expands a 8 bit color into two longs for two movepl (8 plane) | ||
28 | * operations. | ||
29 | */ | ||
30 | |||
31 | void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, | ||
32 | int sy, int sx, int dy, int dx, | ||
33 | int height, int width) | ||
34 | { | ||
35 | /* bmove() has to distinguish two major cases: If both, source and | ||
36 | * destination, start at even addresses or both are at odd | ||
37 | * addresses, just the first odd and last even column (if present) | ||
38 | * require special treatment (memmove_col()). The rest between | ||
39 | * then can be copied by normal operations, because all adjacent | ||
40 | * bytes are affected and are to be stored in the same order. | ||
41 | * The pathological case is when the move should go from an odd | ||
42 | * address to an even or vice versa. Since the bytes in the plane | ||
43 | * words must be assembled in new order, it seems wisest to make | ||
44 | * all movements by memmove_col(). | ||
45 | */ | ||
46 | |||
47 | u8 *src, *dst; | ||
48 | u32 *s, *d; | ||
49 | int w, l , i, j; | ||
50 | u_int colsize; | ||
51 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
52 | |||
53 | colsize = height; | ||
54 | if (!((sx ^ dx) & 15)) { | ||
55 | /* odd->odd or even->even */ | ||
56 | |||
57 | if (upwards) { | ||
58 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
59 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
60 | if (sx & 15) { | ||
61 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
62 | src += BPL * 2; | ||
63 | dst += BPL * 2; | ||
64 | width -= 8; | ||
65 | } | ||
66 | w = width >> 4; | ||
67 | if (w) { | ||
68 | s = (u32 *)src; | ||
69 | d = (u32 *)dst; | ||
70 | w *= BPL / 2; | ||
71 | l = next_line - w * 4; | ||
72 | for (j = height; j > 0; j--) { | ||
73 | for (i = w; i > 0; i--) | ||
74 | *d++ = *s++; | ||
75 | s = (u32 *)((u8 *)s + l); | ||
76 | d = (u32 *)((u8 *)d + l); | ||
77 | } | ||
78 | } | ||
79 | if (width & 15) | ||
80 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
81 | 0xff00ff00, height, next_line - BPL * 2); | ||
82 | } else { | ||
83 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
84 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
85 | |||
86 | if ((sx + width) & 15) { | ||
87 | src -= BPL * 2; | ||
88 | dst -= BPL * 2; | ||
89 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
90 | width -= 8; | ||
91 | } | ||
92 | w = width >> 4; | ||
93 | if (w) { | ||
94 | s = (u32 *)src; | ||
95 | d = (u32 *)dst; | ||
96 | w *= BPL / 2; | ||
97 | l = next_line - w * 4; | ||
98 | for (j = height; j > 0; j--) { | ||
99 | for (i = w; i > 0; i--) | ||
100 | *--d = *--s; | ||
101 | s = (u32 *)((u8 *)s - l); | ||
102 | d = (u32 *)((u8 *)d - l); | ||
103 | } | ||
104 | } | ||
105 | if (sx & 15) | ||
106 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
107 | src - (width - 16) / (8 / BPL), | ||
108 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
109 | } | ||
110 | } else { | ||
111 | /* odd->even or even->odd */ | ||
112 | if (upwards) { | ||
113 | u32 *src32, *dst32; | ||
114 | u32 pval[4], v, v1, mask; | ||
115 | int i, j, w, f; | ||
116 | |||
117 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
118 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
119 | |||
120 | mask = 0xff00ff00; | ||
121 | f = 0; | ||
122 | w = width; | ||
123 | if (sx & 15) { | ||
124 | f = 1; | ||
125 | w += 8; | ||
126 | } | ||
127 | if ((sx + width) & 15) | ||
128 | f |= 2; | ||
129 | w >>= 4; | ||
130 | for (i = height; i; i--) { | ||
131 | src32 = (u32 *)src; | ||
132 | dst32 = (u32 *)dst; | ||
133 | |||
134 | if (f & 1) { | ||
135 | pval[0] = (*src32++ << 8) & mask; | ||
136 | pval[1] = (*src32++ << 8) & mask; | ||
137 | pval[2] = (*src32++ << 8) & mask; | ||
138 | pval[3] = (*src32++ << 8) & mask; | ||
139 | } else { | ||
140 | pval[0] = dst32[0] & mask; | ||
141 | pval[1] = dst32[1] & mask; | ||
142 | pval[2] = dst32[2] & mask; | ||
143 | pval[3] = dst32[3] & mask; | ||
144 | } | ||
145 | |||
146 | for (j = w; j > 0; j--) { | ||
147 | v = *src32++; | ||
148 | v1 = v & mask; | ||
149 | *dst32++ = pval[0] | (v1 >> 8); | ||
150 | pval[0] = (v ^ v1) << 8; | ||
151 | v = *src32++; | ||
152 | v1 = v & mask; | ||
153 | *dst32++ = pval[1] | (v1 >> 8); | ||
154 | pval[1] = (v ^ v1) << 8; | ||
155 | v = *src32++; | ||
156 | v1 = v & mask; | ||
157 | *dst32++ = pval[2] | (v1 >> 8); | ||
158 | pval[2] = (v ^ v1) << 8; | ||
159 | v = *src32++; | ||
160 | v1 = v & mask; | ||
161 | *dst32++ = pval[3] | (v1 >> 8); | ||
162 | pval[3] = (v ^ v1) << 8; | ||
163 | } | ||
164 | |||
165 | if (f & 2) { | ||
166 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
167 | dst32[1] = (dst32[1] & mask) | pval[1]; | ||
168 | dst32[2] = (dst32[2] & mask) | pval[2]; | ||
169 | dst32[3] = (dst32[3] & mask) | pval[3]; | ||
170 | } | ||
171 | |||
172 | src += next_line; | ||
173 | dst += next_line; | ||
174 | } | ||
175 | } else { | ||
176 | u32 *src32, *dst32; | ||
177 | u32 pval[4], v, v1, mask; | ||
178 | int i, j, w, f; | ||
179 | |||
180 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
181 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
182 | |||
183 | mask = 0xff00ff; | ||
184 | f = 0; | ||
185 | w = width; | ||
186 | if ((dx + width) & 15) | ||
187 | f = 1; | ||
188 | if (sx & 15) { | ||
189 | f |= 2; | ||
190 | w += 8; | ||
191 | } | ||
192 | w >>= 4; | ||
193 | for (i = height; i; i--) { | ||
194 | src32 = (u32 *)src; | ||
195 | dst32 = (u32 *)dst; | ||
196 | |||
197 | if (f & 1) { | ||
198 | pval[0] = dst32[-1] & mask; | ||
199 | pval[1] = dst32[-2] & mask; | ||
200 | pval[2] = dst32[-3] & mask; | ||
201 | pval[3] = dst32[-4] & mask; | ||
202 | } else { | ||
203 | pval[0] = (*--src32 >> 8) & mask; | ||
204 | pval[1] = (*--src32 >> 8) & mask; | ||
205 | pval[2] = (*--src32 >> 8) & mask; | ||
206 | pval[3] = (*--src32 >> 8) & mask; | ||
207 | } | ||
208 | |||
209 | for (j = w; j > 0; j--) { | ||
210 | v = *--src32; | ||
211 | v1 = v & mask; | ||
212 | *--dst32 = pval[0] | (v1 << 8); | ||
213 | pval[0] = (v ^ v1) >> 8; | ||
214 | v = *--src32; | ||
215 | v1 = v & mask; | ||
216 | *--dst32 = pval[1] | (v1 << 8); | ||
217 | pval[1] = (v ^ v1) >> 8; | ||
218 | v = *--src32; | ||
219 | v1 = v & mask; | ||
220 | *--dst32 = pval[2] | (v1 << 8); | ||
221 | pval[2] = (v ^ v1) >> 8; | ||
222 | v = *--src32; | ||
223 | v1 = v & mask; | ||
224 | *--dst32 = pval[3] | (v1 << 8); | ||
225 | pval[3] = (v ^ v1) >> 8; | ||
226 | } | ||
227 | |||
228 | if (!(f & 2)) { | ||
229 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
230 | dst32[-2] = (dst32[-2] & mask) | pval[1]; | ||
231 | dst32[-3] = (dst32[-3] & mask) | pval[2]; | ||
232 | dst32[-4] = (dst32[-4] & mask) | pval[3]; | ||
233 | } | ||
234 | |||
235 | src -= next_line; | ||
236 | dst -= next_line; | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
243 | int sy, int sx, int height, int width) | ||
244 | { | ||
245 | u32 *dest; | ||
246 | int rows, i; | ||
247 | u32 cval[4]; | ||
248 | |||
249 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
250 | if (sx & 15) { | ||
251 | u8 *dest8 = (u8 *)dest + 1; | ||
252 | |||
253 | expand8_col2mask(color, cval); | ||
254 | |||
255 | for (i = height; i; i--) { | ||
256 | fill8_col(dest8, cval); | ||
257 | dest8 += next_line; | ||
258 | } | ||
259 | dest += BPL / 2; | ||
260 | width -= 8; | ||
261 | } | ||
262 | |||
263 | expand16_col2mask(color, cval); | ||
264 | rows = width >> 4; | ||
265 | if (rows) { | ||
266 | u32 *d = dest; | ||
267 | u32 off = next_line - rows * BPL * 2; | ||
268 | for (i = height; i; i--) { | ||
269 | d = fill16_col(d, rows, cval); | ||
270 | d = (u32 *)((long)d + off); | ||
271 | } | ||
272 | dest += rows * BPL / 2; | ||
273 | width &= 15; | ||
274 | } | ||
275 | |||
276 | if (width) { | ||
277 | u8 *dest8 = (u8 *)dest; | ||
278 | |||
279 | expand8_col2mask(color, cval); | ||
280 | |||
281 | for (i = height; i; i--) { | ||
282 | fill8_col(dest8, cval); | ||
283 | dest8 += next_line; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, | ||
289 | int dy, int dx, u32 width, | ||
290 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
291 | { | ||
292 | u32 *dest; | ||
293 | const u16 *data16; | ||
294 | int rows; | ||
295 | u32 fgm[4], bgm[4], m; | ||
296 | |||
297 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
298 | if (dx & 15) { | ||
299 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
300 | dest += BPL / 2; | ||
301 | width -= 8; | ||
302 | } | ||
303 | |||
304 | if (width >= 16) { | ||
305 | data16 = (const u16 *)data; | ||
306 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
307 | |||
308 | for (rows = width / 16; rows; rows--) { | ||
309 | u16 d = *data16++; | ||
310 | m = d | ((u32)d << 16); | ||
311 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
312 | *dest++ = (m & fgm[1]) ^ bgm[1]; | ||
313 | *dest++ = (m & fgm[2]) ^ bgm[2]; | ||
314 | *dest++ = (m & fgm[3]) ^ bgm[3]; | ||
315 | } | ||
316 | |||
317 | data = (const u8 *)data16; | ||
318 | width &= 15; | ||
319 | } | ||
320 | |||
321 | if (width) | ||
322 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
323 | } | ||
324 | |||
325 | #ifdef MODULE | ||
326 | MODULE_LICENSE("GPL"); | ||
327 | |||
328 | int init_module(void) | ||
329 | { | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | void cleanup_module(void) | ||
334 | { | ||
335 | } | ||
336 | #endif /* MODULE */ | ||
337 | |||
338 | |||
339 | /* | ||
340 | * Visible symbols for modules | ||
341 | */ | ||
342 | |||
343 | EXPORT_SYMBOL(atafb_iplan2p8_copyarea); | ||
344 | EXPORT_SYMBOL(atafb_iplan2p8_fillrect); | ||
345 | EXPORT_SYMBOL(atafb_iplan2p8_linefill); | ||
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c new file mode 100644 index 000000000000..6a352d62eecf --- /dev/null +++ b/drivers/video/atafb_mfb.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mfb.c -- Low level frame buffer operations for | ||
3 | * monochrome | ||
4 | * | ||
5 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file COPYING in the main directory of this archive for | ||
9 | * more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/fb.h> | ||
15 | |||
16 | #include "atafb.h" | ||
17 | #include "atafb_utils.h" | ||
18 | |||
19 | |||
20 | /* | ||
21 | * Monochrome | ||
22 | */ | ||
23 | |||
24 | void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | u8 *src, *dest; | ||
29 | u_int rows; | ||
30 | |||
31 | if (sx == 0 && dx == 0 && width == next_line) { | ||
32 | src = (u8 *)info->screen_base + sy * (width >> 3); | ||
33 | dest = (u8 *)info->screen_base + dy * (width >> 3); | ||
34 | fb_memmove(dest, src, height * (width >> 3)); | ||
35 | } else if (dy <= sy) { | ||
36 | src = (u8 *)info->screen_base + sy * next_line + (sx >> 3); | ||
37 | dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); | ||
38 | for (rows = height; rows--;) { | ||
39 | fb_memmove(dest, src, width >> 3); | ||
40 | src += next_line; | ||
41 | dest += next_line; | ||
42 | } | ||
43 | } else { | ||
44 | src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3); | ||
45 | dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3); | ||
46 | for (rows = height; rows--;) { | ||
47 | fb_memmove(dest, src, width >> 3); | ||
48 | src -= next_line; | ||
49 | dest -= next_line; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
55 | int sy, int sx, int height, int width) | ||
56 | { | ||
57 | u8 *dest; | ||
58 | u_int rows; | ||
59 | |||
60 | dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3); | ||
61 | |||
62 | if (sx == 0 && width == next_line) { | ||
63 | if (color) | ||
64 | fb_memset255(dest, height * (width >> 3)); | ||
65 | else | ||
66 | fb_memclear(dest, height * (width >> 3)); | ||
67 | } else { | ||
68 | for (rows = height; rows--; dest += next_line) { | ||
69 | if (color) | ||
70 | fb_memset255(dest, width >> 3); | ||
71 | else | ||
72 | fb_memclear_small(dest, width >> 3); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void atafb_mfb_linefill(struct fb_info *info, u_long next_line, | ||
78 | int dy, int dx, u32 width, | ||
79 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
80 | { | ||
81 | u8 *dest; | ||
82 | u_int rows; | ||
83 | |||
84 | dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); | ||
85 | |||
86 | for (rows = width / 8; rows--; /* check margins */ ) { | ||
87 | // use fast_memmove or fb_memmove | ||
88 | *dest++ = *data++; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #ifdef MODULE | ||
93 | MODULE_LICENSE("GPL"); | ||
94 | |||
95 | int init_module(void) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void cleanup_module(void) | ||
101 | { | ||
102 | } | ||
103 | #endif /* MODULE */ | ||
104 | |||
105 | |||
106 | /* | ||
107 | * Visible symbols for modules | ||
108 | */ | ||
109 | |||
110 | EXPORT_SYMBOL(atafb_mfb_copyarea); | ||
111 | EXPORT_SYMBOL(atafb_mfb_fillrect); | ||
112 | EXPORT_SYMBOL(atafb_mfb_linefill); | ||
diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h new file mode 100644 index 000000000000..ac9e19dc5057 --- /dev/null +++ b/drivers/video/atafb_utils.h | |||
@@ -0,0 +1,400 @@ | |||
1 | #ifndef _VIDEO_ATAFB_UTILS_H | ||
2 | #define _VIDEO_ATAFB_UTILS_H | ||
3 | |||
4 | /* ================================================================= */ | ||
5 | /* Utility Assembler Functions */ | ||
6 | /* ================================================================= */ | ||
7 | |||
8 | /* ====================================================================== */ | ||
9 | |||
10 | /* Those of a delicate disposition might like to skip the next couple of | ||
11 | * pages. | ||
12 | * | ||
13 | * These functions are drop in replacements for memmove and | ||
14 | * memset(_, 0, _). However their five instances add at least a kilobyte | ||
15 | * to the object file. You have been warned. | ||
16 | * | ||
17 | * Not a great fan of assembler for the sake of it, but I think | ||
18 | * that these routines are at least 10 times faster than their C | ||
19 | * equivalents for large blits, and that's important to the lowest level of | ||
20 | * a graphics driver. Question is whether some scheme with the blitter | ||
21 | * would be faster. I suspect not for simple text system - not much | ||
22 | * asynchrony. | ||
23 | * | ||
24 | * Code is very simple, just gruesome expansion. Basic strategy is to | ||
25 | * increase data moved/cleared at each step to 16 bytes to reduce | ||
26 | * instruction per data move overhead. movem might be faster still | ||
27 | * For more than 15 bytes, we try to align the write direction on a | ||
28 | * longword boundary to get maximum speed. This is even more gruesome. | ||
29 | * Unaligned read/write used requires 68020+ - think this is a problem? | ||
30 | * | ||
31 | * Sorry! | ||
32 | */ | ||
33 | |||
34 | |||
35 | /* ++roman: I've optimized Robert's original versions in some minor | ||
36 | * aspects, e.g. moveq instead of movel, let gcc choose the registers, | ||
37 | * use movem in some places... | ||
38 | * For other modes than 1 plane, lots of more such assembler functions | ||
39 | * were needed (e.g. the ones using movep or expanding color values). | ||
40 | */ | ||
41 | |||
42 | /* ++andreas: more optimizations: | ||
43 | subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc | ||
44 | addal is faster than addaw | ||
45 | movep is rather expensive compared to ordinary move's | ||
46 | some functions rewritten in C for clarity, no speed loss */ | ||
47 | |||
48 | static inline void *fb_memclear_small(void *s, size_t count) | ||
49 | { | ||
50 | if (!count) | ||
51 | return 0; | ||
52 | |||
53 | asm volatile ("\n" | ||
54 | " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" | ||
55 | "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" | ||
56 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" | ||
57 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" | ||
58 | "1:" | ||
59 | : "=a" (s), "=d" (count) | ||
60 | : "d" (0), "0" ((char *)s + count), "1" (count)); | ||
61 | asm volatile ("\n" | ||
62 | " subq.l #1,%1\n" | ||
63 | " jcs 3f\n" | ||
64 | " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" | ||
65 | "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" | ||
66 | " dbra %1,2b\n" | ||
67 | "3:" | ||
68 | : "=a" (s), "=d" (count) | ||
69 | : "d" (0), "0" (s), "1" (count) | ||
70 | : "d4", "d5", "d6" | ||
71 | ); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | |||
77 | static inline void *fb_memclear(void *s, size_t count) | ||
78 | { | ||
79 | if (!count) | ||
80 | return 0; | ||
81 | |||
82 | if (count < 16) { | ||
83 | asm volatile ("\n" | ||
84 | " lsr.l #1,%1 ; jcc 1f ; clr.b (%0)+\n" | ||
85 | "1: lsr.l #1,%1 ; jcc 1f ; clr.w (%0)+\n" | ||
86 | "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+\n" | ||
87 | "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
88 | "1:" | ||
89 | : "=a" (s), "=d" (count) | ||
90 | : "0" (s), "1" (count)); | ||
91 | } else { | ||
92 | long tmp; | ||
93 | asm volatile ("\n" | ||
94 | " move.l %1,%2\n" | ||
95 | " lsr.l #1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n" | ||
96 | " lsr.l #1,%2 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
97 | " clr.w (%0)+ ; subq.w #2,%1 ; jra 2f\n" | ||
98 | "1: lsr.l #1,%2 ; jcc 2f\n" | ||
99 | " clr.w (%0)+ ; subq.w #2,%1\n" | ||
100 | "2: move.w %1,%2; lsr.l #2,%1 ; jeq 6f\n" | ||
101 | " lsr.l #1,%1 ; jcc 3f ; clr.l (%0)+\n" | ||
102 | "3: lsr.l #1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
103 | "4: subq.l #1,%1 ; jcs 6f\n" | ||
104 | "5: clr.l (%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
105 | " dbra %1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n" | ||
106 | "6: move.w %2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n" | ||
107 | "7: btst #0,%1 ; jeq 8f ; clr.b (%0)+\n" | ||
108 | "8:" | ||
109 | : "=a" (s), "=d" (count), "=d" (tmp) | ||
110 | : "0" (s), "1" (count)); | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | |||
117 | static inline void *fb_memset255(void *s, size_t count) | ||
118 | { | ||
119 | if (!count) | ||
120 | return 0; | ||
121 | |||
122 | asm volatile ("\n" | ||
123 | " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" | ||
124 | "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" | ||
125 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" | ||
126 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" | ||
127 | "1:" | ||
128 | : "=a" (s), "=d" (count) | ||
129 | : "d" (-1), "0" ((char *)s+count), "1" (count)); | ||
130 | asm volatile ("\n" | ||
131 | " subq.l #1,%1 ; jcs 3f\n" | ||
132 | " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" | ||
133 | "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" | ||
134 | " dbra %1,2b\n" | ||
135 | "3:" | ||
136 | : "=a" (s), "=d" (count) | ||
137 | : "d" (-1), "0" (s), "1" (count) | ||
138 | : "d4", "d5", "d6"); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | |||
144 | static inline void *fb_memmove(void *d, const void *s, size_t count) | ||
145 | { | ||
146 | if (d < s) { | ||
147 | if (count < 16) { | ||
148 | asm volatile ("\n" | ||
149 | " lsr.l #1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n" | ||
150 | "1: lsr.l #1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n" | ||
151 | "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n" | ||
152 | "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" | ||
153 | "1:" | ||
154 | : "=a" (d), "=a" (s), "=d" (count) | ||
155 | : "0" (d), "1" (s), "2" (count)); | ||
156 | } else { | ||
157 | long tmp; | ||
158 | asm volatile ("\n" | ||
159 | " move.l %0,%3\n" | ||
160 | " lsr.l #1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n" | ||
161 | " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
162 | " move.w (%1)+,(%0)+ ; subqw #2,%2 ; jra 2f\n" | ||
163 | "1: lsr.l #1,%3 ; jcc 2f\n" | ||
164 | " move.w (%1)+,(%0)+ ; subqw #2,%2\n" | ||
165 | "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" | ||
166 | " lsr.l #1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n" | ||
167 | "3: lsr.l #1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" | ||
168 | "4: subq.l #1,%2 ; jcs 6f\n" | ||
169 | "5: move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" | ||
170 | " move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" | ||
171 | " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" | ||
172 | "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n" | ||
173 | "7: btst #0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n" | ||
174 | "8:" | ||
175 | : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) | ||
176 | : "0" (d), "1" (s), "2" (count)); | ||
177 | } | ||
178 | } else { | ||
179 | if (count < 16) { | ||
180 | asm volatile ("\n" | ||
181 | " lsr.l #1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n" | ||
182 | "1: lsr.l #1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n" | ||
183 | "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n" | ||
184 | "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" | ||
185 | "1:" | ||
186 | : "=a" (d), "=a" (s), "=d" (count) | ||
187 | : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); | ||
188 | } else { | ||
189 | long tmp; | ||
190 | |||
191 | asm volatile ("\n" | ||
192 | " move.l %0,%3\n" | ||
193 | " lsr.l #1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n" | ||
194 | " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
195 | " move.w -(%1),-(%0) ; subqw #2,%2 ; jra 2f\n" | ||
196 | "1: lsr.l #1,%3 ; jcc 2f\n" | ||
197 | " move.w -(%1),-(%0) ; subqw #2,%2\n" | ||
198 | "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" | ||
199 | " lsr.l #1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n" | ||
200 | "3: lsr.l #1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" | ||
201 | "4: subq.l #1,%2 ; jcs 6f\n" | ||
202 | "5: move.l -(%1),-(%0); move.l -(%1),-(%0)\n" | ||
203 | " move.l -(%1),-(%0); move.l -(%1),-(%0)\n" | ||
204 | " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" | ||
205 | "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n" | ||
206 | "7: btst #0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n" | ||
207 | "8:" | ||
208 | : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) | ||
209 | : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | |||
217 | /* ++andreas: Simple and fast version of memmove, assumes size is | ||
218 | divisible by 16, suitable for moving the whole screen bitplane */ | ||
219 | static inline void fast_memmove(char *dst, const char *src, size_t size) | ||
220 | { | ||
221 | if (!size) | ||
222 | return; | ||
223 | if (dst < src) | ||
224 | asm volatile ("\n" | ||
225 | "1: movem.l (%0)+,%%d0/%%d1/%%a0/%%a1\n" | ||
226 | " movem.l %%d0/%%d1/%%a0/%%a1,%1@\n" | ||
227 | " addq.l #8,%1; addq.l #8,%1\n" | ||
228 | " dbra %2,1b\n" | ||
229 | " clr.w %2; subq.l #1,%2\n" | ||
230 | " jcc 1b" | ||
231 | : "=a" (src), "=a" (dst), "=d" (size) | ||
232 | : "0" (src), "1" (dst), "2" (size / 16 - 1) | ||
233 | : "d0", "d1", "a0", "a1", "memory"); | ||
234 | else | ||
235 | asm volatile ("\n" | ||
236 | "1: subq.l #8,%0; subq.l #8,%0\n" | ||
237 | " movem.l %0@,%%d0/%%d1/%%a0/%%a1\n" | ||
238 | " movem.l %%d0/%%d1/%%a0/%%a1,-(%1)\n" | ||
239 | " dbra %2,1b\n" | ||
240 | " clr.w %2; subq.l #1,%2\n" | ||
241 | " jcc 1b" | ||
242 | : "=a" (src), "=a" (dst), "=d" (size) | ||
243 | : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1) | ||
244 | : "d0", "d1", "a0", "a1", "memory"); | ||
245 | } | ||
246 | |||
247 | #ifdef BPL | ||
248 | |||
249 | /* | ||
250 | * This expands a up to 8 bit color into two longs | ||
251 | * for movel operations. | ||
252 | */ | ||
253 | static const u32 four2long[] = { | ||
254 | 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, | ||
255 | 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, | ||
256 | 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, | ||
257 | 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff, | ||
258 | }; | ||
259 | |||
260 | static inline void expand8_col2mask(u8 c, u32 m[]) | ||
261 | { | ||
262 | m[0] = four2long[c & 15]; | ||
263 | #if BPL > 4 | ||
264 | m[1] = four2long[c >> 4]; | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) | ||
269 | { | ||
270 | fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]); | ||
271 | #if BPL > 4 | ||
272 | fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]); | ||
273 | #endif | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * set an 8bit value to a color | ||
278 | */ | ||
279 | static inline void fill8_col(u8 *dst, u32 m[]) | ||
280 | { | ||
281 | u32 tmp = m[0]; | ||
282 | dst[0] = tmp; | ||
283 | dst[2] = (tmp >>= 8); | ||
284 | #if BPL > 2 | ||
285 | dst[4] = (tmp >>= 8); | ||
286 | dst[6] = tmp >> 8; | ||
287 | #endif | ||
288 | #if BPL > 4 | ||
289 | tmp = m[1]; | ||
290 | dst[8] = tmp; | ||
291 | dst[10] = (tmp >>= 8); | ||
292 | dst[12] = (tmp >>= 8); | ||
293 | dst[14] = tmp >> 8; | ||
294 | #endif | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * set an 8bit value according to foreground/background color | ||
299 | */ | ||
300 | static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask) | ||
301 | { | ||
302 | u32 fgm[2], bgm[2], tmp; | ||
303 | |||
304 | expand8_2col2mask(fg, bg, fgm, bgm); | ||
305 | |||
306 | mask |= mask << 8; | ||
307 | #if BPL > 2 | ||
308 | mask |= mask << 16; | ||
309 | #endif | ||
310 | tmp = (mask & fgm[0]) ^ bgm[0]; | ||
311 | dst[0] = tmp; | ||
312 | dst[2] = (tmp >>= 8); | ||
313 | #if BPL > 2 | ||
314 | dst[4] = (tmp >>= 8); | ||
315 | dst[6] = tmp >> 8; | ||
316 | #endif | ||
317 | #if BPL > 4 | ||
318 | tmp = (mask & fgm[1]) ^ bgm[1]; | ||
319 | dst[8] = tmp; | ||
320 | dst[10] = (tmp >>= 8); | ||
321 | dst[12] = (tmp >>= 8); | ||
322 | dst[14] = tmp >> 8; | ||
323 | #endif | ||
324 | } | ||
325 | |||
326 | static const u32 two2word[] = { | ||
327 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff | ||
328 | }; | ||
329 | |||
330 | static inline void expand16_col2mask(u8 c, u32 m[]) | ||
331 | { | ||
332 | m[0] = two2word[c & 3]; | ||
333 | #if BPL > 2 | ||
334 | m[1] = two2word[(c >> 2) & 3]; | ||
335 | #endif | ||
336 | #if BPL > 4 | ||
337 | m[2] = two2word[(c >> 4) & 3]; | ||
338 | m[3] = two2word[c >> 6]; | ||
339 | #endif | ||
340 | } | ||
341 | |||
342 | static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) | ||
343 | { | ||
344 | bgm[0] = two2word[bg & 3]; | ||
345 | fgm[0] = two2word[fg & 3] ^ bgm[0]; | ||
346 | #if BPL > 2 | ||
347 | bgm[1] = two2word[(bg >> 2) & 3]; | ||
348 | fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1]; | ||
349 | #endif | ||
350 | #if BPL > 4 | ||
351 | bgm[2] = two2word[(bg >> 4) & 3]; | ||
352 | fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2]; | ||
353 | bgm[3] = two2word[bg >> 6]; | ||
354 | fgm[3] = two2word[fg >> 6] ^ bgm[3]; | ||
355 | #endif | ||
356 | } | ||
357 | |||
358 | static inline u32 *fill16_col(u32 *dst, int rows, u32 m[]) | ||
359 | { | ||
360 | while (rows) { | ||
361 | *dst++ = m[0]; | ||
362 | #if BPL > 2 | ||
363 | *dst++ = m[1]; | ||
364 | #endif | ||
365 | #if BPL > 4 | ||
366 | *dst++ = m[2]; | ||
367 | *dst++ = m[3]; | ||
368 | #endif | ||
369 | rows--; | ||
370 | } | ||
371 | return dst; | ||
372 | } | ||
373 | |||
374 | static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes) | ||
375 | { | ||
376 | u32 *s, *d, v; | ||
377 | |||
378 | s = src; | ||
379 | d = dst; | ||
380 | do { | ||
381 | v = (*s++ & mask) | (*d & ~mask); | ||
382 | *d++ = v; | ||
383 | #if BPL > 2 | ||
384 | v = (*s++ & mask) | (*d & ~mask); | ||
385 | *d++ = v; | ||
386 | #endif | ||
387 | #if BPL > 4 | ||
388 | v = (*s++ & mask) | (*d & ~mask); | ||
389 | *d++ = v; | ||
390 | v = (*s++ & mask) | (*d & ~mask); | ||
391 | *d++ = v; | ||
392 | #endif | ||
393 | d = (u32 *)((u8 *)d + bytes); | ||
394 | s = (u32 *)((u8 *)s + bytes); | ||
395 | } while (--h); | ||
396 | } | ||
397 | |||
398 | #endif | ||
399 | |||
400 | #endif /* _VIDEO_ATAFB_UTILS_H */ | ||