OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [atafb.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
3
 *
4
 *  Copyright (C) 1994 Martin Schaller & Roman Hodek
5
 *
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
8
 * for more details.
9
 *
10
 * History:
11
 *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12
 *                all the device independent stuff
13
 *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14
 *                and wrote the Falcon, ST(E), and External drivers
15
 *                based on the original TT driver.
16
 *   - 07 May 95: Martin: Added colormap operations for the external driver
17
 *   - 21 May 95: Martin: Added support for overscan
18
 *                Andreas: some bug fixes for this
19
 *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20
 *                Programmable Falcon video modes
21
 *                (thanks to Christian Cartus for documentation
22
 *                of VIDEL registers).
23
 *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24
 *                on minor 24...31. "user0" may be set on commandline by
25
 *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26
 *                Video mode switch on Falcon now done at next VBL interrupt
27
 *                to avoid the annoying right shift of the screen.
28
 *   - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29
 *                The external-part is legacy, therefore hardware-specific
30
 *                functions like panning/hardwarescrolling/blanking isn't
31
 *                                supported.
32
 *   - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33
 *                                (var->xoffset was changed even if no set_screen_base avail.)
34
 *       - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35
 *                                we know how to set the colors
36
 *                                ext_*palette: read from ext_colors (former MV300_colors)
37
 *                                                          write to ext_colors and RAMDAC
38
 *
39
 * To do:
40
 *   - For the Falcon it is not possible to set random video modes on
41
 *     SM124 and SC/TV, only the bootup resolution is supported.
42
 *
43
 */
44
 
45
#define ATAFB_TT
46
#define ATAFB_STE
47
#define ATAFB_EXT
48
#define ATAFB_FALCON
49
 
50
#include <linux/module.h>
51
#include <linux/kernel.h>
52
#include <linux/errno.h>
53
#include <linux/string.h>
54
#include <linux/mm.h>
55
#include <linux/slab.h>
56
#include <linux/delay.h>
57
#include <linux/init.h>
58
#include <linux/interrupt.h>
59
 
60
#include <asm/setup.h>
61
#include <linux/uaccess.h>
62
#include <asm/pgtable.h>
63
#include <asm/irq.h>
64
#include <asm/io.h>
65
 
66
#include <asm/atarihw.h>
67
#include <asm/atariints.h>
68
#include <asm/atari_stram.h>
69
 
70
#include <linux/fb.h>
71
#include <asm/atarikb.h>
72
 
73
#include "c2p.h"
74
#include "atafb.h"
75
 
76
#define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
77
#define SWITCH_SND6 0x40
78
#define SWITCH_SND7 0x80
79
#define SWITCH_NONE 0x00
80
 
81
 
82
#define up(x, r) (((x) + (r) - 1) & ~((r)-1))
83
 
84
        /*
85
         * Interface to the world
86
         */
87
 
88
static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
89
static int atafb_set_par(struct fb_info *info);
90
static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
91
                           unsigned int blue, unsigned int transp,
92
                           struct fb_info *info);
93
static int atafb_blank(int blank, struct fb_info *info);
94
static int atafb_pan_display(struct fb_var_screeninfo *var,
95
                             struct fb_info *info);
96
static void atafb_fillrect(struct fb_info *info,
97
                           const struct fb_fillrect *rect);
98
static void atafb_copyarea(struct fb_info *info,
99
                           const struct fb_copyarea *region);
100
static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
101
static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
102
                       unsigned long arg);
103
 
104
 
105
static int default_par;         /* default resolution (0=none) */
106
 
107
static unsigned long default_mem_req;
108
 
109
static int hwscroll = -1;
110
 
111
static int use_hwscroll = 1;
112
 
113
static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
114
static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
115
static int ovsc_offset, ovsc_addlen;
116
 
117
        /*
118
         * Hardware parameters for current mode
119
         */
120
 
121
static struct atafb_par {
122
        void *screen_base;
123
        int yres_virtual;
124
        u_long next_line;
125
        u_long next_plane;
126
#if defined ATAFB_TT || defined ATAFB_STE
127
        union {
128
                struct {
129
                        int mode;
130
                        int sync;
131
                } tt, st;
132
#endif
133
#ifdef ATAFB_FALCON
134
                struct falcon_hw {
135
                        /* Here are fields for storing a video mode, as direct
136
                         * parameters for the hardware.
137
                         */
138
                        short sync;
139
                        short line_width;
140
                        short line_offset;
141
                        short st_shift;
142
                        short f_shift;
143
                        short vid_control;
144
                        short vid_mode;
145
                        short xoffset;
146
                        short hht, hbb, hbe, hdb, hde, hss;
147
                        short vft, vbb, vbe, vdb, vde, vss;
148
                        /* auxiliary information */
149
                        short mono;
150
                        short ste_mode;
151
                        short bpp;
152
                } falcon;
153
#endif
154
                /* Nothing needed for external mode */
155
        } hw;
156
} current_par;
157
 
158
/* Don't calculate an own resolution, and thus don't change the one found when
159
 * booting (currently used for the Falcon to keep settings for internal video
160
 * hardware extensions (e.g. ScreenBlaster)  */
161
static int DontCalcRes = 0;
162
 
163
#ifdef ATAFB_FALCON
164
#define HHT hw.falcon.hht
165
#define HBB hw.falcon.hbb
166
#define HBE hw.falcon.hbe
167
#define HDB hw.falcon.hdb
168
#define HDE hw.falcon.hde
169
#define HSS hw.falcon.hss
170
#define VFT hw.falcon.vft
171
#define VBB hw.falcon.vbb
172
#define VBE hw.falcon.vbe
173
#define VDB hw.falcon.vdb
174
#define VDE hw.falcon.vde
175
#define VSS hw.falcon.vss
176
#define VCO_CLOCK25             0x04
177
#define VCO_CSYPOS              0x10
178
#define VCO_VSYPOS              0x20
179
#define VCO_HSYPOS              0x40
180
#define VCO_SHORTOFFS   0x100
181
#define VMO_DOUBLE              0x01
182
#define VMO_INTER               0x02
183
#define VMO_PREMASK             0x0c
184
#endif
185
 
186
static struct fb_info fb_info = {
187
        .fix = {
188
                .id     = "Atari ",
189
                .visual = FB_VISUAL_PSEUDOCOLOR,
190
                .accel  = FB_ACCEL_NONE,
191
        }
192
};
193
 
194
static void *screen_base;       /* base address of screen */
195
static void *real_screen_base;  /* (only for Overscan) */
196
 
197
static int screen_len;
198
 
199
static int current_par_valid;
200
 
201
static int mono_moni;
202
 
203
 
204
#ifdef ATAFB_EXT
205
 
206
/* external video handling */
207
static unsigned int external_xres;
208
static unsigned int external_xres_virtual;
209
static unsigned int external_yres;
210
 
211
/*
212
 * not needed - atafb will never support panning/hardwarescroll with external
213
 * static unsigned int external_yres_virtual;
214
 */
215
static unsigned int external_depth;
216
static int external_pmode;
217
static void *external_addr;
218
static unsigned long external_len;
219
static unsigned long external_vgaiobase;
220
static unsigned int external_bitspercol = 6;
221
 
222
/*
223
 * JOE <joe@amber.dinoco.de>:
224
 * added card type for external driver, is only needed for
225
 * colormap handling.
226
 */
227
enum cardtype { IS_VGA, IS_MV300 };
228
static enum cardtype external_card_type = IS_VGA;
229
 
230
/*
231
 * The MV300 mixes the color registers. So we need an array of munged
232
 * indices in order to access the correct reg.
233
 */
234
static int MV300_reg_1bit[2] = {
235
        0, 1
236
};
237
static int MV300_reg_4bit[16] = {
238
        0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
239
};
240
static int MV300_reg_8bit[256] = {
241
        0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
242
        8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
243
        4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
244
        12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
245
        2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
246
        10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
247
        6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
248
        14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
249
        1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
250
        9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
251
        5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
252
        13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
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
};
258
 
259
static int *MV300_reg = MV300_reg_8bit;
260
#endif /* ATAFB_EXT */
261
 
262
 
263
static int inverse;
264
 
265
extern int fontheight_8x8;
266
extern int fontwidth_8x8;
267
extern unsigned char fontdata_8x8[];
268
 
269
extern int fontheight_8x16;
270
extern int fontwidth_8x16;
271
extern unsigned char fontdata_8x16[];
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
 
342
/* ++roman: This structure abstracts from the underlying hardware (ST(e),
343
 * TT, or Falcon.
344
 *
345
 * int (*detect)(void)
346
 *   This function should detect the current video mode settings and
347
 *   store them in atafb_predefined[0] for later reference by the
348
 *   user. Return the index+1 of an equivalent predefined mode or 0
349
 *   if there is no such.
350
 *
351
 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
352
 *                   struct atafb_par *par)
353
 *   This function should fill in the 'fix' structure based on the
354
 *   values in the 'par' structure.
355
 * !!! Obsolete, perhaps !!!
356
 *
357
 * int (*decode_var)(struct fb_var_screeninfo *var,
358
 *                   struct atafb_par *par)
359
 *   Get the video params out of 'var'. If a value doesn't fit, round
360
 *   it up, if it's too big, return EINVAL.
361
 *   Round up in the following order: bits_per_pixel, xres, yres,
362
 *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
363
 *   horizontal timing, vertical timing.
364
 *
365
 * int (*encode_var)(struct fb_var_screeninfo *var,
366
 *                   struct atafb_par *par);
367
 *   Fill the 'var' structure based on the values in 'par' and maybe
368
 *   other values read out of the hardware.
369
 *
370
 * void (*get_par)(struct atafb_par *par)
371
 *   Fill the hardware's 'par' structure.
372
 *   !!! Used only by detect() !!!
373
 *
374
 * void (*set_par)(struct atafb_par *par)
375
 *   Set the hardware according to 'par'.
376
 *
377
 * void (*set_screen_base)(void *s_base)
378
 *   Set the base address of the displayed frame buffer. Only called
379
 *   if yres_virtual > yres or xres_virtual > xres.
380
 *
381
 * int (*blank)(int blank_mode)
382
 *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
383
 *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
384
 *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
385
 *   doesn't support it. Implements VESA suspend and powerdown modes on
386
 *   hardware that supports disabling hsync/vsync:
387
 *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
388
 */
389
 
390
static struct fb_hwswitch {
391
        int (*detect)(void);
392
        int (*encode_fix)(struct fb_fix_screeninfo *fix,
393
                          struct atafb_par *par);
394
        int (*decode_var)(struct fb_var_screeninfo *var,
395
                          struct atafb_par *par);
396
        int (*encode_var)(struct fb_var_screeninfo *var,
397
                          struct atafb_par *par);
398
        void (*get_par)(struct atafb_par *par);
399
        void (*set_par)(struct atafb_par *par);
400
        void (*set_screen_base)(void *s_base);
401
        int (*blank)(int blank_mode);
402
        int (*pan_display)(struct fb_var_screeninfo *var,
403
                           struct fb_info *info);
404
} *fbhw;
405
 
406
static char *autodetect_names[] = { "autodetect", NULL };
407
static char *stlow_names[] = { "stlow", NULL };
408
static char *stmid_names[] = { "stmid", "default5", NULL };
409
static char *sthigh_names[] = { "sthigh", "default4", NULL };
410
static char *ttlow_names[] = { "ttlow", NULL };
411
static char *ttmid_names[] = { "ttmid", "default1", NULL };
412
static char *tthigh_names[] = { "tthigh", "default2", NULL };
413
static char *vga2_names[] = { "vga2", NULL };
414
static char *vga4_names[] = { "vga4", NULL };
415
static char *vga16_names[] = { "vga16", "default3", NULL };
416
static char *vga256_names[] = { "vga256", NULL };
417
static char *falh2_names[] = { "falh2", NULL };
418
static char *falh16_names[] = { "falh16", NULL };
419
 
420
static char **fb_var_names[] = {
421
        autodetect_names,
422
        stlow_names,
423
        stmid_names,
424
        sthigh_names,
425
        ttlow_names,
426
        ttmid_names,
427
        tthigh_names,
428
        vga2_names,
429
        vga4_names,
430
        vga16_names,
431
        vga256_names,
432
        falh2_names,
433
        falh16_names,
434
        NULL
435
};
436
 
