ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / video / 68328fb.c
1 /*
2  * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the
3  *                                           mc68328 LCD frame buffer device
4  *
5  *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
6  *                            The Silver Hammer Group, Ltd.
7  *
8  *
9  * This file is based on the Amiga CyberVision frame buffer device (Cyberfb.c):
10  *
11  *    Copyright (C) 1996 Martin Apel
12  *                       Geert Uytterhoeven
13  *
14  *
15  * This file is based on the Amiga frame buffer device (amifb.c):
16  *
17  *    Copyright (C) 1995 Geert Uytterhoeven
18  *
19  *
20  * History:
21  *   - 17 Feb 98: Original version by Kenneth Albanowski <kjahds@kjahds.com>
22  *
23  *
24  * This file is subject to the terms and conditions of the GNU General Public
25  * License.  See the file COPYING in the main directory of this archive
26  * for more details.
27  */
28
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/errno.h>
32 #include <linux/string.h>
33 #include <linux/mm.h>
34 #include <linux/tty.h>
35 #include <linux/slab.h>
36 #include <linux/delay.h>
37 #include <linux/config.h>
38 #include <asm/segment.h>
39 #include <asm/system.h>
40 #include <asm/irq.h>
41 #include <asm/pgtable.h>
42 #include <linux/fb.h>
43
44 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
45
46 static struct fb_info fb_info;
47
48    /*
49     *    mc68328vision Graphics Board
50     */
51
52 #define CYBER8_WIDTH 1152
53 #define CYBER8_HEIGHT 886
54 #define CYBER8_PIXCLOCK 12500   /* ++Geert: Just a guess */
55
56 #define CYBER16_WIDTH 800
57 #define CYBER16_HEIGHT 600
58 #define CYBER16_PIXCLOCK 25000  /* ++Geert: Just a guess */
59
60 #define PALM_WIDTH 160
61 #define PALM_HEIGHT 160
62
63 /*static int mc68328Key = 0;
64 static u_char mc68328_colour_table [256][4];*/
65
66    /*
67     *    Predefined Video Mode Names
68     */
69
70 static char *mc68328_fb_modenames[] = {
71
72         /*
73          *    Autodetect (Default) Video Mode
74          */
75
76         "default",
77
78         /*
79          *    Predefined Video Modes
80          */
81
82         "Palm",                 /* Palm Pilot devices, 1.0 and higher */
83         "Palm Grey",            /* Palm Pilot devices, 1.0 and higher */
84
85         /*
86          *    Dummy Video Modes
87          */
88
89         "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
90             "dummy",
91         "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
92             "dummy",
93         "dummy", "dummy", "dummy", "dummy",
94
95         /*
96          *    User Defined Video Modes
97          *
98          *    This doesn't work yet!!
99          */
100
101         "user0", "user1", "user2", "user3", "user4", "user5", "user6",
102             "user7"
103 };
104
105
106    /*
107     *    Predefined Video Mode Definitions
108     */
109
110 static struct fb_var_screeninfo mc68328_fb_predefined[] = {
111
112         /*
113          *    Autodetect (Default) Video Mode
114          */
115
116         {0,},
117
118         /*
119          *    Predefined Video Modes
120          */
121
122         {
123          /* Palm */
124          PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
125          0, 0,
126          1, -1,
127          {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
128          0, 0,
129          -1, -1,                /* phys height, width */
130          FB_ACCEL_NONE,
131          0, 0, 0, 0, 0, 0, 0,   /* timing */
132          0,                     /* sync */
133          FB_VMODE_NONINTERLACED},
134         {
135          /* Palm Grey */
136          PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
137          0, 0,
138          2, -1,
139          {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
140          0, 0,
141          -1, -1,                /* phys height, width */
142          FB_ACCEL_NONE,
143          0, 0, 0, 0, 0, 0, 0,   /* timing */
144          0,                     /* sync */
145          FB_VMODE_NONINTERLACED},
146
147         /*
148          *    Dummy Video Modes
149          */
150
151         {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
152         {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
153         {0,}, {0,},
154
155         /*
156          *    User Defined Video Modes
157          */
158
159         {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}
160 };
161
162 static struct fb_fix_screeninfo mc68328_fix __initdata = {
163         .id             = "mc68328";
164         .smem_len       = 160 * 160 /8;
165         .type           = FB_TYPE_PACKED_PIXELS;
166         .accel          = FB_ACCEL_NONE;
167 };
168
169 #define NUM_TOTAL_MODES    arraysize(mc68328_fb_predefined)
170 #define NUM_PREDEF_MODES   (3)
171
172 static int mc68328fb_inverse = 0;
173 static int mc68328fb_mode = 0;
174 static int mc68328fbCursorMode = 0;
175
176    /*
177     *    Some default modes
178     */
179
180 #define PALM_DEFMODE     (1)
181 #define CYBER16_DEFMODE    (2)
182
183    /*
184     *    Interface used by the world
185     */
186 int mc68328_fb_init(void);
187
188 static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
189                                u_int blue, u_int transp);
190 static void mc68328fb_blank(int blank, struct fb_info *info);
191
192    /*
193     *    Accelerated Functions used by the low level console driver
194     */
195
196 void mc68328_WaitQueue(u_short fifo);
197 void mc68328_WaitBlit(void);
198 void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
199                     u_short desty, u_short width, u_short height,
200                     u_short mode);
201 void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
202                       u_short mode, u_short color);
203 void mc68328_MoveCursor(u_short x, u_short y);
204
205    /*
206     *    Internal routines
207     */
208 static int get_video_mode(const char *name);
209
210    /*
211     *    Set a single color register. The values supplied are already
212     *    rounded down to the hardware's capabilities (according to the
213     *    entries in the var structure). Return != 0 for invalid regno.
214     */
215
216 static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
217                                u_int blue, u_int transp)
218 {
219         return 1;
220 #if 0
221         if (regno > 255)
222                 return (1);
223
224         *(mc68328Regs + 0x3c8) = (char) regno;
225         mc68328_colour_table[regno][0] = red & 0xff;
226         mc68328_colour_table[regno][1] = green & 0xff;
227         mc68328_colour_table[regno][2] = blue & 0xff;
228         mc68328_colour_table[regno][3] = transp;
229
230         *(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
231         *(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
232         *(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
233
234         return (0);
235 #endif
236 }
237
238    /*
239     *    (Un)Blank the screen
240     */
241
242 static void mc68328fb_blank(int blank, struct fb_info *info)
243 {
244 #if 0
245         if (blank)
246                 (*(volatile unsigned char *) 0xFFFFFA27) &= ~128;
247         else
248                 (*(volatile unsigned char *) 0xFFFFFA27) |= 128;
249 #endif
250 }
251
252
253 /**************************************************************
254  * We are waiting for "fifo" FIFO-slots empty
255  */
256 void mc68328_WaitQueue(u_short fifo)
257 {
258 }
259
260 /**************************************************************
261  * We are waiting for Hardware (Graphics Engine) not busy
262  */
263 void mc68328_WaitBlit(void)
264 {
265 }
266
267 /**************************************************************
268  * BitBLT - Through the Plane
269  */
270 void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
271                     u_short desty, u_short width, u_short height,
272                     u_short mode)
273 {
274 #if 0
275         u_short blitcmd = S3_BITBLT;
276
277 /* Set drawing direction */
278 /* -Y, X maj, -X (default) */
279         if (curx > destx)
280                 blitcmd |= 0x0020;      /* Drawing direction +X */
281         else {
282                 curx += (width - 1);
283                 destx += (width - 1);
284         }
285
286         if (cury > desty)
287                 blitcmd |= 0x0080;      /* Drawing direction +Y */
288         else {
289                 cury += (height - 1);
290                 desty += (height - 1);
291         }
292
293         mc68328_WaitQueue(0x8000);
294
295         *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
296         *((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
297             (0x0060 | mode);
298
299         *((u_short volatile *) (mc68328Regs + S3_CUR_X)) = curx;
300         *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = cury;
301
302         *((u_short volatile *) (mc68328Regs + S3_DESTX_DIASTP)) = destx;
303         *((u_short volatile *) (mc68328Regs + S3_DESTY_AXSTP)) = desty;
304
305         *((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
306             height - 1;
307         *((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
308             width - 1;
309
310         *((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
311 #endif
312 }
313
314 /**************************************************************
315  * Rectangle Fill Solid
316  */
317 void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
318                       u_short mode, u_short color)
319 {
320 #if 0
321         u_short blitcmd = S3_FILLEDRECT;
322
323         mc68328_WaitQueue(0x8000);
324
325         *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
326         *((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
327             (0x0020 | mode);
328
329         *((u_short volatile *) (mc68328Regs + S3_MULT_MISC)) = 0xe000;
330         *((u_short volatile *) (mc68328Regs + S3_FRGD_COLOR)) = color;
331
332         *((u_short volatile *) (mc68328Regs + S3_CUR_X)) = x;
333         *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = y;
334
335         *((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
336             height - 1;
337         *((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
338             width - 1;
339
340         *((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
341 #endif
342 }
343
344
345 /**************************************************************
346  * Move cursor to x, y
347  */
348 void mc68328_MoveCursor(u_short x, u_short y)
349 {
350         (*(volatile unsigned short *) 0xFFFFFA18) =
351             (mc68328fbCursorMode << 14) | x;
352         (*(volatile unsigned short *) 0xFFFFFA1A) = y;
353 #if 0
354         *(mc68328Regs + S3_CRTC_ADR) = 0x39;
355         *(mc68328Regs + S3_CRTC_DATA) = 0xa0;
356
357         *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
358         *(mc68328Regs + S3_CRTC_DATA) = (char) ((x & 0x0700) >> 8);
359         *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
360         *(mc68328Regs + S3_CRTC_DATA) = (char) (x & 0x00ff);
361
362         *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
363         *(mc68328Regs + S3_CRTC_DATA) = (char) ((y & 0x0700) >> 8);
364         *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
365         *(mc68328Regs + S3_CRTC_DATA) = (char) (y & 0x00ff);
366 #endif
367 }
368
369 /* -------------------- Generic routines ------------------------------------ */
370
371    /*
372     *    Default Colormaps
373     */
374
375 static u_short red16[] =
376     { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
377         0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff
378 };
379 static u_short green16[] =
380     { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
381         0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff
382 };
383 static u_short blue16[] =
384     { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
385         0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff
386 };
387
388
389 static struct fb_cmap default_16_colors =
390     { 0, 16, red16, green16, blue16, NULL };
391
392
393 static struct fb_cmap *get_default_colormap(int bpp)
394 {
395         return (&default_16_colors);
396 }
397
398
399 #define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
400 #define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
401                                               ((1<<(width))-1)) : 0))
402
403 static struct fb_ops mc68328_fb_ops = {
404         .owner          = THIS_MODULE,
405         .fb_setcolreg   = mc68328fb_setcolreg,
406         .fb_fillrect    = cfbfillrect,
407         .fb_copyarea    = cfbcopyarea,
408         .fb_imageblit   = cfbimgblt,
409         .fb_cursor      = softcursor,
410 };
411
412
413    /*
414     *    Initialization
415     */
416
417 int __init mc68328_fb_init(void)
418 {
419         if (mc68328fb_mode == -1)
420                 mc68328fb_mode = PALM_DEFMODE;
421         mc68328_fix.smem_start = (*(volatile unsigned long *) 0xFFFFFA00);
422         /*kernel_map (board_addr + 0x01400000, 0x00400000, */
423         
424         info->var = mc68328_fb_predefined[mc68328fb_mode];
425         
426         if (info->var.bits_per_pixel == 1)
427                 fix->visual = FB_VISUAL_MONO01;
428         else
429                 fix->visual = FB_VISUAL_DIRECTCOLOR;
430         info->screen_base = (u_char *) mc68328_fix.smem_start;
431         
432         if (register_framebuffer(&fb_info) < 0)
433                 panic("Cannot register frame buffer\n");
434         return 0;
435 }
436
437    /*
438     *    Get a Video Mode
439     */
440
441 static int get_video_mode(const char *name)
442 {
443         int i;
444
445         for (i = 1; i < NUM_PREDEF_MODES; i++)
446                 if (!strcmp(name, mc68328_fb_modenames[i]))
447                         return (i);
448         return (0);
449 }