aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig5
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/atafb.c2801
-rw-r--r--drivers/video/atafb.h36
-rw-r--r--drivers/video/atafb_iplan2p2.c293
-rw-r--r--drivers/video/atafb_iplan2p4.c308
-rw-r--r--drivers/video/atafb_iplan2p8.c345
-rw-r--r--drivers/video/atafb_mfb.c112
-rw-r--r--drivers/video/atafb_utils.h400
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
390config FB_ATARI 390config 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
63obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o 63obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
64obj-$(CONFIG_FB_SGIVW) += sgivwfb.o 64obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
65obj-$(CONFIG_FB_ACORN) += acornfb.o 65obj-$(CONFIG_FB_ACORN) += acornfb.o
66obj-$(CONFIG_FB_ATARI) += atafb.o 66obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \
67 atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
67obj-$(CONFIG_FB_MAC) += macfb.o 68obj-$(CONFIG_FB_MAC) += macfb.o
68obj-$(CONFIG_FB_HGA) += hgafb.o 69obj-$(CONFIG_FB_HGA) += hgafb.o
69obj-$(CONFIG_FB_IGA) += igafb.o 70obj-$(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
88static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
89static int atafb_set_par(struct fb_info *info);
90static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
91 unsigned int blue, unsigned int transp,
92 struct fb_info *info);
93static int atafb_blank(int blank, struct fb_info *info);
94static int atafb_pan_display(struct fb_var_screeninfo *var,
95 struct fb_info *info);
96static void atafb_fillrect(struct fb_info *info,
97 const struct fb_fillrect *rect);
98static void atafb_copyarea(struct fb_info *info,
99 const struct fb_copyarea *region);
100static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
101static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
102 unsigned long arg);
103
90 104
91static int default_par=0; /* default resolution (0=none) */ 105static int default_par; /* default resolution (0=none) */
92 106
93static unsigned long default_mem_req=0; 107static unsigned long default_mem_req;
94 108
95static int hwscroll=-1; 109static int hwscroll = -1;
96 110
97static int use_hwscroll = 1; 111static int use_hwscroll = 1;
98 112
99static int sttt_xres=640,st_yres=400,tt_yres=480; 113static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
100static int sttt_xres_virtual=640,sttt_yres_virtual=400; 114static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
101static int ovsc_offset=0, ovsc_addlen=0; 115static int ovsc_offset, ovsc_addlen;
116
117 /*
118 * Hardware parameters for current mode
119 */
102 120
103static struct atafb_par { 121static 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) */
141static int DontCalcRes = 0; 161static 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
166static struct fb_info fb_info; 186static struct fb_info fb_info = {
187 .fix = {
188 .id = "Atari ",
189 .visual = FB_VISUAL_PSEUDOCOLOR,
190 .accel = FB_ACCEL_NONE,
191 }
192};
167 193
168static void *screen_base; /* base address of screen */ 194static void *screen_base; /* base address of screen */
169static void *real_screen_base; /* (only for Overscan) */ 195static void *real_screen_base; /* (only for Overscan) */
170 196
171static int screen_len; 197static int screen_len;
172 198
173static int current_par_valid=0; 199static int current_par_valid;
174 200
175static int mono_moni=0; 201static int mono_moni;
176
177static struct display disp;
178 202
179 203
180#ifdef ATAFB_EXT 204#ifdef ATAFB_EXT
181/* external video handling */
182 205
183static unsigned external_xres; 206/* external video handling */
184static unsigned external_xres_virtual; 207static unsigned int external_xres;
185static unsigned external_yres; 208static unsigned int external_xres_virtual;
186/* not needed - atafb will never support panning/hardwarescroll with external 209static unsigned int external_yres;
187 * static unsigned external_yres_virtual;
188*/
189 210
190static unsigned external_depth; 211/*
191static int external_pmode; 212 * not needed - atafb will never support panning/hardwarescroll with external
192static void *external_addr = 0; 213 * static unsigned int external_yres_virtual;
193static unsigned long external_len; 214 */
194static unsigned long external_vgaiobase = 0; 215static unsigned int external_depth;
195static unsigned int external_bitspercol = 6; 216static int external_pmode;
196 217static void *external_addr;
197/* 218static unsigned long external_len;
198JOE <joe@amber.dinoco.de>: 219static unsigned long external_vgaiobase;
199added card type for external driver, is only needed for 220static unsigned int external_bitspercol = 6;
200colormap 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 */
203enum cardtype { IS_VGA, IS_MV300 }; 227enum cardtype { IS_VGA, IS_MV300 };
204static enum cardtype external_card_type = IS_VGA; 228static enum cardtype external_card_type = IS_VGA;
205 229
206/* 230/*
207The 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
208indices in order to access the correct reg. 232 * indices in order to access the correct reg.
209*/ 233 */
210static int MV300_reg_1bit[2]={0,1}; 234static int MV300_reg_1bit[2] = {
211static int MV300_reg_4bit[16]={ 235 0, 1
2120, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; 236};
213static int MV300_reg_8bit[256]={ 237static int MV300_reg_4bit[16] = {
2140, 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
2158, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 239};
2164, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 240static int MV300_reg_8bit[256] = {
21712, 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,
2182, 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,
21910, 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,
2206, 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,
22114, 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,
2221, 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,
2239, 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,
2245, 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,
22513, 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,
2263, 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,
22711, 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,
2287, 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,
22915, 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
231static int *MV300_reg = MV300_reg_8bit; 259static int *MV300_reg = MV300_reg_8bit;
232
233/*
234And on the MV300 it's difficult to read out the hardware palette. So we
235just keep track of the set colors in our own array here, and use that!
236*/
237
238static struct { unsigned char red,green,blue,pad; } ext_color[256];
239#endif /* ATAFB_EXT */ 260#endif /* ATAFB_EXT */
240 261
241 262
242static int inverse=0; 263static int inverse;
243 264
244extern int fontheight_8x8; 265extern int fontheight_8x8;
245extern int fontwidth_8x8; 266extern int fontwidth_8x8;
@@ -249,96 +270,154 @@ extern int fontheight_8x16;
249extern int fontwidth_8x16; 270extern int fontwidth_8x16;
250extern unsigned char fontdata_8x16[]; 271extern 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
304static struct fb_hwswitch { 390static 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
323static char *autodetect_names[] = {"autodetect", NULL}; 406static char *autodetect_names[] = { "autodetect", NULL };
324static char *stlow_names[] = {"stlow", NULL}; 407static char *stlow_names[] = { "stlow", NULL };
325static char *stmid_names[] = {"stmid", "default5", NULL}; 408static char *stmid_names[] = { "stmid", "default5", NULL };
326static char *sthigh_names[] = {"sthigh", "default4", NULL}; 409static char *sthigh_names[] = { "sthigh", "default4", NULL };
327static char *ttlow_names[] = {"ttlow", NULL}; 410static char *ttlow_names[] = { "ttlow", NULL };
328static char *ttmid_names[]= {"ttmid", "default1", NULL}; 411static char *ttmid_names[] = { "ttmid", "default1", NULL };
329static char *tthigh_names[]= {"tthigh", "default2", NULL}; 412static char *tthigh_names[] = { "tthigh", "default2", NULL };
330static char *vga2_names[] = {"vga2", NULL}; 413static char *vga2_names[] = { "vga2", NULL };
331static char *vga4_names[] = {"vga4", NULL}; 414static char *vga4_names[] = { "vga4", NULL };
332static char *vga16_names[] = {"vga16", "default3", NULL}; 415static char *vga16_names[] = { "vga16", "default3", NULL };
333static char *vga256_names[] = {"vga256", NULL}; 416static char *vga256_names[] = { "vga256", NULL };
334static char *falh2_names[] = {"falh2", NULL}; 417static char *falh2_names[] = { "falh2", NULL };
335static char *falh16_names[] = {"falh16", NULL}; 418static char *falh16_names[] = { "falh16", NULL };
336 419
337static char **fb_var_names[] = { 420static 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
359static struct fb_var_screeninfo atafb_predefined[] = { 437static 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
417static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); 495static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
418 496
497static 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
420static int 504 /*
421get_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
561static 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
571static 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
446static int tt_encode_fix( struct fb_fix_screeninfo *fix, 597static 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 622static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
474static 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
555static int tt_encode_var( struct fb_var_screeninfo *var, 697static 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 791static void tt_get_par(struct atafb_par *par)
651static 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
662static void tt_set_par( struct atafb_par *par ) 802static 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 811static int tt_setcolreg(unsigned int regno, unsigned int red,
672static 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
700static 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 827static int tt_detect(void)
717static 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 = {
762f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25}, 872 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
763f32 = {32000000, 31250, 18, 0, 42, 0x0, 0}, 873}, f32 = {
764fext = { 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] */
767static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}}; 880static 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 */
770static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000}; 885static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
771 886
772#ifdef FBCON_HAS_CFB16 887#ifdef FBCON_HAS_CFB16
773static u16 fbcon_cfb16_cmap[16]; 888static u16 fbcon_cfb16_cmap[16];
@@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16];
775 890
776static inline int hxx_prescale(struct falcon_hw *hw) 891static 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
782static int falcon_encode_fix( struct fb_fix_screeninfo *fix, 897static 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 926static int falcon_decode_var(struct fb_var_screeninfo *var,
813static 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: 1209again:
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: 1385set_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
1295static int falcon_encode_var( struct fb_var_screeninfo *var, 1409static 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 1571static int f_change_mode;
1459static int f_change_mode = 0;
1460static struct falcon_hw f_new_mode; 1572static struct falcon_hw f_new_mode;
1461static int f_pan_display = 0; 1573static int f_pan_display;
1462 1574
1463static void falcon_get_par( struct atafb_par *par ) 1575static 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
1500static void falcon_set_par( struct atafb_par *par ) 1612static 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 1634static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1523static 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 1692static int falcon_pan_display(struct fb_var_screeninfo *var,
1584static 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 1724static int falcon_setcolreg(unsigned int regno, unsigned int red,
1615static 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
1635static 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 1747static int falcon_blank(int blank_mode)
1659static 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 1785static int falcon_detect(void)
1698static 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
1743static int stste_encode_fix( struct fb_fix_screeninfo *fix, 1830static 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 1860static int stste_decode_var(struct fb_var_screeninfo *var,
1775static 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
1833static int stste_encode_var( struct fb_var_screeninfo *var, 1916static 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 1992static void stste_get_par(struct atafb_par *par)
1911static 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
1923static void stste_set_par( struct atafb_par *par ) 2004static 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 2013static int stste_setcolreg(unsigned int regno, unsigned int red,
1933static 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
1969static 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 2035static int stste_detect(void)
1992static 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 )
2014static void stste_set_screen_base(void *s_base) 2057static 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!) */
2046static void st_ovsc_switch(void) 2089static 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
2088static int ext_encode_fix( struct fb_fix_screeninfo *fix, 2131static 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 2176static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2138static 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 2190static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2154static 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 2230static void ext_get_par(struct atafb_par *par)
2196static 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
2201static void ext_set_par( struct atafb_par *par ) 2235static 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
2215static int ext_getcolreg( unsigned regno, unsigned *red, 2249static 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);
2229static 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
2266static int ext_detect( void )
2267 2280
2281static 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 )
2284static void set_screen_base(void *s_base) 2298static 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 2309static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2295static 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
2314static struct fb_hwswitch tt_switch = { 2327static 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
2322static struct fb_hwswitch falcon_switch = { 2340static 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
2330static struct fb_hwswitch st_switch = { 2354static 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
2338static struct fb_hwswitch ext_switch = { 2367static 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 2377static void ata_get_par(struct atafb_par *par)
2345
2346static 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 2385static void ata_set_par(struct atafb_par *par)
2356static 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
2372static int 2399static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2373fb_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
2385static int
2386do_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
2400static int 2415static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2401atafb_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
2415static int 2427static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2416atafb_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
2428static void 2437// No longer called by fbcon!
2429atafb_set_disp(int con, struct fb_info *info) 2438// Still called by set_var internally
2439
2440static 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
2484static 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
2501static int 2494static int
2502atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 2495atafb_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
2533static int 2542
2534atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) 2543static 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
2547static int 2579static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2548atafb_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, &current_par))) 2622
2561 return err; 2623static 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
2571static int 2683static int
@@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2584 if (copy_from_user((void *)&current_par, (void *)arg, 2696 if (copy_from_user((void *)&current_par, (void *)arg,
2585 sizeof(struct atafb_par))) 2697 sizeof(struct atafb_par)))
2586 return -EFAULT; 2698 return -EFAULT;
2587 atafb_set_par(&current_par); 2699 ata_set_par(&current_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 */
2601static int 2713static int atafb_blank(int blank, struct fb_info *info)
2602atafb_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 */
2742static 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 */
2760static 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
2623static struct fb_ops atafb_ops = { 2775static 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
2635static void 2788static void check_default_par(int detected_mode)
2636check_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
2676static int
2677atafb_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
2690int __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
2835static void __init atafb_setup_ext(char *spec) 2829static 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
2944static void __init atafb_setup_int(char *spec) 2946static 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
2984static void __init atafb_setup_mcap(char *spec) 2982static 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
3022static void __init atafb_setup_user(char *spec) 3019static 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
3046int __init atafb_setup( char *options ) 3047int __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
3096int __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(&current_par);
3221 fb_info.par = &current_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
3269module_init(atafb_init);
3270
3099#ifdef MODULE 3271#ifdef MODULE
3100MODULE_LICENSE("GPL"); 3272MODULE_LICENSE("GPL");
3101 3273
3102int init_module(void) 3274int 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
4void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
5 int dx, int height, int width);
6void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
7 int sy, int sx, int height, int width);
8void 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
12void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
13 int dx, int height, int width);
14void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
15 int sy, int sx, int height, int width);
16void 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
20void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
21 int dx, int height, int width);
22void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
23 int sy, int sx, int height, int width);
24void 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
28void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
29 int dx, int height, int width);
30void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
31 int sy, int sx, int height, int width);
32void 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
24void 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
193void 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
239void 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
274MODULE_LICENSE("GPL");
275
276int init_module(void)
277{
278 return 0;
279}
280
281void cleanup_module(void)
282{
283}
284#endif /* MODULE */
285
286
287 /*
288 * Visible symbols for modules
289 */
290
291EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
292EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
293EXPORT_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
24void 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
207void 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
253void 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
289MODULE_LICENSE("GPL");
290
291int init_module(void)
292{
293 return 0;
294}
295
296void cleanup_module(void)
297{
298}
299#endif /* MODULE */
300
301
302 /*
303 * Visible symbols for modules
304 */
305
306EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
307EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
308EXPORT_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
31void 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
242void 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
288void 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
326MODULE_LICENSE("GPL");
327
328int init_module(void)
329{
330 return 0;
331}
332
333void cleanup_module(void)
334{
335}
336#endif /* MODULE */
337
338
339 /*
340 * Visible symbols for modules
341 */
342
343EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
344EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
345EXPORT_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
24void 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
54void 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
77void 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
93MODULE_LICENSE("GPL");
94
95int init_module(void)
96{
97 return 0;
98}
99
100void cleanup_module(void)
101{
102}
103#endif /* MODULE */
104
105
106 /*
107 * Visible symbols for modules
108 */
109
110EXPORT_SYMBOL(atafb_mfb_copyarea);
111EXPORT_SYMBOL(atafb_mfb_fillrect);
112EXPORT_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
48static 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
77static 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
117static 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
144static 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 */
219static 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 */
253static 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
260static 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
268static 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 */
279static 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 */
300static 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
326static const u32 two2word[] = {
327 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
328};
329
330static 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
342static 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
358static 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
374static 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 */