437
static struct fb_var_screeninfo atafb_predefined[] = {
438
        /*
439
         * yres_virtual == 0 means use hw-scrolling if possible, else yres
440
         */
441
        { /* autodetect */
442
          0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
443
          {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},       /* red green blue tran*/
444
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
445
        { /* st low */
446
          320, 200, 320, 0, 0, 0, 4, 0,
447
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
448
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
449
        { /* st mid */
450
          640, 200, 640, 0, 0, 0, 2, 0,
451
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
452
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
453
        { /* st high */
454
          640, 400, 640, 0, 0, 0, 1, 0,
455
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
456
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
457
        { /* tt low */
458
          320, 480, 320, 0, 0, 0, 8, 0,
459
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
460
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
461
        { /* tt mid */
462
          640, 480, 640, 0, 0, 0, 4, 0,
463
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
464
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
465
        { /* tt high */
466
          1280, 960, 1280, 0, 0, 0, 1, 0,
467
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
468
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
469
        { /* vga2 */
470
          640, 480, 640, 0, 0, 0, 1, 0,
471
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
472
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
473
        { /* vga4 */
474
          640, 480, 640, 0, 0, 0, 2, 0,
475
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
476
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
477
        { /* vga16 */
478
          640, 480, 640, 0, 0, 0, 4, 0,
479
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
480
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
481
        { /* vga256 */
482
          640, 480, 640, 0, 0, 0, 8, 0,
483
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
484
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
485
        { /* falh2 */
486
          896, 608, 896, 0, 0, 0, 1, 0,
487
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
488
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
489
        { /* falh16 */
490
          896, 608, 896, 0, 0, 0, 4, 0,
491
          {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
492
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
493
};
494
 
495
static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
496
 
497
static struct fb_videomode atafb_modedb[] __initdata = {
498
        /*
499
         *  Atari Video Modes
500
         *
501
         *  If you change these, make sure to update DEFMODE_* as well!
502
         */
503
 
504
        /*
505
         *  ST/TT Video Modes
506
         */
507
 
508
        {
509
                /* 320x200, 15 kHz, 60 Hz (ST low) */
510
                "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
511
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
512
        }, {
513
                /* 640x200, 15 kHz, 60 Hz (ST medium) */
514
                "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
515
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
516
        }, {
517
                /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
518
                "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
519
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
520
        }, {
521
                /* 320x480, 15 kHz, 60 Hz (TT low) */
522
                "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
523
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
524
        }, {
525
                /* 640x480, 29 kHz, 57 Hz (TT medium) */
526
                "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
527
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
528
        }, {
529
                /* 1280x960, 29 kHz, 60 Hz (TT high) */
530
                "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
531
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
532
        },
533
 
534
        /*
535
         *  VGA Video Modes
536
         */
537
 
538
        {
539
                /* 640x480, 31 kHz, 60 Hz (VGA) */
540
                "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
541
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
542
        }, {
543
                /* 640x400, 31 kHz, 70 Hz (VGA) */
544
                "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
545
                FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
546
        },
547
 
548
        /*
549
         *  Falcon HiRes Video Modes
550
         */
551
 
552
        {
553
                /* 896x608, 31 kHz, 60 Hz (Falcon High) */
554
                "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
555
                0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
556
        },
557
};
558
 
559
#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
560
 
561
static char *mode_option __initdata = NULL;
562
 
563
 /* default modes */
564
 
565
#define DEFMODE_TT      5               /* "tt-high" for TT */
566
#define DEFMODE_F30     7               /* "vga70" for Falcon */
567
#define DEFMODE_STE     2               /* "st-high" for ST/E */
568
#define DEFMODE_EXT     6               /* "vga" for external */
569
 
570
 
571
static int get_video_mode(char *vname)
572
{
573
        char ***name_list;
574
        char **name;
575
        int i;
576
 
577
        name_list = fb_var_names;
578
        for (i = 0; i < num_atafb_predefined; i++) {
579
                name = *name_list++;
580
                if (!name || !*name)
581
                        break;
582
                while (*name) {
583
                        if (!strcmp(vname, *name))
584
                                return i + 1;
585
                        name++;
586
                }
587
        }
588
        return 0;
589
}
590
 
591
 
592
 
593
/* ------------------- TT specific functions ---------------------- */
594
 
595
#ifdef ATAFB_TT
596
 
597
static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
598
{
599
        int mode;
600
 
601
        strcpy(fix->id, "Atari Builtin");
602
        fix->smem_start = (unsigned long)real_screen_base;
603
        fix->smem_len = screen_len;
604
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
605
        fix->type_aux = 2;
606
        fix->visual = FB_VISUAL_PSEUDOCOLOR;
607
        mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
608
        if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
609
                fix->type = FB_TYPE_PACKED_PIXELS;
610
                fix->type_aux = 0;
611
                if (mode == TT_SHIFTER_TTHIGH)
612
                        fix->visual = FB_VISUAL_MONO01;
613
        }
614
        fix->xpanstep = 0;
615
        fix->ypanstep = 1;
616
        fix->ywrapstep = 0;
617
        fix->line_length = 0;
618
        fix->accel = FB_ACCEL_ATARIBLITT;
619
        return 0;
620
}
621
 
622
static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
623
{
624
        int xres = var->xres;
625
        int yres = var->yres;
626
        int bpp = var->bits_per_pixel;
627
        int linelen;
628
        int yres_virtual = var->yres_virtual;
629
 
630
        if (mono_moni) {
631
                if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
632
                        return -EINVAL;
633
                par->hw.tt.mode = TT_SHIFTER_TTHIGH;
634
                xres = sttt_xres * 2;
635
                yres = tt_yres * 2;
636
                bpp = 1;
637
        } else {
638
                if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
639
                        return -EINVAL;
640
                if (bpp > 4) {
641
                        if (xres > sttt_xres / 2 || yres > tt_yres)
642
                                return -EINVAL;
643
                        par->hw.tt.mode = TT_SHIFTER_TTLOW;
644
                        xres = sttt_xres / 2;
645
                        yres = tt_yres;
646
                        bpp = 8;
647
                } else if (bpp > 2) {
648
                        if (xres > sttt_xres || yres > tt_yres)
649
                                return -EINVAL;
650
                        if (xres > sttt_xres / 2 || yres > st_yres / 2) {
651
                                par->hw.tt.mode = TT_SHIFTER_TTMID;
652
                                xres = sttt_xres;
653
                                yres = tt_yres;
654
                                bpp = 4;
655
                        } else {
656
                                par->hw.tt.mode = TT_SHIFTER_STLOW;
657
                                xres = sttt_xres / 2;
658
                                yres = st_yres / 2;
659
                                bpp = 4;
660
                        }
661
                } else if (bpp > 1) {
662
                        if (xres > sttt_xres || yres > st_yres / 2)
663
                                return -EINVAL;
664
                        par->hw.tt.mode = TT_SHIFTER_STMID;
665
                        xres = sttt_xres;
666
                        yres = st_yres / 2;
667
                        bpp = 2;
668
                } else if (var->xres > sttt_xres || var->yres > st_yres) {
669
                        return -EINVAL;
670
                } else {
671
                        par->hw.tt.mode = TT_SHIFTER_STHIGH;
672
                        xres = sttt_xres;
673
                        yres = st_yres;
674
                        bpp = 1;
675
                }
676
        }
677
        if (yres_virtual <= 0)
678
                yres_virtual = 0;
679
        else if (yres_virtual < yres)
680
                yres_virtual = yres;
681
        if (var->sync & FB_SYNC_EXT)
682
                par->hw.tt.sync = 0;
683
        else
684
                par->hw.tt.sync = 1;
685
        linelen = xres * bpp / 8;
686
        if (yres_virtual * linelen > screen_len && screen_len)
687
                return -EINVAL;
688
        if (yres * linelen > screen_len && screen_len)
689
                return -EINVAL;
690
        if (var->yoffset + yres > yres_virtual && yres_virtual)
691
                return -EINVAL;
692
        par->yres_virtual = yres_virtual;
693
        par->screen_base = screen_base + var->yoffset * linelen;
694
        return 0;
695
}
696
 
697
static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
698
{
699
        int linelen;
700
        memset(var, 0, sizeof(struct fb_var_screeninfo));
701
        var->red.offset = 0;
702
        var->red.length = 4;
703
        var->red.msb_right = 0;
704
        var->grayscale = 0;
705
 
706
        var->pixclock = 31041;
707
        var->left_margin = 120;         /* these may be incorrect */
708
        var->right_margin = 100;
709
        var->upper_margin = 8;
710
        var->lower_margin = 16;
711
        var->hsync_len = 140;
712
        var->vsync_len = 30;
713
 
714
        var->height = -1;
715
        var->width = -1;
716
 
717
        if (par->hw.tt.sync & 1)
718
                var->sync = 0;
719
        else
720
                var->sync = FB_SYNC_EXT;
721
 
722
        switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
723
        case TT_SHIFTER_STLOW:
724
                var->xres = sttt_xres / 2;
725
                var->xres_virtual = sttt_xres_virtual / 2;
726
                var->yres = st_yres / 2;
727
                var->bits_per_pixel = 4;
728
                break;
729
        case TT_SHIFTER_STMID:
730
                var->xres = sttt_xres;
731
                var->xres_virtual = sttt_xres_virtual;
732
                var->yres = st_yres / 2;
733
                var->bits_per_pixel = 2;
734
                break;
735
        case TT_SHIFTER_STHIGH:
736
                var->xres = sttt_xres;
737
                var->xres_virtual = sttt_xres_virtual;
738
                var->yres = st_yres;
739
                var->bits_per_pixel = 1;
740
                break;
741
        case TT_SHIFTER_TTLOW:
742
                var->xres = sttt_xres / 2;
743
                var->xres_virtual = sttt_xres_virtual / 2;
744
                var->yres = tt_yres;
745
                var->bits_per_pixel = 8;
746
                break;
747
        case TT_SHIFTER_TTMID:
748
                var->xres = sttt_xres;
749
                var->xres_virtual = sttt_xres_virtual;
750
                var->yres = tt_yres;
751
                var->bits_per_pixel = 4;
752
                break;
753
        case TT_SHIFTER_TTHIGH:
754
                var->red.length = 0;
755
                var->xres = sttt_xres * 2;
756
                var->xres_virtual = sttt_xres_virtual * 2;
757
                var->yres = tt_yres * 2;
758
                var->bits_per_pixel = 1;
759
                break;
760
        }
761
        var->blue = var->green = var->red;
762
        var->transp.offset = 0;
763
        var->transp.length = 0;
764
        var->transp.msb_right = 0;
765
        linelen = var->xres_virtual * var->bits_per_pixel / 8;
766
        if (!use_hwscroll)
767
                var->yres_virtual = var->yres;
768
        else if (screen_len) {
769
                if (par->yres_virtual)
770
                        var->yres_virtual = par->yres_virtual;
771
                else
772
                        /* yres_virtual == 0 means use maximum */
773
                        var->yres_virtual = screen_len / linelen;
774
        } else {
775
                if (hwscroll < 0)
776
                        var->yres_virtual = 2 * var->yres;
777
                else
778
                        var->yres_virtual = var->yres + hwscroll * 16;
779
        }
780
        var->xoffset = 0;
781
        if (screen_base)
782
                var->yoffset = (par->screen_base - screen_base) / linelen;
783
        else
784
                var->yoffset = 0;
785
        var->nonstd = 0;
786
        var->activate = 0;
787
        var->vmode = FB_VMODE_NONINTERLACED;
788
        return 0;
789
}
790
 
791
static void tt_get_par(struct atafb_par *par)
792
{
793
        unsigned long addr;
794
        par->hw.tt.mode = shifter_tt.tt_shiftmode;
795
        par->hw.tt.sync = shifter.syncmode;
796
        addr = ((shifter.bas_hi & 0xff) << 16) |
797
               ((shifter.bas_md & 0xff) << 8)  |
798
               ((shifter.bas_lo & 0xff));
799
        par->screen_base = phys_to_virt(addr);
800
}
801
 
802
static void tt_set_par(struct atafb_par *par)
803
{
804
        shifter_tt.tt_shiftmode = par->hw.tt.mode;
805
        shifter.syncmode = par->hw.tt.sync;
806
        /* only set screen_base if really necessary */
807
        if (current_par.screen_base != par->screen_base)
808
                fbhw->set_screen_base(par->screen_base);
809
}
810
 
811
static int tt_setcolreg(unsigned int regno, unsigned int red,
812
                        unsigned int green, unsigned int blue,
813
                        unsigned int transp, struct fb_info *info)
814
{
815
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
816
                regno += 254;
817
        if (regno > 255)
818
                return 1;
819
        tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
820
                             (blue >> 12));
821
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
822
            TT_SHIFTER_STHIGH && regno == 254)
823
                tt_palette[0] = 0;
824
        return 0;
825
}
826
 
827
static int tt_detect(void)
828
{
829
        struct atafb_par par;
830
 
831
        /* Determine the connected monitor: The DMA sound must be
832
         * disabled before reading the MFP GPIP, because the Sound
833
         * Done Signal and the Monochrome Detect are XORed together!
834
         *
835
         * Even on a TT, we should look if there is a DMA sound. It was
836
         * announced that the Eagle is TT compatible, but only the PCM is
837
         * missing...
838
         */
839
        if (ATARIHW_PRESENT(PCM_8BIT)) {
840
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
841
                udelay(20);             /* wait a while for things to settle down */
842
        }
843
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
844
 
845
        tt_get_par(&par);
846
        tt_encode_var(&atafb_predefined[0], &par);
847
 
848
        return 1;
849
}
850
 
851
#endif /* ATAFB_TT */
852
 
853
/* ------------------- Falcon specific functions ---------------------- */
854
 
855
#ifdef ATAFB_FALCON
856
 
857
static int mon_type;            /* Falcon connected monitor */
858
static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
859
#define F_MON_SM        0
860
#define F_MON_SC        1
861
#define F_MON_VGA       2
862
#define F_MON_TV        3
863
 
864
static struct pixel_clock {
865
        unsigned long f;        /* f/[Hz] */
866
        unsigned long t;        /* t/[ps] (=1/f) */
867
        int right, hsync, left; /* standard timing in clock cycles, not pixel */
868
        /* hsync initialized in falcon_detect() */
869
        int sync_mask;          /* or-mask for hw.falcon.sync to set this clock */
870
        int control_mask;       /* ditto, for hw.falcon.vid_control */
871
} f25 = {
872
        25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
873
}, f32 = {
874
        32000000, 31250, 18, 0, 42, 0x0, 0
875
}, fext = {
876
        0, 0, 18, 0, 42, 0x1, 0
877
};
878
 
879
/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
880
static int vdl_prescale[4][3] = {
881
        { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
882
};
883
 
884
/* Default hsync timing [mon_type] in picoseconds */
885
static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
886
 
887
#ifdef FBCON_HAS_CFB16
888
static u16 fbcon_cfb16_cmap[16];
889
#endif
890
 
891
static inline int hxx_prescale(struct falcon_hw *hw)
892
{
893
        return hw->ste_mode ? 16
894
                            : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
895
}
896
 
897
static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
898
                             struct atafb_par *par)
899
{
900
        strcpy(fix->id, "Atari Builtin");
901
        fix->smem_start = (unsigned long)real_screen_base;
902
        fix->smem_len = screen_len;
903
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
904
        fix->type_aux = 2;
905
        fix->visual = FB_VISUAL_PSEUDOCOLOR;
906
        fix->xpanstep = 1;
907
        fix->ypanstep = 1;
908
        fix->ywrapstep = 0;
909
        if (par->hw.falcon.mono) {
910
                fix->type = FB_TYPE_PACKED_PIXELS;
911
                fix->type_aux = 0;
912
                /* no smooth scrolling with longword aligned video mem */
913
                fix->xpanstep = 32;
914
        } else if (par->hw.falcon.f_shift & 0x100) {
915
                fix->type = FB_TYPE_PACKED_PIXELS;
916
                fix->type_aux = 0;
917
                /* Is this ok or should it be DIRECTCOLOR? */
918
                fix->visual = FB_VISUAL_TRUECOLOR;
919
                fix->xpanstep = 2;
920
        }
921
        fix->line_length = 0;
922
        fix->accel = FB_ACCEL_ATARIBLITT;
923
        return 0;
924
}
925
 
926
static int falcon_decode_var(struct fb_var_screeninfo *var,
927
                             struct atafb_par *par)
928
{
929
        int bpp = var->bits_per_pixel;
930
        int xres = var->xres;
931
        int yres = var->yres;
932
        int xres_virtual = var->xres_virtual;
933
        int yres_virtual = var->yres_virtual;
934
        int left_margin, right_margin, hsync_len;
935
        int upper_margin, lower_margin, vsync_len;
936
        int linelen;
937
        int interlace = 0, doubleline = 0;
938
        struct pixel_clock *pclock;
939
        int plen;                       /* width of pixel in clock cycles */
940
        int xstretch;
941
        int prescale;
942
        int longoffset = 0;
943
        int hfreq, vfreq;
944
        int hdb_off, hde_off, base_off;
945
        int gstart, gend1, gend2, align;
946
 
947
/*
948
        Get the video params out of 'var'. If a value doesn't fit, round
949
        it up, if it's too big, return EINVAL.
950
        Round up in the following order: bits_per_pixel, xres, yres,
951
        xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
952
        horizontal timing, vertical timing.
953
 
954
        There is a maximum of screen resolution determined by pixelclock
955
        and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
956
        In interlace mode this is     "     *    "     *vfmin <= pixelclock.
957
        Additional constraints: hfreq.
958
        Frequency range for multisync monitors is given via command line.
959
        For TV and SM124 both frequencies are fixed.
960
 
961
        X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
962
        Y % 16 == 0 to fit 8x16 font
963
        Y % 8 == 0 if Y<400
964
 
965
        Currently interlace and doubleline mode in var are ignored.
966
        On SM124 and TV only the standard resolutions can be used.
967
*/
968
 
969
        /* Reject uninitialized mode */
970
        if (!xres || !yres || !bpp)
971
                return -EINVAL;
972
 
973
        if (mon_type == F_MON_SM && bpp != 1)
974
                return -EINVAL;
975
 
976
        if (bpp <= 1) {
977
                bpp = 1;
978
                par->hw.falcon.f_shift = 0x400;
979
                par->hw.falcon.st_shift = 0x200;
980
        } else if (bpp <= 2) {
981
                bpp = 2;
982
                par->hw.falcon.f_shift = 0x000;
983
                par->hw.falcon.st_shift = 0x100;
984
        } else if (bpp <= 4) {
985
                bpp = 4;
986
                par->hw.falcon.f_shift = 0x000;
987
                par->hw.falcon.st_shift = 0x000;
988
        } else if (bpp <= 8) {
989
                bpp = 8;
990
                par->hw.falcon.f_shift = 0x010;
991
        } else if (bpp <= 16) {
992
                bpp = 16;               /* packed pixel mode */
993
                par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
994
        } else
995
                return -EINVAL;
996
        par->hw.falcon.bpp = bpp;
997
 
998
        if (mon_type == F_MON_SM || DontCalcRes) {
999
                /* Skip all calculations. VGA/TV/SC1224 only supported. */
1000
                struct fb_var_screeninfo *myvar = &atafb_predefined[0];
1001
 
1002
                if (bpp > myvar->bits_per_pixel ||
1003
                    var->xres > myvar->xres ||
1004
                    var->yres > myvar->yres)
1005
                        return -EINVAL;
1006
                fbhw->get_par(par);     /* Current par will be new par */
1007
                goto set_screen_base;   /* Don't forget this */
1008
        }
1009
 
1010
        /* Only some fixed resolutions < 640x400 */
1011
        if (xres <= 320)
1012
                xres = 320;
1013
        else if (xres <= 640 && bpp != 16)
1014
                xres = 640;
1015
        if (yres <= 200)
1016
                yres = 200;
1017
        else if (yres <= 240)
1018
                yres = 240;
1019
        else if (yres <= 400)
1020
                yres = 400;
1021
 
1022
        /* 2 planes must use STE compatibility mode */
1023
        par->hw.falcon.ste_mode = bpp == 2;
1024
        par->hw.falcon.mono = bpp == 1;
1025
 
1026
        /* Total and visible scanline length must be a multiple of one longword,
1027
         * this and the console fontwidth yields the alignment for xres and
1028
         * xres_virtual.
1029
         * TODO: this way "odd" fontheights are not supported
1030
         *
1031
         * Special case in STE mode: blank and graphic positions don't align,
1032
         * avoid trash at right margin
1033
         */
1034
        if (par->hw.falcon.ste_mode)
1035
                xres = (xres + 63) & ~63;
1036
        else if (bpp == 1)
1037
                xres = (xres + 31) & ~31;
1038
        else
1039
                xres = (xres + 15) & ~15;
1040
        if (yres >= 400)
1041
                yres = (yres + 15) & ~15;
1042
        else
1043
                yres = (yres + 7) & ~7;
1044
 
1045
        if (xres_virtual < xres)
1046
                xres_virtual = xres;
1047
        else if (bpp == 1)
1048
                xres_virtual = (xres_virtual + 31) & ~31;
1049
        else
1050
                xres_virtual = (xres_virtual + 15) & ~15;
1051
 
1052
        if (yres_virtual <= 0)
1053
                yres_virtual = 0;
1054
        else if (yres_virtual < yres)
1055
                yres_virtual = yres;
1056
 
1057
        /* backward bug-compatibility */
1058
        if (var->pixclock > 1)
1059
                var->pixclock -= 1;
1060
 
1061
        par->hw.falcon.line_width = bpp * xres / 16;
1062
        par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1063
 
1064
        /* single or double pixel width */
1065
        xstretch = (xres < 640) ? 2 : 1;
1066
 
1067
#if 0 /* SM124 supports only 640x400, this is rejected above */
1068
        if (mon_type == F_MON_SM) {
1069
                if (xres != 640 && yres != 400)
1070
                        return -EINVAL;
1071
                plen = 1;
1072
                pclock = &f32;
1073
                /* SM124-mode is special */
1074
                par->hw.falcon.ste_mode = 1;
1075
                par->hw.falcon.f_shift = 0x000;
1076
                par->hw.falcon.st_shift = 0x200;
1077
                left_margin = hsync_len = 128 / plen;
1078
                right_margin = 0;
1079
                /* TODO set all margins */
1080
        } else
1081
#endif
1082
        if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1083
                plen = 2 * xstretch;
1084
                if (var->pixclock > f32.t * plen)
1085
                        return -EINVAL;
1086
                pclock = &f32;
1087
                if (yres > 240)
1088
                        interlace = 1;
1089
                if (var->pixclock == 0) {
1090
                        /* set some minimal margins which center the screen */
1091
                        left_margin = 32;
1092
                        right_margin = 18;
1093
                        hsync_len = pclock->hsync / plen;
1094
                        upper_margin = 31;
1095
                        lower_margin = 14;
1096
                        vsync_len = interlace ? 3 : 4;
1097
                } else {
1098
                        left_margin = var->left_margin;
1099
                        right_margin = var->right_margin;
1100
                        hsync_len = var->hsync_len;
1101
                        upper_margin = var->upper_margin;
1102
                        lower_margin = var->lower_margin;
1103
                        vsync_len = var->vsync_len;
1104
                        if (var->vmode & FB_VMODE_INTERLACED) {
1105
                                upper_margin = (upper_margin + 1) / 2;
1106
                                lower_margin = (lower_margin + 1) / 2;
1107
                                vsync_len = (vsync_len + 1) / 2;
1108
                        } else if (var->vmode & FB_VMODE_DOUBLE) {
1109
                                upper_margin *= 2;
1110
                                lower_margin *= 2;
1111
                                vsync_len *= 2;
1112
                        }
1113
                }
1114
        } else {                        /* F_MON_VGA */
1115
                if (bpp == 16)
1116
                        xstretch = 2;   /* Double pixel width only for hicolor */
1117
                /* Default values are used for vert./hor. timing if no pixelclock given. */
1118
                if (var->pixclock == 0) {
1119
                        int linesize;
1120
 
1121
                        /* Choose master pixelclock depending on hor. timing */
1122
                        plen = 1 * xstretch;
1123
                        if ((plen * xres + f25.right + f25.hsync + f25.left) *
1124
                            fb_info.monspecs.hfmin < f25.f)
1125
                                pclock = &f25;
1126
                        else if ((plen * xres + f32.right + f32.hsync +
1127
                                  f32.left) * fb_info.monspecs.hfmin < f32.f)
1128
                                pclock = &f32;
1129
                        else if ((plen * xres + fext.right + fext.hsync +
1130
                                  fext.left) * fb_info.monspecs.hfmin < fext.f &&
1131
                                 fext.f)
1132
                                pclock = &fext;
1133
                        else
1134
                                return -EINVAL;
1135
 
1136
                        left_margin = pclock->left / plen;
1137
                        right_margin = pclock->right / plen;
1138
                        hsync_len = pclock->hsync / plen;
1139
                        linesize = left_margin + xres + right_margin + hsync_len;
1140
                        upper_margin = 31;
1141
                        lower_margin = 11;
1142
                        vsync_len = 3;
1143
                } else {
1144
                        /* Choose largest pixelclock <= wanted clock */
1145
                        int i;
1146
                        unsigned long pcl = ULONG_MAX;
1147
                        pclock = 0;
1148
                        for (i = 1; i <= 4; i *= 2) {
1149
                                if (f25.t * i >= var->pixclock &&
1150
                                    f25.t * i < pcl) {
1151
                                        pcl = f25.t * i;
1152
                                        pclock = &f25;
1153
                                }
1154
                                if (f32.t * i >= var->pixclock &&
1155
                                    f32.t * i < pcl) {
1156
                                        pcl = f32.t * i;
1157
                                        pclock = &f32;
1158
                                }
1159
                                if (fext.t && fext.t * i >= var->pixclock &&
1160
                                    fext.t * i < pcl) {
1161
                                        pcl = fext.t * i;
1162
                                        pclock = &fext;
1163
                                }
1164
                        }
1165
                        if (!pclock)
1166
                                return -EINVAL;
1167
                        plen = pcl / pclock->t;
1168
 
1169
                        left_margin = var->left_margin;
1170
                        right_margin = var->right_margin;
1171
                        hsync_len = var->hsync_len;
1172
                        upper_margin = var->upper_margin;
1173
                        lower_margin = var->lower_margin;
1174
                        vsync_len = var->vsync_len;
1175
                        /* Internal unit is [single lines per (half-)frame] */
1176
                        if (var->vmode & FB_VMODE_INTERLACED) {
1177
                                /* # lines in half frame */
1178
                                /* External unit is [lines per full frame] */
1179
                                upper_margin = (upper_margin + 1) / 2;
1180
                                lower_margin = (lower_margin + 1) / 2;
1181
                                vsync_len = (vsync_len + 1) / 2;
1182
                        } else if (var->vmode & FB_VMODE_DOUBLE) {
1183
                                /* External unit is [double lines per frame] */
1184
                                upper_margin *= 2;
1185
                                lower_margin *= 2;
1186
                                vsync_len *= 2;
1187
                        }
1188
                }
1189
                if (pclock == &fext)
1190
                        longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1191
        }
1192
        /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1193
        /* this is definitely wrong if bus clock != 32MHz */
1194
        if (pclock->f / plen / 8 * bpp > 32000000L)
1195
                return -EINVAL;
1196
 
1197
        if (vsync_len < 1)
1198
                vsync_len = 1;
1199
 
1200
        /* include sync lengths in right/lower margin for all calculations */
1201
        right_margin += hsync_len;
1202
        lower_margin += vsync_len;
1203
 
1204
        /* ! In all calculations of margins we use # of lines in half frame
1205
         * (which is a full frame in non-interlace mode), so we can switch
1206
         * between interlace and non-interlace without messing around
1207
         * with these.
1208
         */
1209
again:
1210
        /* Set base_offset 128 and video bus width */
1211
        par->hw.falcon.vid_control = mon_type | f030_bus_width;
1212
        if (!longoffset)
1213
                par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
1214
        if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1215
                par->hw.falcon.vid_control |= VCO_HSYPOS;
1216
        if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1217
                par->hw.falcon.vid_control |= VCO_VSYPOS;
1218
        /* Pixelclock */
1219
        par->hw.falcon.vid_control |= pclock->control_mask;
1220
        /* External or internal clock */
1221
        par->hw.falcon.sync = pclock->sync_mask | 0x2;
1222
        /* Pixellength and prescale */
1223
        par->hw.falcon.vid_mode = (2 / plen) << 2;
1224
        if (doubleline)
1225
                par->hw.falcon.vid_mode |= VMO_DOUBLE;
1226
        if (interlace)
1227
                par->hw.falcon.vid_mode |= VMO_INTER;
1228
 
1229
        /*********************
1230
         * Horizontal timing: unit = [master clock cycles]
1231
         * unit of hxx-registers: [master clock cycles * prescale]
1232
         * Hxx-registers are 9 bit wide
1233
         *
1234
         * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1235
         *
1236
         * graphic output = hdb & 0x200 ?
1237
         *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1238
         *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
1239
         * (this must be a multiple of plen*128/bpp, on VGA pixels
1240
         *  to the right may be cut off with a bigger right margin)
1241
         *
1242
         * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1243
         *        (hdb - hht - 2) * prescale + hdboff :
1244
         *        hdb * prescale + hdboff
1245
         *
1246
         * end of graphics relative to start of 1st halfline =
1247
         *        (hde + hht + 2) * prescale + hdeoff
1248
         *********************/
1249
        /* Calculate VIDEL registers */
1250
{
1251
        prescale = hxx_prescale(&par->hw.falcon);
1252
        base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1253
 
1254
        /* Offsets depend on video mode */
1255
        /* Offsets are in clock cycles, divide by prescale to
1256
         * calculate hd[be]-registers
1257
         */
1258
        if (par->hw.falcon.f_shift & 0x100) {
1259
                align = 1;
1260
                hde_off = 0;
1261
                hdb_off = (base_off + 16 * plen) + prescale;
1262
        } else {
1263
                align = 128 / bpp;
1264
                hde_off = ((128 / bpp + 2) * plen);
1265
                if (par->hw.falcon.ste_mode)
1266
                        hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1267
                else
1268
                        hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1269
        }
1270
 
1271
        gstart = (prescale / 2 + plen * left_margin) / prescale;
1272
        /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1273
        gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
1274
        /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1275
        gend2 = gstart + xres * plen / prescale;
1276
        par->HHT = plen * (left_margin + xres + right_margin) /
1277
                           (2 * prescale) - 2;
1278
/*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1279
 
1280
        par->HDB = gstart - hdb_off / prescale;
1281
        par->HBE = gstart;
1282
        if (par->HDB < 0)
1283
                par->HDB += par->HHT + 2 + 0x200;
1284
        par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1285
        par->HBB = gend2 - par->HHT - 2;
1286
#if 0
1287
        /* One more Videl constraint: data fetch of two lines must not overlap */
1288
        if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1289
                /* if this happens increase margins, decrease hfreq. */
1290
        }
1291
#endif
1292
        if (hde_off % prescale)
1293
                par->HBB++;             /* compensate for non matching hde and hbb */
1294
        par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1295
        if (par->HSS < par->HBB)
1296
                par->HSS = par->HBB;
1297
}
1298
 
1299
        /*  check hor. frequency */
1300
        hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1301
        if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1302
                /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1303
                /* Too high -> enlarge margin */
1304
                left_margin += 1;
1305
                right_margin += 1;
1306
                goto again;
1307
        }
1308
        if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1309
                return -EINVAL;
1310
 
1311
        /* Vxx-registers */
1312
        /* All Vxx must be odd in non-interlace, since frame starts in the middle
1313
         * of the first displayed line!
1314
         * One frame consists of VFT+1 half lines. VFT+1 must be even in
1315
         * non-interlace, odd in interlace mode for synchronisation.
1316
         * Vxx-registers are 11 bit wide
1317
         */
1318
        par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1319
        par->VDB = par->VBE;
1320
        par->VDE = yres;
1321
        if (!interlace)
1322
                par->VDE <<= 1;
1323
        if (doubleline)
1324
                par->VDE <<= 1;         /* VDE now half lines per (half-)frame */
1325
        par->VDE += par->VDB;
1326
        par->VBB = par->VDE;
1327
        par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1328
        par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1329
        /* vbb,vss,vft must be even in interlace mode */
1330
        if (interlace) {
1331
                par->VBB++;
1332
                par->VSS++;
1333
                par->VFT++;
1334
        }
1335
 
1336
        /* V-frequency check, hope I didn't create any loop here. */
1337
        /* Interlace and doubleline are mutually exclusive. */
1338
        vfreq = (hfreq * 2) / (par->VFT + 1);
1339
        if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1340
                /* Too high -> try again with doubleline */
1341
                doubleline = 1;
1342
                goto again;
1343
        } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1344
                /* Too low -> try again with interlace */
1345
                interlace = 1;
1346
                goto again;
1347
        } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1348
                /* Doubleline too low -> clear doubleline and enlarge margins */
1349
                int lines;
1350
                doubleline = 0;
1351
                for (lines = 0;
1352
                     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1353
                     fb_info.monspecs.vfmax;
1354
                     lines++)
1355
                        ;
1356
                upper_margin += lines;
1357
                lower_margin += lines;
1358
                goto again;
1359
        } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1360
                /* Doubleline too high -> enlarge margins */
1361
                int lines;
1362
                for (lines = 0;
1363
                     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1364
                     fb_info.monspecs.vfmax;
1365
                     lines += 2)
1366
                        ;
1367
                upper_margin += lines;
1368
                lower_margin += lines;
1369
                goto again;
1370
        } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1371
                /* Interlace, too high -> enlarge margins */
1372
                int lines;
1373
                for (lines = 0;
1374
                     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1375
                     fb_info.monspecs.vfmax;
1376
                     lines++)
1377
                        ;
1378
                upper_margin += lines;
1379
                lower_margin += lines;
1380
                goto again;
1381
        } else if (vfreq < fb_info.monspecs.vfmin ||
1382
                   vfreq > fb_info.monspecs.vfmax)
1383
                return -EINVAL;
1384
 
1385
set_screen_base:
1386
        linelen = xres_virtual * bpp / 8;
1387
        if (yres_virtual * linelen > screen_len && screen_len)
1388
                return -EINVAL;
1389
        if (yres * linelen > screen_len && screen_len)
1390
                return -EINVAL;
1391
        if (var->yoffset + yres > yres_virtual && yres_virtual)
1392
                return -EINVAL;
1393
        par->yres_virtual = yres_virtual;
1394
        par->screen_base = screen_base + var->yoffset * linelen;
1395
        par->hw.falcon.xoffset = 0;
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
 
1406
        return 0;
1407
}
1408
 
1409
static int falcon_encode_var(struct fb_var_screeninfo *var,
1410
                             struct atafb_par *par)
1411
{
1412
/* !!! only for VGA !!! */
1413
        int linelen;
1414
        int prescale, plen;
1415
        int hdb_off, hde_off, base_off;
1416
        struct falcon_hw *hw = &par->hw.falcon;
1417
 
1418
        memset(var, 0, sizeof(struct fb_var_screeninfo));
1419
        /* possible frequencies: 25.175 or 32MHz */
1420
        var->pixclock = hw->sync & 0x1 ? fext.t :
1421
                        hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1422
 
1423
        var->height = -1;
1424
        var->width = -1;
1425
 
1426
        var->sync = 0;
1427
        if (hw->vid_control & VCO_HSYPOS)
1428
                var->sync |= FB_SYNC_HOR_HIGH_ACT;
1429
        if (hw->vid_control & VCO_VSYPOS)
1430
                var->sync |= FB_SYNC_VERT_HIGH_ACT;
1431
 
1432
        var->vmode = FB_VMODE_NONINTERLACED;
1433
        if (hw->vid_mode & VMO_INTER)
1434
                var->vmode |= FB_VMODE_INTERLACED;
1435
        if (hw->vid_mode & VMO_DOUBLE)
1436
                var->vmode |= FB_VMODE_DOUBLE;
1437
 
1438
        /* visible y resolution:
1439
         * Graphics display starts at line VDB and ends at line
1440
         * VDE. If interlace mode off unit of VC-registers is
1441
         * half lines, else lines.
1442
         */
1443
        var->yres = hw->vde - hw->vdb;
1444
        if (!(var->vmode & FB_VMODE_INTERLACED))
1445
                var->yres >>= 1;
1446
        if (var->vmode & FB_VMODE_DOUBLE)
1447
                var->yres >>= 1;
1448
 
1449
        /*
1450
         * to get bpp, we must examine f_shift and st_shift.
1451
         * f_shift is valid if any of bits no. 10, 8 or 4
1452
         * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1453
         * if bit 10 set then bit 8 and bit 4 don't care...
1454
         * If all these bits are 0 get display depth from st_shift
1455
         * (as for ST and STE)
1456
         */
1457
        if (hw->f_shift & 0x400)        /* 2 colors */
1458
                var->bits_per_pixel = 1;
1459
        else if (hw->f_shift & 0x100)   /* hicolor */
1460
                var->bits_per_pixel = 16;
1461
        else if (hw->f_shift & 0x010)   /* 8 bitplanes */
1462
                var->bits_per_pixel = 8;
1463
        else if (hw->st_shift == 0)
1464
                var->bits_per_pixel = 4;
1465
        else if (hw->st_shift == 0x100)
1466
                var->bits_per_pixel = 2;
1467
        else                            /* if (hw->st_shift == 0x200) */
1468
                var->bits_per_pixel = 1;
1469
 
1470
        var->xres = hw->line_width * 16 / var->bits_per_pixel;
1471
        var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1472
        if (hw->xoffset)
1473
                var->xres_virtual += 16;
1474
 
1475
        if (var->bits_per_pixel == 16) {
1476
                var->red.offset = 11;
1477
                var->red.length = 5;
1478
                var->red.msb_right = 0;
1479
                var->green.offset = 5;
1480
                var->green.length = 6;
1481
                var->green.msb_right = 0;
1482
                var->blue.offset = 0;
1483
                var->blue.length = 5;
1484
                var->blue.msb_right = 0;
1485
        } else {
1486
                var->red.offset = 0;
1487
                var->red.length = hw->ste_mode ? 4 : 6;
1488
                if (var->red.length > var->bits_per_pixel)
1489
                        var->red.length = var->bits_per_pixel;
1490
                var->red.msb_right = 0;
1491
                var->grayscale = 0;
1492
                var->blue = var->green = var->red;
1493
        }
1494
        var->transp.offset = 0;
1495
        var->transp.length = 0;
1496
        var->transp.msb_right = 0;
1497
 
1498
        linelen = var->xres_virtual * var->bits_per_pixel / 8;
1499
        if (screen_len) {
1500
                if (par->yres_virtual)
1501
                        var->yres_virtual = par->yres_virtual;
1502
                else
1503
                        /* yres_virtual == 0 means use maximum */
1504
                        var->yres_virtual = screen_len / linelen;
1505
        } else {
1506
                if (hwscroll < 0)
1507
                        var->yres_virtual = 2 * var->yres;
1508
                else
1509
                        var->yres_virtual = var->yres + hwscroll * 16;
1510
        }
1511
        var->xoffset = 0;                /* TODO change this */
1512
 
1513
        /* hdX-offsets */
1514
        prescale = hxx_prescale(hw);
1515
        plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1516
        base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1517
        if (hw->f_shift & 0x100) {
1518
                hde_off = 0;
1519
                hdb_off = (base_off + 16 * plen) + prescale;
1520
        } else {
1521
                hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1522
                if (hw->ste_mode)
1523
                        hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1524
                                         + prescale;
1525
                else
1526
                        hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1527
                                         + prescale;
1528
        }
1529
 
1530
        /* Right margin includes hsync */
1531
        var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1532
                                           (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1533
        if (hw->ste_mode || mon_type != F_MON_VGA)
1534
                var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1535
        else
1536
                /* can't use this in ste_mode, because hbb is +1 off */
1537
                var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1538
        var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1539
 
1540
        /* Lower margin includes vsync */
1541
        var->upper_margin = hw->vdb / 2;        /* round down to full lines */
1542
        var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;    /* round up */
1543
        var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;       /* round up */
1544
        if (var->vmode & FB_VMODE_INTERLACED) {
1545
                var->upper_margin *= 2;
1546
                var->lower_margin *= 2;
1547
                var->vsync_len *= 2;
1548
        } else if (var->vmode & FB_VMODE_DOUBLE) {
1549
                var->upper_margin = (var->upper_margin + 1) / 2;
1550
                var->lower_margin = (var->lower_margin + 1) / 2;
1551
                var->vsync_len = (var->vsync_len + 1) / 2;
1552
        }
1553
 
1554
        var->pixclock *= plen;
1555
        var->left_margin /= plen;
1556
        var->right_margin /= plen;
1557
        var->hsync_len /= plen;
1558
 
1559
        var->right_margin -= var->hsync_len;
1560
        var->lower_margin -= var->vsync_len;
1561
 
1562
        if (screen_base)
1563
                var->yoffset = (par->screen_base - screen_base) / linelen;
1564
        else
1565
                var->yoffset = 0;
1566
        var->nonstd = 0;         /* what is this for? */
1567
        var->activate = 0;
1568
        return 0;
1569
}
1570
 
1571
static int f_change_mode;
1572
static struct falcon_hw f_new_mode;
1573
static int f_pan_display;
1574
 
1575
static void falcon_get_par(struct atafb_par *par)
1576
{
1577
        unsigned long addr;
1578
        struct falcon_hw *hw = &par->hw.falcon;
1579
 
1580
        hw->line_width = shifter_f030.scn_width;
1581
        hw->line_offset = shifter_f030.off_next;
1582
        hw->st_shift = videl.st_shift & 0x300;
1583
        hw->f_shift = videl.f_shift;
1584
        hw->vid_control = videl.control;
1585
        hw->vid_mode = videl.mode;
1586
        hw->sync = shifter.syncmode & 0x1;
1587
        hw->xoffset = videl.xoffset & 0xf;
1588
        hw->hht = videl.hht;
1589
        hw->hbb = videl.hbb;
1590
        hw->hbe = videl.hbe;
1591
        hw->hdb = videl.hdb;
1592
        hw->hde = videl.hde;
1593
        hw->hss = videl.hss;
1594
        hw->vft = videl.vft;
1595
        hw->vbb = videl.vbb;
1596
        hw->vbe = videl.vbe;
1597
        hw->vdb = videl.vdb;
1598
        hw->vde = videl.vde;
1599
        hw->vss = videl.vss;
1600
 
1601
        addr = (shifter.bas_hi & 0xff) << 16 |
1602
               (shifter.bas_md & 0xff) << 8  |
1603
               (shifter.bas_lo & 0xff);
1604
        par->screen_base = phys_to_virt(addr);
1605
 
1606
        /* derived parameters */
1607
        hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1608
        hw->mono = (hw->f_shift & 0x400) ||
1609
                   ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1610
}
1611
 
1612
static void falcon_set_par(struct atafb_par *par)
1613
{
1614
        f_change_mode = 0;
1615
 
1616
        /* only set screen_base if really necessary */
1617
        if (current_par.screen_base != par->screen_base)
1618
                fbhw->set_screen_base(par->screen_base);
1619
 
1620
        /* Don't touch any other registers if we keep the default resolution */
1621
        if (DontCalcRes)
1622
                return;
1623
 
1624
        /* Tell vbl-handler to change video mode.
1625
         * We change modes only on next VBL, to avoid desynchronisation
1626
         * (a shift to the right and wrap around by a random number of pixels
1627
         * in all monochrome modes).
1628
         * This seems to work on my Falcon.
1629
         */
1630
        f_new_mode = par->hw.falcon;
1631
        f_change_mode = 1;
1632
}
1633
 
1634
static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1635
{
1636
        struct falcon_hw *hw = &f_new_mode;
1637
 
1638
        if (f_change_mode) {
1639
                f_change_mode = 0;
1640
 
1641
                if (hw->sync & 0x1) {
1642
                        /* Enable external pixelclock. This code only for ScreenWonder */
1643
                        *(volatile unsigned short *)0xffff9202 = 0xffbf;
1644
                } else {
1645
                        /* Turn off external clocks. Read sets all output bits to 1. */
1646
                        *(volatile unsigned short *)0xffff9202;
1647
                }
1648
                shifter.syncmode = hw->sync;
1649
 
1650
                videl.hht = hw->hht;
1651
                videl.hbb = hw->hbb;
1652
                videl.hbe = hw->hbe;
1653
                videl.hdb = hw->hdb;
1654
                videl.hde = hw->hde;
1655
                videl.hss = hw->hss;
1656
                videl.vft = hw->vft;
1657
                videl.vbb = hw->vbb;
1658
                videl.vbe = hw->vbe;
1659
                videl.vdb = hw->vdb;
1660
                videl.vde = hw->vde;
1661
                videl.vss = hw->vss;
1662
 
1663
                videl.f_shift = 0;       /* write enables Falcon palette, 0: 4 planes */
1664
                if (hw->ste_mode) {
1665
                        videl.st_shift = hw->st_shift;  /* write enables STE palette */
1666
                } else {
1667
                        /* IMPORTANT:
1668
                         * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1669
                         * Writing 0 to f_shift enables 4 plane Falcon mode but
1670
                         * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1671
                         * with Falcon palette.
1672
                         */
1673
                        videl.st_shift = 0;
1674
                        /* now back to Falcon palette mode */
1675
                        videl.f_shift = hw->f_shift;
1676
                }
1677
                /* writing to st_shift changed scn_width and vid_mode */
1678
                videl.xoffset = hw->xoffset;
1679
                shifter_f030.scn_width = hw->line_width;
1680
                shifter_f030.off_next = hw->line_offset;
1681
                videl.control = hw->vid_control;
1682
                videl.mode = hw->vid_mode;
1683
        }
1684
        if (f_pan_display) {
1685
                f_pan_display = 0;
1686
                videl.xoffset = current_par.hw.falcon.xoffset;
1687
                shifter_f030.off_next = current_par.hw.falcon.line_offset;
1688
        }
1689
        return IRQ_HANDLED;
1690
}
1691
 
1692
static int falcon_pan_display(struct fb_var_screeninfo *var,
1693
                              struct fb_info *info)
1694
{
1695
        struct atafb_par *par = (struct atafb_par *)info->par;
1696
 
1697
        int xoffset;
1698
        int bpp = info->var.bits_per_pixel;
1699
 
1700
        if (bpp == 1)
1701
                var->xoffset = up(var->xoffset, 32);
1702
        if (bpp != 16)
1703
                par->hw.falcon.xoffset = var->xoffset & 15;
1704
        else {
1705
                par->hw.falcon.xoffset = 0;
1706
                var->xoffset = up(var->xoffset, 2);
1707
        }
1708
        par->hw.falcon.line_offset = bpp *
1709
                (info->var.xres_virtual - info->var.xres) / 16;
1710
        if (par->hw.falcon.xoffset)
1711
                par->hw.falcon.line_offset -= bpp;
1712
        xoffset = var->xoffset - par->hw.falcon.xoffset;
1713
 
1714
        par->screen_base = screen_base +
1715
                (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1716
        if (fbhw->set_screen_base)
1717
                fbhw->set_screen_base(par->screen_base);
1718
        else
1719
                return -EINVAL;         /* shouldn't happen */
1720
        f_pan_display = 1;
1721
        return 0;
1722
}
1723
 
1724
static int falcon_setcolreg(unsigned int regno, unsigned int red,
1725
                            unsigned int green, unsigned int blue,
1726
                            unsigned int transp, struct fb_info *info)
1727
{
1728
        if (regno > 255)
1729
                return 1;
1730
        f030_col[regno] = (((red & 0xfc00) << 16) |
1731
                           ((green & 0xfc00) << 8) |
1732
                           ((blue & 0xfc00) >> 8));
1733
        if (regno < 16) {
1734
                shifter_tt.color_reg[regno] =
1735
                        (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1736
                        (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1737
                        ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1738
#ifdef FBCON_HAS_CFB16
1739
                fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
1740
                                           ((green & 0xfc00) >> 5) |
1741
                                           ((blue & 0xf800) >> 11));
1742
#endif
1743
        }
1744
        return 0;
1745
}
1746
 
1747
static int falcon_blank(int blank_mode)
1748
{
1749
        /* ++guenther: we can switch off graphics by changing VDB and VDE,
1750
         * so VIDEL doesn't hog the bus while saving.
1751
         * (this may affect usleep()).
1752
         */
1753
        int vdb, vss, hbe, hss;
1754
 
1755
        if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
1756
                return 1;
1757
 
1758
        vdb = current_par.VDB;
1759
        vss = current_par.VSS;
1760
        hbe = current_par.HBE;
1761
        hss = current_par.HSS;
1762
 
1763
        if (blank_mode >= 1) {
1764
                /* disable graphics output (this speeds up the CPU) ... */
1765
                vdb = current_par.VFT + 1;
1766
                /* ... and blank all lines */
1767
                hbe = current_par.HHT + 2;
1768
        }
1769
        /* use VESA suspend modes on VGA monitors */
1770
        if (mon_type == F_MON_VGA) {
1771
                if (blank_mode == 2 || blank_mode == 4)
1772
                        vss = current_par.VFT + 1;
1773
                if (blank_mode == 3 || blank_mode == 4)
1774
                        hss = current_par.HHT + 2;
1775
        }
1776
 
1777
        videl.vdb = vdb;
1778
        videl.vss = vss;
1779
        videl.hbe = hbe;
1780
        videl.hss = hss;
1781
 
1782
        return 0;
1783
}
1784
 
1785
static int falcon_detect(void)
1786
{
1787
        struct atafb_par par;
1788
        unsigned char fhw;
1789
 
1790
        /* Determine connected monitor and set monitor parameters */
1791
        fhw = *(unsigned char *)0xffff8006;
1792
        mon_type = fhw >> 6 & 0x3;
1793
        /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1794
        f030_bus_width = fhw << 6 & 0x80;
1795
        switch (mon_type) {
1796
        case F_MON_SM:
1797
                fb_info.monspecs.vfmin = 70;
1798
                fb_info.monspecs.vfmax = 72;
1799
                fb_info.monspecs.hfmin = 35713;
1800
                fb_info.monspecs.hfmax = 35715;
1801
                break;
1802
        case F_MON_SC:
1803
        case F_MON_TV:
1804
                /* PAL...NTSC */
1805
                fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
1806
                fb_info.monspecs.vfmax = 60;
1807
                fb_info.monspecs.hfmin = 15620;
1808
                fb_info.monspecs.hfmax = 15755;
1809
                break;
1810
        }
1811
        /* initialize hsync-len */
1812
        f25.hsync = h_syncs[mon_type] / f25.t;
1813
        f32.hsync = h_syncs[mon_type] / f32.t;
1814
        if (fext.t)
1815
                fext.hsync = h_syncs[mon_type] / fext.t;
1816
 
1817
        falcon_get_par(&par);
1818
        falcon_encode_var(&atafb_predefined[0], &par);
1819
 
1820
        /* Detected mode is always the "autodetect" slot */
1821
        return 1;
1822
}
1823
 
1824
#endif /* ATAFB_FALCON */
1825
 
1826
/* ------------------- ST(E) specific functions ---------------------- */
1827
 
1828
#ifdef ATAFB_STE
1829
 
1830
static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1831
                            struct atafb_par *par)
1832
{
1833
        int mode;
1834
 
1835
        strcpy(fix->id, "Atari Builtin");
1836
        fix->smem_start = (unsigned long)real_screen_base;
1837
        fix->smem_len = screen_len;
1838
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
1839
        fix->type_aux = 2;
1840
        fix->visual = FB_VISUAL_PSEUDOCOLOR;
1841
        mode = par->hw.st.mode & 3;
1842
        if (mode == ST_HIGH) {
1843
                fix->type = FB_TYPE_PACKED_PIXELS;
1844
                fix->type_aux = 0;
1845
                fix->visual = FB_VISUAL_MONO10;
1846
        }
1847
        if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1848
                fix->xpanstep = 16;
1849
                fix->ypanstep = 1;
1850
        } else {
1851
                fix->xpanstep = 0;
1852
                fix->ypanstep = 0;
1853
        }
1854
        fix->ywrapstep = 0;
1855
        fix->line_length = 0;
1856
        fix->accel = FB_ACCEL_ATARIBLITT;
1857
        return 0;
1858
}
1859
 
1860
static int stste_decode_var(struct fb_var_screeninfo *var,
1861
                            struct atafb_par *par)
1862
{
1863
        int xres = var->xres;
1864
        int yres = var->yres;
1865
        int bpp = var->bits_per_pixel;
1866
        int linelen;
1867
        int yres_virtual = var->yres_virtual;
1868
 
1869
        if (mono_moni) {
1870
                if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1871
                        return -EINVAL;
1872
                par->hw.st.mode = ST_HIGH;
1873
                xres = sttt_xres;
1874
                yres = st_yres;
1875
                bpp = 1;
1876
        } else {
1877
                if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1878
                        return -EINVAL;
1879
                if (bpp > 2) {
1880
                        if (xres > sttt_xres / 2 || yres > st_yres / 2)
1881
                                return -EINVAL;
1882
                        par->hw.st.mode = ST_LOW;
1883
                        xres = sttt_xres / 2;
1884
                        yres = st_yres / 2;
1885
                        bpp = 4;
1886
                } else if (bpp > 1) {
1887
                        if (xres > sttt_xres || yres > st_yres / 2)
1888
                                return -EINVAL;
1889
                        par->hw.st.mode = ST_MID;
1890
                        xres = sttt_xres;
1891
                        yres = st_yres / 2;
1892
                        bpp = 2;
1893
                } else
1894
                        return -EINVAL;
1895
        }
1896
        if (yres_virtual <= 0)
1897
                yres_virtual = 0;
1898
        else if (yres_virtual < yres)
1899
                yres_virtual = yres;
1900
        if (var->sync & FB_SYNC_EXT)
1901
                par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1902
        else
1903
                par->hw.st.sync = (par->hw.st.sync & ~1);
1904
        linelen = xres * bpp / 8;
1905
        if (yres_virtual * linelen > screen_len && screen_len)
1906
                return -EINVAL;
1907
        if (yres * linelen > screen_len && screen_len)
1908
                return -EINVAL;
1909
        if (var->yoffset + yres > yres_virtual && yres_virtual)
1910
                return -EINVAL;
1911
        par->yres_virtual = yres_virtual;
1912
        par->screen_base = screen_base + var->yoffset * linelen;
1913
        return 0;
1914
}
1915
 
1916
static int stste_encode_var(struct fb_var_screeninfo *var,
1917
                            struct atafb_par *par)
1918
{
1919
        int linelen;
1920
        memset(var, 0, sizeof(struct fb_var_screeninfo));
1921
        var->red.offset = 0;
1922
        var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1923
        var->red.msb_right = 0;
1924
        var->grayscale = 0;
1925
 
1926
        var->pixclock = 31041;
1927
        var->left_margin = 120;         /* these are incorrect */
1928
        var->right_margin = 100;
1929
        var->upper_margin = 8;
1930
        var->lower_margin = 16;
1931
        var->hsync_len = 140;
1932
        var->vsync_len = 30;
1933
 
1934
        var->height = -1;
1935
        var->width = -1;
1936
 
1937
        if (!(par->hw.st.sync & 1))
1938
                var->sync = 0;
1939
        else
1940
                var->sync = FB_SYNC_EXT;
1941
 
1942
        switch (par->hw.st.mode & 3) {
1943
        case ST_LOW:
1944
                var->xres = sttt_xres / 2;
1945
                var->yres = st_yres / 2;
1946
                var->bits_per_pixel = 4;
1947
                break;
1948
        case ST_MID:
1949
                var->xres = sttt_xres;
1950
                var->yres = st_yres / 2;
1951
                var->bits_per_pixel = 2;
1952
                break;
1953
        case ST_HIGH:
1954
                var->xres = sttt_xres;
1955
                var->yres = st_yres;
1956
                var->bits_per_pixel = 1;
1957
                break;
1958
        }
1959
        var->blue = var->green = var->red;
1960
        var->transp.offset = 0;
1961
        var->transp.length = 0;
1962
        var->transp.msb_right = 0;
1963
        var->xres_virtual = sttt_xres_virtual;
1964
        linelen = var->xres_virtual * var->bits_per_pixel / 8;
1965
        ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1966
 
1967
        if (!use_hwscroll)
1968
                var->yres_virtual = var->yres;
1969
        else if (screen_len) {
1970
                if (par->yres_virtual)
1971
                        var->yres_virtual = par->yres_virtual;
1972
                else
1973
                        /* yres_virtual == 0 means use maximum */
1974
                        var->yres_virtual = screen_len / linelen;
1975
        } else {
1976
                if (hwscroll < 0)
1977
                        var->yres_virtual = 2 * var->yres;
1978
                else
1979
                        var->yres_virtual = var->yres + hwscroll * 16;
1980
        }
1981
        var->xoffset = 0;
1982
        if (screen_base)
1983
                var->yoffset = (par->screen_base - screen_base) / linelen;
1984
        else
1985
                var->yoffset = 0;
1986
        var->nonstd = 0;
1987
        var->activate = 0;
1988
        var->vmode = FB_VMODE_NONINTERLACED;
1989
        return 0;
1990
}
1991
 
1992
static void stste_get_par(struct atafb_par *par)
1993
{
1994
        unsigned long addr;
1995
        par->hw.st.mode = shifter_tt.st_shiftmode;
1996
        par->hw.st.sync = shifter.syncmode;
1997
        addr = ((shifter.bas_hi & 0xff) << 16) |
1998
               ((shifter.bas_md & 0xff) << 8);
1999
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
2000
                addr |= (shifter.bas_lo & 0xff);
2001
        par->screen_base = phys_to_virt(addr);
2002
}
2003
 
2004
static void stste_set_par(struct atafb_par *par)
2005
{
2006
        shifter_tt.st_shiftmode = par->hw.st.mode;
2007
        shifter.syncmode = par->hw.st.sync;
2008
        /* only set screen_base if really necessary */
2009
        if (current_par.screen_base != par->screen_base)
2010
                fbhw->set_screen_base(par->screen_base);
2011
}
2012
 
2013
static int stste_setcolreg(unsigned int regno, unsigned int red,
2014
                           unsigned int green, unsigned int blue,
2015
                           unsigned int transp, struct fb_info *info)
2016
{
2017
        if (regno > 15)
2018
                return 1;
2019
        red >>= 12;
2020
        blue >>= 12;
2021
        green >>= 12;
2022
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
2023
                shifter_tt.color_reg[regno] =
2024
                        (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
2025
                        (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
2026
                        ((blue & 0xe) >> 1) | ((blue & 1) << 3);
2027
        else
2028
                shifter_tt.color_reg[regno] =
2029
                        ((red & 0xe) << 7) |
2030
                        ((green & 0xe) << 3) |
2031
                        ((blue & 0xe) >> 1);
2032
        return 0;
2033
}
2034
 
2035
static int stste_detect(void)
2036
{
2037
        struct atafb_par par;
2038
 
2039
        /* Determine the connected monitor: The DMA sound must be
2040
         * disabled before reading the MFP GPIP, because the Sound
2041
         * Done Signal and the Monochrome Detect are XORed together!
2042
         */
2043
        if (ATARIHW_PRESENT(PCM_8BIT)) {
2044
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2045
                udelay(20);             /* wait a while for things to settle down */
2046
        }
2047
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
2048
 
2049
        stste_get_par(&par);
2050
        stste_encode_var(&atafb_predefined[0], &par);
2051
 
2052
        if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2053
                use_hwscroll = 0;
2054
        return 1;
2055
}
2056
 
2057
static void stste_set_screen_base(void *s_base)
2058
{
2059
        unsigned long addr;
2060
        addr = virt_to_phys(s_base);
2061
        /* Setup Screen Memory */
2062
        shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2063
        shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2064
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
2065
                shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2066
}
2067
 
2068
#endif /* ATAFB_STE */
2069
 
2070
/* Switching the screen size should be done during vsync, otherwise
2071
 * the margins may get messed up. This is a well known problem of
2072
 * the ST's video system.
2073
 *
2074
 * Unfortunately there is hardly any way to find the vsync, as the
2075
 * vertical blank interrupt is no longer in time on machines with
2076
 * overscan type modifications.
2077
 *
2078
 * We can, however, use Timer B to safely detect the black shoulder,
2079
 * but then we've got to guess an appropriate delay to find the vsync.
2080
 * This might not work on every machine.
2081
 *
2082
 * martin_rogge @ ki.maus.de, 8th Aug 1995
2083
 */
2084
 
2085
#define LINE_DELAY  (mono_moni ? 30 : 70)
2086
#define SYNC_DELAY  (mono_moni ? 1500 : 2000)
2087
 
2088
/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2089
static void st_ovsc_switch(void)
2090
{
2091
        unsigned long flags;
2092
        register unsigned char old, new;
2093
 
2094
        if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2095
                return;
2096
        local_irq_save(flags);
2097
 
2098
        mfp.tim_ct_b = 0x10;
2099
        mfp.active_edge |= 8;
2100
        mfp.tim_ct_b = 0;
2101
        mfp.tim_dt_b = 0xf0;
2102
        mfp.tim_ct_b = 8;
2103
        while (mfp.tim_dt_b > 1)        /* TOS does it this way, don't ask why */
2104
                ;
2105
        new = mfp.tim_dt_b;
2106
        do {
2107
                udelay(LINE_DELAY);
2108
                old = new;
2109
                new = mfp.tim_dt_b;
2110
        } while (old != new);
2111
        mfp.tim_ct_b = 0x10;
2112
        udelay(SYNC_DELAY);
2113
 
2114
        if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2115
                acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2116
        if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2117
                acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2118
        if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2119
                sound_ym.rd_data_reg_sel = 14;
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);
2125
}
2126
 
2127
/* ------------------- External Video ---------------------- */
2128
 
2129
#ifdef ATAFB_EXT
2130
 
2131
static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2132
{
2133
        strcpy(fix->id, "Unknown Extern");
2134
        fix->smem_start = (unsigned long)external_addr;
2135
        fix->smem_len = PAGE_ALIGN(external_len);
2136
        if (external_depth == 1) {
2137
                fix->type = FB_TYPE_PACKED_PIXELS;
2138
                /* The letters 'n' and 'i' in the "atavideo=external:" stand
2139
                 * for "normal" and "inverted", rsp., in the monochrome case */
2140
                fix->visual =
2141
                        (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2142
                         external_pmode == FB_TYPE_PACKED_PIXELS) ?
2143
                                FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2144
        } else {
2145
                /* Use STATIC if we don't know how to access color registers */
2146
                int visual = external_vgaiobase ?
2147
                                         FB_VISUAL_PSEUDOCOLOR :
2148
                                         FB_VISUAL_STATIC_PSEUDOCOLOR;
2149
                switch (external_pmode) {
2150
                case -1:                /* truecolor */
2151
                        fix->type = FB_TYPE_PACKED_PIXELS;
2152
                        fix->visual = FB_VISUAL_TRUECOLOR;
2153
                        break;
2154
                case FB_TYPE_PACKED_PIXELS:
2155
                        fix->type = FB_TYPE_PACKED_PIXELS;
2156
                        fix->visual = visual;
2157
                        break;
2158
                case FB_TYPE_PLANES:
2159
                        fix->type = FB_TYPE_PLANES;
2160
                        fix->visual = visual;
2161
                        break;
2162
                case FB_TYPE_INTERLEAVED_PLANES:
2163
                        fix->type = FB_TYPE_INTERLEAVED_PLANES;
2164
                        fix->type_aux = 2;
2165
                        fix->visual = visual;
2166
                        break;
2167
                }
2168
        }
2169
        fix->xpanstep = 0;
2170
        fix->ypanstep = 0;
2171
        fix->ywrapstep = 0;
2172
        fix->line_length = 0;
2173
        return 0;
2174
}
2175
 
2176
static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2177
{
2178
        struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2179
 
2180
        if (var->bits_per_pixel > myvar->bits_per_pixel ||
2181
            var->xres > myvar->xres ||
2182
            var->xres_virtual > myvar->xres_virtual ||
2183
            var->yres > myvar->yres ||
2184
            var->xoffset > 0 ||
2185
            var->yoffset > 0)
2186
                return -EINVAL;
2187
        return 0;
2188
}
2189
 
2190
static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2191
{
2192
        memset(var, 0, sizeof(struct fb_var_screeninfo));
2193
        var->red.offset = 0;
2194
        var->red.length = (external_pmode == -1) ? external_depth / 3 :
2195
                        (external_vgaiobase ? external_bitspercol : 0);
2196
        var->red.msb_right = 0;
2197
        var->grayscale = 0;
2198
 
2199
        var->pixclock = 31041;
2200
        var->left_margin = 120;         /* these are surely incorrect */
2201
        var->right_margin = 100;
2202
        var->upper_margin = 8;
2203
        var->lower_margin = 16;
2204
        var->hsync_len = 140;
2205
        var->vsync_len = 30;
2206
 
2207
        var->height = -1;
2208
        var->width = -1;
2209
 
2210
        var->sync = 0;
2211
 
2212
        var->xres = external_xres;
2213
        var->yres = external_yres;
2214
        var->xres_virtual = external_xres_virtual;
2215
        var->bits_per_pixel = external_depth;
2216
 
2217
        var->blue = var->green = var->red;
2218
        var->transp.offset = 0;
2219
        var->transp.length = 0;
2220
        var->transp.msb_right = 0;
2221
        var->yres_virtual = var->yres;
2222
        var->xoffset = 0;
2223
        var->yoffset = 0;
2224
        var->nonstd = 0;
2225
        var->activate = 0;
2226
        var->vmode = FB_VMODE_NONINTERLACED;
2227
        return 0;
2228
}
2229
 
2230
static void ext_get_par(struct atafb_par *par)
2231
{
2232
        par->screen_base = external_addr;
2233
}
2234
 
2235
static void ext_set_par(struct atafb_par *par)
2236
{
2237
}
2238
 
2239
#define OUTB(port,val) \
2240
        *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2241
#define INB(port) \
2242
        (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2243
#define DACDelay                                \
2244
        do {                                    \
2245
                unsigned char tmp = INB(0x3da); \
2246
                tmp = INB(0x3da);                       \
2247
        } while (0)
2248
 
2249
static int ext_setcolreg(unsigned int regno, unsigned int red,
2250
                         unsigned int green, unsigned int blue,
2251
                         unsigned int transp, struct fb_info *info)
2252
{
2253
        unsigned char colmask = (1 << external_bitspercol) - 1;
2254
 
2255
        if (!external_vgaiobase)
2256
                return 1;
2257
 
2258
        switch (external_card_type) {
2259
        case IS_VGA:
2260
                OUTB(0x3c8, regno);
2261
                DACDelay;
2262
                OUTB(0x3c9, red & colmask);
2263
                DACDelay;
2264
                OUTB(0x3c9, green & colmask);
2265
                DACDelay;
2266
                OUTB(0x3c9, blue & colmask);
2267
                DACDelay;
2268
                return 0;
2269
 
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;
2275
 
2276
        default:
2277
                return 1;
2278
        }
2279
}
2280
 
2281
static int ext_detect(void)
2282
{
2283
        struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2284
        struct atafb_par dummy_par;
2285
 
2286
        myvar->xres = external_xres;
2287
        myvar->xres_virtual = external_xres_virtual;
2288
        myvar->yres = external_yres;
2289
        myvar->bits_per_pixel = external_depth;
2290
        ext_encode_var(myvar, &dummy_par);
2291
        return 1;
2292
}
2293
 
2294
#endif /* ATAFB_EXT */
2295
 
2296
/* ------ This is the same for most hardware types -------- */
2297
 
2298
static void set_screen_base(void *s_base)
2299
{
2300
        unsigned long addr;
2301
 
2302
        addr = virt_to_phys(s_base);
2303
        /* Setup Screen Memory */
2304
        shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2305
        shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2306
        shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
2307
}
2308
 
2309
static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2310
{
2311
        struct atafb_par *par = (struct atafb_par *)info->par;
2312
 
2313
        if (!fbhw->set_screen_base ||
2314
            (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2315
                return -EINVAL;
2316
        var->xoffset = up(var->xoffset, 16);
2317
        par->screen_base = screen_base +
2318
                (var->yoffset * info->var.xres_virtual + var->xoffset)
2319
                * info->var.bits_per_pixel / 8;
2320
        fbhw->set_screen_base(par->screen_base);
2321
        return 0;
2322
}
2323
 
2324
/* ------------ Interfaces to hardware functions ------------ */
2325
 
2326
#ifdef ATAFB_TT
2327
static struct fb_hwswitch tt_switch = {
2328
        .detect         = tt_detect,
2329
        .encode_fix     = tt_encode_fix,
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,
2336
};
2337
#endif
2338
 
2339
#ifdef ATAFB_FALCON
2340
static struct fb_hwswitch falcon_switch = {
2341
        .detect         = falcon_detect,
2342
        .encode_fix     = falcon_encode_fix,
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,
2350
};
2351
#endif
2352
 
2353
#ifdef ATAFB_STE
2354
static struct fb_hwswitch st_switch = {
2355
        .detect         = stste_detect,
2356
        .encode_fix     = stste_encode_fix,
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
2363
};
2364
#endif
2365
 
2366
#ifdef ATAFB_EXT
2367
static struct fb_hwswitch ext_switch = {
2368
        .detect         = ext_detect,
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,
2374
};
2375
#endif
2376
 
2377
static void ata_get_par(struct atafb_par *par)
2378
{
2379
        if (current_par_valid)
2380
                *par = current_par;
2381
        else
2382
                fbhw->get_par(par);
2383
}
2384
 
2385
static void ata_set_par(struct atafb_par *par)
2386
{
2387
        fbhw->set_par(par);
2388
        current_par = *par;
2389
        current_par_valid = 1;
2390
}
2391
 
2392
 
2393
/* =========================================================== */
2394
/* ============== Hardware Independent Functions ============= */
2395
/* =========================================================== */
2396
 
2397
/* used for hardware scrolling */
2398
 
2399
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2400
{
2401
        int err, activate;
2402
        struct atafb_par par;
2403
 
2404
        err = fbhw->decode_var(var, &par);
2405
        if (err)
2406
                return err;
2407
        activate = var->activate;
2408
        if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2409
                ata_set_par(&par);
2410
        fbhw->encode_var(var, &par);
2411
        var->activate = activate;
2412
        return 0;
2413
}
2414
 
2415
static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2416
{
2417
        struct atafb_par par;
2418
        int err;
2419
        // Get fix directly (case con == -1 before)??
2420
        err = fbhw->decode_var(&info->var, &par);
2421
        if (err)
2422
                return err;
2423
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2424
        return fbhw->encode_fix(fix, &par);
2425
}
2426
 
2427
static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2428
{
2429
        struct atafb_par par;
2430
 
2431
        ata_get_par(&par);
2432
        fbhw->encode_var(var, &par);
2433
 
2434
        return 0;
2435
}
2436
 
2437
// No longer called by fbcon!
2438
// Still called by set_var internally
2439
 
2440
static void atafb_set_disp(struct fb_info *info)
2441
{
2442
        atafb_get_var(&info->var, info);
2443
        atafb_get_fix(&info->fix, info);
2444
 
2445
        info->screen_base = (void *)info->fix.smem_start;
2446
 
2447
        switch (info->fix.type) {
2448
        case FB_TYPE_INTERLEAVED_PLANES:
2449
                switch (info->var.bits_per_pixel) {
2450
                case 2:
2451
                        // display->dispsw = &fbcon_iplan2p2;
2452
                        break;
2453
                case 4:
2454
                        // display->dispsw = &fbcon_iplan2p4;
2455
                        break;
2456
                case 8:
2457
                        // display->dispsw = &fbcon_iplan2p8;
2458
                        break;
2459
                }
2460
                break;
2461
        case FB_TYPE_PACKED_PIXELS:
2462
                switch (info->var.bits_per_pixel) {
2463
#ifdef FBCON_HAS_MFB
2464
                case 1:
2465
                        // display->dispsw = &fbcon_mfb;
2466
                        break;
2467
#endif
2468
#ifdef FBCON_HAS_CFB8
2469
                case 8:
2470
                        // display->dispsw = &fbcon_cfb8;
2471
                        break;
2472
#endif
2473
#ifdef FBCON_HAS_CFB16
2474
                case 16:
2475
                        // display->dispsw = &fbcon_cfb16;
2476
                        // display->dispsw_data = fbcon_cfb16_cmap;
2477
                        break;
2478
#endif
2479
                }
2480
                break;
2481
        }
2482
}
2483
 
2484
static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2485
                           u_int transp, struct fb_info *info)
2486
{
2487
        red >>= 8;
2488
        green >>= 8;
2489
        blue >>= 8;
2490
 
2491
        return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
2492
}
2493
 
2494
static int
2495
atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2496
{
2497
        int xoffset = var->xoffset;
2498
        int yoffset = var->yoffset;
2499
        int err;
2500
 
2501
        if (var->vmode & FB_VMODE_YWRAP) {
2502
                if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2503
                        return -EINVAL;
2504
        } else {
2505
                if (xoffset + info->var.xres > info->var.xres_virtual ||
2506
                    yoffset + info->var.yres > info->var.yres_virtual)
2507
                        return -EINVAL;
2508
        }
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
 
2525
        return 0;
2526
}
2527
 
2528
/*
2529
 * generic drawing routines; imageblit needs updating for image depth > 1
2530
 */
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
2541
 
2542
 
2543
static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2544
{
2545
        struct atafb_par *par = (struct atafb_par *)info->par;
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);
2572
        else
2573
                atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2574
                                        rect->dy, rect->dx, height, width);
2575
 
2576
        return;
2577
}
2578
 
2579
static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2580
{
2581
        struct atafb_par *par = (struct atafb_par *)info->par;
2582
        int x2, y2;
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;
2604
 
2605
        if (dy > sy || (dy == sy && dx > sx)) {
2606
                dy += height;
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);
2619
 
2620
        return;
2621
}
2622
 
2623
static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2624
{
2625
        struct atafb_par *par = (struct atafb_par *)info->par;
2626
        int x2, y2;
2627
        unsigned long *dst;
2628
        int dst_idx;
2629
        const char *src;
2630
        u32 dx, dy, width, height, pitch;
2631
 
2632
        /*
2633
         * We could use hardware clipping but on many cards you get around
2634
         * hardware clipping by writing to framebuffer directly like we are
2635
         * doing here.
2636
         */
2637
        x2 = image->dx + image->width;
2638
        y2 = image->dy + image->height;
2639
        dx = image->dx;
2640
        dy = image->dy;
2641
        x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2642
        y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2643
        width = x2 - dx;
2644
        height = y2 - dy;
2645
 
2646
        if (image->depth == 1) {
2647
                // used for font data
2648
                dst = (unsigned long *)
2649
                        ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2650
                dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2651
                dst_idx += dy * par->next_line * 8 + dx;
2652
                src = image->data;
2653
                pitch = (image->width + 7) / 8;
2654
                while (height--) {
2655
 
2656
                        if (info->var.bits_per_pixel == 1)
2657
                                atafb_mfb_linefill(info, par->next_line,
2658
                                                   dy, dx, width, src,
2659
                                                   image->bg_color, image->fg_color);
2660
                        else if (info->var.bits_per_pixel == 2)
2661
                                atafb_iplan2p2_linefill(info, par->next_line,
2662
                                                        dy, dx, width, src,
2663
                                                        image->bg_color, image->fg_color);
2664
                        else if (info->var.bits_per_pixel == 4)
2665
                                atafb_iplan2p4_linefill(info, par->next_line,
2666
                                                        dy, dx, width, src,
2667
                                                        image->bg_color, image->fg_color);
2668
                        else
2669
                                atafb_iplan2p8_linefill(info, par->next_line,
2670
                                                        dy, dx, width, src,
2671
                                                        image->bg_color, image->fg_color);
2672
                        dy++;
2673
                        src += pitch;
2674
                }
2675
        } else {
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);
2680
        }
2681
}
2682
 
2683
static int
2684
atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2685
{
2686
        switch (cmd) {
2687
#ifdef FBCMD_GET_CURRENTPAR
2688
        case FBCMD_GET_CURRENTPAR:
2689
                if (copy_to_user((void *)arg, (void *)&current_par,
2690
                                 sizeof(struct atafb_par)))
2691
                        return -EFAULT;
2692
                return 0;
2693
#endif
2694
#ifdef FBCMD_SET_CURRENTPAR
2695
        case FBCMD_SET_CURRENTPAR:
2696
                if (copy_from_user((void *)&current_par, (void *)arg,
2697
                                   sizeof(struct atafb_par)))
2698
                        return -EFAULT;
2699
                ata_set_par(&current_par);
2700
                return 0;
2701
#endif
2702
        }
2703
        return -EINVAL;
2704
}
2705
 
2706
/* (un)blank/poweroff
2707
 * 0 = unblank
2708
 * 1 = blank
2709
 * 2 = suspend vsync
2710
 * 3 = suspend hsync
2711
 * 4 = off
2712
 */
2713
static int atafb_blank(int blank, struct fb_info *info)
2714
{
2715
        unsigned short black[16];
2716
        struct fb_cmap cmap;
2717
        if (fbhw->blank && !fbhw->blank(blank))
2718
                return 1;
2719
        if (blank) {
2720
                memset(black, 0, 16 * sizeof(unsigned short));
2721
                cmap.red = black;
2722
                cmap.green = black;
2723
                cmap.blue = black;
2724
                cmap.transp = NULL;
2725
                cmap.start = 0;
2726
                cmap.len = 16;
2727
                fb_set_cmap(&cmap, info);
2728
        }
2729
#if 0
2730
        else
2731
                do_install_cmap(info);
2732
#endif
2733
        return 0;
2734
}
2735
 
2736
        /*
2737
         * New fbcon interface ...
2738
         */
2739
 
2740
         /* check var by decoding var into hw par, rounding if necessary,
2741
          * then encoding hw par back into new, validated var */
2742
static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2743
{
2744
        int err;
2745
        struct atafb_par par;
2746
 
2747
        /* Validate wanted screen parameters */
2748
        // if ((err = ata_decode_var(var, &par)))
2749
        err = fbhw->decode_var(var, &par);
2750
        if (err)
2751
                return err;
2752
 
2753
        /* Encode (possibly rounded) screen parameters */
2754
        fbhw->encode_var(var, &par);
2755
        return 0;
2756
}
2757
 
2758
        /* actually set hw par by decoding var, then setting hardware from
2759
         * hw par just decoded */
2760
static int atafb_set_par(struct fb_info *info)
2761
{
2762
        struct atafb_par *par = (struct atafb_par *)info->par;
2763
 
2764
        /* Decode wanted screen parameters */
2765
        fbhw->decode_var(&info->var, par);
2766
        fbhw->encode_fix(&info->fix, par);
2767
 
2768
        /* Set new videomode */
2769
        ata_set_par(par);
2770
 
2771
        return 0;
2772
}
2773
 
2774
 
2775
static struct fb_ops atafb_ops = {
2776
        .owner =        THIS_MODULE,
2777
        .fb_check_var   = atafb_check_var,
2778
        .fb_set_par     = atafb_set_par,
2779
        .fb_setcolreg   = atafb_setcolreg,
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,
2785
        .fb_ioctl =     atafb_ioctl,
2786
};
2787
 
2788
static void check_default_par(int detected_mode)
2789
{
2790
        char default_name[10];
2791
        int i;
2792
        struct fb_var_screeninfo var;
2793
        unsigned long min_mem;
2794
 
2795
        /* First try the user supplied mode */
2796
        if (default_par) {
2797
                var = atafb_predefined[default_par - 1];
2798
                var.activate = FB_ACTIVATE_TEST;
2799
                if (do_fb_set_var(&var, 1))
2800
                        default_par = 0; /* failed */
2801
        }
2802
        /* Next is the autodetected one */
2803
        if (!default_par) {
2804
                var = atafb_predefined[detected_mode - 1]; /* autodetect */
2805
                var.activate = FB_ACTIVATE_TEST;
2806
                if (!do_fb_set_var(&var, 1))
2807
                        default_par = detected_mode;
2808
        }
2809
        /* If that also failed, try some default modes... */
2810
        if (!default_par) {
2811
                /* try default1, default2... */
2812
                for (i = 1; i < 10; i++) {
2813
                        sprintf(default_name,"default%d", i);
2814
                        default_par = get_video_mode(default_name);
2815
                        if (!default_par)
2816
                                panic("can't set default video mode");
2817
                        var = atafb_predefined[default_par - 1];
2818
                        var.activate = FB_ACTIVATE_TEST;
2819
                        if (!do_fb_set_var(&var,1))
2820
                                break;  /* ok */
2821
                }
2822
        }
2823
        min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2824
        if (default_mem_req < min_mem)
2825
                default_mem_req = min_mem;
2826
}
2827
 
2828
#ifdef ATAFB_EXT
2829
static void __init atafb_setup_ext(char *spec)
2830
{
2831
        int xres, xres_virtual, yres, depth, planes;
2832
        unsigned long addr, len;
2833
        char *p;
2834
 
2835
        /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2836
         *            <screen mem addr>
2837
         *            [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2838
         *            [;<xres-virtual>]]]]]
2839
         *
2840
         * 09/23/97     Juergen
2841
         * <xres_virtual>:      hardware's x-resolution (f.e. ProMST)
2842
         *
2843
         * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2844
         */
2845
        p = strsep(&spec, ";");
2846
        if (!p || !*p)
2847
                return;
2848
        xres_virtual = xres = simple_strtoul(p, NULL, 10);
2849
        if (xres <= 0)
2850
                return;
2851
 
2852
        p = strsep(&spec, ";");
2853
        if (!p || !*p)
2854
                return;
2855
        yres = simple_strtoul(p, NULL, 10);
2856
        if (yres <= 0)
2857
                return;
2858
 
2859
        p = strsep(&spec, ";");
2860
        if (!p || !*p)
2861
                return;
2862
        depth = simple_strtoul(p, NULL, 10);
2863
        if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2864
            depth != 16 && depth != 24)
2865
                return;
2866
 
2867
        p = strsep(&spec, ";");
2868
        if (!p || !*p)
2869
                return;
2870
        if (*p == 'i')
2871
                planes = FB_TYPE_INTERLEAVED_PLANES;
2872
        else if (*p == 'p')
2873
                planes = FB_TYPE_PACKED_PIXELS;
2874
        else if (*p == 'n')
2875
                planes = FB_TYPE_PLANES;
2876
        else if (*p == 't')
2877
                planes = -1;            /* true color */
2878
        else
2879
                return;
2880
 
2881
        p = strsep(&spec, ";");
2882
        if (!p || !*p)
2883
                return;
2884
        addr = simple_strtoul(p, NULL, 0);
2885
 
2886
        p = strsep(&spec, ";");
2887
        if (!p || !*p)
2888
                len = xres * yres * depth / 8;
2889
        else
2890
                len = simple_strtoul(p, NULL, 0);
2891
 
2892
        p = strsep(&spec, ";");
2893
        if (p && *p)
2894
                external_vgaiobase = simple_strtoul(p, NULL, 0);
2895
 
2896
        p = strsep(&spec, ";");
2897
        if (p && *p) {
2898
                external_bitspercol = simple_strtoul(p, NULL, 0);
2899
                if (external_bitspercol > 8)
2900
                        external_bitspercol = 8;
2901
                else if (external_bitspercol < 1)
2902
                        external_bitspercol = 1;
2903
        }
2904
 
2905
        p = strsep(&spec, ";");
2906
        if (p && *p) {
2907
                if (!strcmp(p, "vga"))
2908
                        external_card_type = IS_VGA;
2909
                if (!strcmp(p, "mv300"))
2910
                        external_card_type = IS_MV300;
2911
        }
2912
 
2913
        p = strsep(&spec, ";");
2914
        if (p && *p) {
2915
                xres_virtual = simple_strtoul(p, NULL, 10);
2916
                if (xres_virtual < xres)
2917
                        xres_virtual = xres;
2918
                if (xres_virtual * yres * depth / 8 > len)
2919
                        len = xres_virtual * yres * depth / 8;
2920
        }
2921
 
2922
        external_xres = xres;
2923
        external_xres_virtual = xres_virtual;
2924
        external_yres = yres;
2925
        external_depth = depth;
2926
        external_pmode = planes;
2927
        external_addr = (void *)addr;
2928
        external_len = len;
2929
 
2930
        if (external_card_type == IS_MV300) {
2931
                switch (external_depth) {
2932
                case 1:
2933
                        MV300_reg = MV300_reg_1bit;
2934
                        break;
2935
                case 4:
2936
                        MV300_reg = MV300_reg_4bit;
2937
                        break;
2938
                case 8:
2939
                        MV300_reg = MV300_reg_8bit;
2940
                        break;
2941
                }
2942
        }
2943
}
2944
#endif /* ATAFB_EXT */
2945
 
2946
static void __init atafb_setup_int(char *spec)
2947
{
2948
        /* Format to config extended internal video hardware like OverScan:
2949
         * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2950
         * Explanation:
2951
         * <xres>: x-resolution
2952
         * <yres>: y-resolution
2953
         * The following are only needed if you have an overscan which
2954
         * needs a black border:
2955
         * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2956
         * <yres_max>: max. number of lines your OverScan hardware would allow
2957
         * <offset>: Offset from physical beginning to visible beginning
2958
         *        of screen in bytes
2959
         */
2960
        int xres;
2961
        char *p;
2962
 
2963
        if (!(p = strsep(&spec, ";")) || !*p)
2964
                return;
2965
        xres = simple_strtoul(p, NULL, 10);
2966
        if (!(p = strsep(&spec, ";")) || !*p)
2967
                return;
2968
        sttt_xres = xres;
2969
        tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2970
        if ((p = strsep(&spec, ";")) && *p)
2971
                sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2972
        if ((p = strsep(&spec, ";")) && *p)
2973
                sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2974
        if ((p = strsep(&spec, ";")) && *p)
2975
                ovsc_offset = simple_strtoul(p, NULL, 0);
2976
 
2977
        if (ovsc_offset || (sttt_yres_virtual != st_yres))
2978
                use_hwscroll = 0;
2979
}
2980
 
2981
#ifdef ATAFB_FALCON
2982
static void __init atafb_setup_mcap(char *spec)
2983
{
2984
        char *p;
2985
        int vmin, vmax, hmin, hmax;
2986
 
2987
        /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2988
         * <V*> vertical freq. in Hz
2989
         * <H*> horizontal freq. in kHz
2990
         */
2991
        if (!(p = strsep(&spec, ";")) || !*p)
2992
                return;
2993
        vmin = simple_strtoul(p, NULL, 10);
2994
        if (vmin <= 0)
2995
                return;
2996
        if (!(p = strsep(&spec, ";")) || !*p)
2997
                return;
2998
        vmax = simple_strtoul(p, NULL, 10);
2999
        if (vmax <= 0 || vmax <= vmin)
3000
                return;
3001
        if (!(p = strsep(&spec, ";")) || !*p)
3002
                return;
3003
        hmin = 1000 * simple_strtoul(p, NULL, 10);
3004
        if (hmin <= 0)
3005
                return;
3006
        if (!(p = strsep(&spec, "")) || !*p)
3007
                return;
3008
        hmax = 1000 * simple_strtoul(p, NULL, 10);
3009
        if (hmax <= 0 || hmax <= hmin)
3010
                return;
3011
 
3012
        fb_info.monspecs.vfmin = vmin;
3013
        fb_info.monspecs.vfmax = vmax;
3014
        fb_info.monspecs.hfmin = hmin;
3015
        fb_info.monspecs.hfmax = hmax;
3016
}
3017
#endif /* ATAFB_FALCON */
3018
 
3019
static void __init atafb_setup_user(char *spec)
3020
{
3021
        /* Format of user defined video mode is: <xres>;<yres>;<depth>
3022
         */
3023
        char *p;
3024
        int xres, yres, depth, temp;
3025
 
3026
        p = strsep(&spec, ";");
3027
        if (!p || !*p)
3028
                return;
3029
        xres = simple_strtoul(p, NULL, 10);
3030
        p = strsep(&spec, ";");
3031
        if (!p || !*p)
3032
                return;
3033
        yres = simple_strtoul(p, NULL, 10);
3034
        p = strsep(&spec, "");
3035
        if (!p || !*p)
3036
                return;
3037
        depth = simple_strtoul(p, NULL, 10);
3038
        temp = get_video_mode("user0");
3039
        if (temp) {
3040
                default_par = temp;
3041
                atafb_predefined[default_par - 1].xres = xres;
3042
                atafb_predefined[default_par - 1].yres = yres;
3043
                atafb_predefined[default_par - 1].bits_per_pixel = depth;
3044
        }
3045
}
3046
 
3047
int __init atafb_setup(char *options)
3048
{
3049
        char *this_opt;
3050
        int temp;
3051
 
3052
        if (!options || !*options)
3053
                return 0;
3054
 
3055
        while ((this_opt = strsep(&options, ",")) != NULL) {
3056
                if (!*this_opt)
3057
                        continue;
3058
                if ((temp = get_video_mode(this_opt))) {
3059
                        default_par = temp;
3060
                        mode_option = this_opt;
3061
                } else if (!strcmp(this_opt, "inverse"))
3062
                        inverse = 1;
3063
                else if (!strncmp(this_opt, "hwscroll_", 9)) {
3064
                        hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3065
                        if (hwscroll < 0)
3066
                                hwscroll = 0;
3067
                        if (hwscroll > 200)
3068
                                hwscroll = 200;
3069
                }
3070
#ifdef ATAFB_EXT
3071
                else if (!strcmp(this_opt, "mv300")) {
3072
                        external_bitspercol = 8;
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);
3092
        }
3093
        return 0;
3094
}
3095
 
3096
int __init atafb_init(void)
3097
{
3098
        int pad;
3099
        int detected_mode;
3100
        unsigned int defmode = 0;
3101
        unsigned long mem_req;
3102
 
3103
#ifndef MODULE
3104
        char *option = NULL;
3105
 
3106
        if (fb_get_options("atafb", &option))
3107
                return -ENODEV;
3108
        atafb_setup(option);
3109
#endif
3110
        printk("atafb_init: start\n");
3111
 
3112
        if (!MACH_IS_ATARI)
3113
                return -ENXIO;
3114
 
3115
        do {
3116
#ifdef ATAFB_EXT
3117
                if (external_addr) {
3118
                        printk("atafb_init: initializing external hw\n");
3119
                        fbhw = &ext_switch;
3120
                        atafb_ops.fb_setcolreg = &ext_setcolreg;
3121
                        defmode = DEFMODE_EXT;
3122
                        break;
3123
                }
3124
#endif
3125
#ifdef ATAFB_TT
3126
                if (ATARIHW_PRESENT(TT_SHIFTER)) {
3127
                        printk("atafb_init: initializing TT hw\n");
3128
                        fbhw = &tt_switch;
3129
                        atafb_ops.fb_setcolreg = &tt_setcolreg;
3130
                        defmode = DEFMODE_TT;
3131
                        break;
3132
                }
3133
#endif
3134
#ifdef ATAFB_FALCON
3135
                if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3136
                        printk("atafb_init: initializing Falcon hw\n");
3137
                        fbhw = &falcon_switch;
3138
                        atafb_ops.fb_setcolreg = &falcon_setcolreg;
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;
3171
        }
3172
 
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
                }
3255
#endif
3256
                return -EINVAL;
3257
        }
3258
 
3259
        // FIXME: mode needs setting!
3260
        //printk("fb%d: %s frame buffer device, using %dK of video memory\n",
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;
3267
}
3268
 
3269
module_init(atafb_init);
3270
 
3271
#ifdef MODULE
3272
MODULE_LICENSE("GPL");
3273
 
3274
int cleanup_module(void)
3275
{
3276
        unregister_framebuffer(&fb_info);
3277
        return atafb_deinit();
3278
}
3279
#endif /* MODULE */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.