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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68knommu/] [console/] [68328fb.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1625 jcastillo
/*
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
 
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/malloc.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
 
45
#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
46
 
47
struct mc68328_fb_par {
48
   int xres;
49
   int yres;
50
   int bpp;
51
};
52
 
53
static struct mc68328_fb_par current_par;
54
 
55
static int current_par_valid = 0;
56
static int currcon = 0;
57
 
58
static struct display disp[MAX_NR_CONSOLES];
59
static struct fb_info fb_info;
60
 
61
static int node;        /* node of the /dev/fb?current file */
62
 
63
 
64
   /*
65
    *    Switch for Chipset Independency
66
    */
67
 
68
static struct fb_hwswitch {
69
 
70
   /* Initialisation */
71
 
72
   int (*init)(void);
73
 
74
   /* Display Control */
75
 
76
   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par);
77
   int (*decode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
78
   int (*encode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
79
   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
80
                    u_int *transp);
81
   int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
82
                    u_int transp);
83
   void (*blank)(int blank);
84
} *fbhw;
85
 
86
 
87
   /*
88
    *    Frame Buffer Name
89
    */
90
 
91
static char mc68328_fb_name[16] = "mc68328";
92
 
93
 
94
   /*
95
    *    mc68328vision Graphics Board
96
    */
97
 
98
#define CYBER8_WIDTH 1152
99
#define CYBER8_HEIGHT 886
100
#define CYBER8_PIXCLOCK 12500    /* ++Geert: Just a guess */
101
 
102
#define CYBER16_WIDTH 800
103
#define CYBER16_HEIGHT 600
104
#define CYBER16_PIXCLOCK 25000   /* ++Geert: Just a guess */
105
 
106
#define PALM_WIDTH 160
107
#define PALM_HEIGHT 160
108
 
109
 
110
/*static int mc68328Key = 0;
111
static u_char mc68328_colour_table [256][4];*/
112
static unsigned long mc68328Mem;
113
static unsigned long mc68328Size;
114
 
115
static long *memstart;
116
 
117
 
118
   /*
119
    *    Predefined Video Mode Names
120
    */
121
 
122
static char *mc68328_fb_modenames[] = {
123
 
124
   /*
125
    *    Autodetect (Default) Video Mode
126
    */
127
 
128
   "default",
129
 
130
   /*
131
    *    Predefined Video Modes
132
    */
133
 
134
   "Palm",            /* Palm Pilot devices, 1.0 and higher */
135
   "Palm Grey",            /* Palm Pilot devices, 1.0 and higher */
136
 
137
   /*
138
    *    Dummy Video Modes
139
    */
140
 
141
   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
142
   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
143
   "dummy", "dummy", "dummy", "dummy",
144
 
145
   /*
146
    *    User Defined Video Modes
147
    *
148
    *    This doesn't work yet!!
149
    */
150
 
151
   "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
152
};
153
 
154
 
155
   /*
156
    *    Predefined Video Mode Definitions
157
    */
158
 
159
static struct fb_var_screeninfo mc68328_fb_predefined[] = {
160
 
161
   /*
162
    *    Autodetect (Default) Video Mode
163
    */
164
 
165
   { 0, },
166
 
167
   /*
168
    *    Predefined Video Modes
169
    */
170
 
171
   {
172
      /* Palm */
173
      PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
174
      0, 0,
175
      1, -1,
176
      {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
177
      0, 0,
178
      -1, -1, /* phys height, width */
179
      FB_ACCEL_NONE,
180
      0, 0, 0, 0, 0, 0, 0, /* timing */
181
      0, /* sync */
182
      FB_VMODE_NONINTERLACED
183
   },
184
   {
185
      /* Palm Grey */
186
      PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
187
      0, 0,
188
      2, -1,
189
      {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
190
      0, 0,
191
      -1, -1, /* phys height, width */
192
      FB_ACCEL_NONE,
193
      0, 0, 0, 0, 0, 0, 0, /* timing */
194
      0, /* sync */
195
      FB_VMODE_NONINTERLACED
196
   },
197
 
198
   /*
199
    *    Dummy Video Modes
200
    */
201
 
202
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
203
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
204
   { 0, }, { 0, },
205
 
206
   /*
207
    *    User Defined Video Modes
208
    */
209
 
210
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
211
};
212
 
213
 
214
#define NUM_TOTAL_MODES    arraysize(mc68328_fb_predefined)
215
#define NUM_PREDEF_MODES   (3)
216
 
217
 
218
static int mc68328fb_inverse = 0;
219
static int mc68328fb_mode = 0;
220
static int mc68328fbCursorMode = 0;
221
 
222
 
223
   /*
224
    *    Some default modes
225
    */
226
 
227
#define PALM_DEFMODE     (1)
228
#define CYBER16_DEFMODE    (2)
229
 
230
 
231
   /*
232
    *    Interface used by the world
233
    */
234
 
235
void mc68328_video_setup(char *options, int *ints);
236
 
237
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
238
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con);
239
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con);
240
static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
241
static int mc68328_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
242
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con);
243
static int mc68328_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
244
                          u_long arg, int con);
245
 
246
 
247
   /*
248
    *    Interface to the low level console driver
249
    */
250
 
251
struct fb_info *mc68328_fb_init(long *mem_start); /* Through amiga_fb_init() */
252
static int mc68328fb_switch(int con);
253
static int mc68328fb_updatevar(int con);
254
static void mc68328fb_blank(int blank);
255
 
256
 
257
   /*
258
    *    Accelerated Functions used by the low level console driver
259
    */
260
 
261
void mc68328_WaitQueue(u_short fifo);
262
void mc68328_WaitBlit(void);
263
void mc68328_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
264
                  u_short width, u_short height, u_short mode);
265
void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
266
                    u_short mode, u_short color);
267
void mc68328_MoveCursor(u_short x, u_short y);
268
 
269
 
270
   /*
271
    *   Hardware Specific Routines
272
    */
273
 
274
static int mc68328_init(void);
275
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
276
                          struct mc68328_fb_par *par);
277
static int mc68328_decode_var(struct fb_var_screeninfo *var,
278
                          struct mc68328_fb_par *par);
279
static int mc68328_encode_var(struct fb_var_screeninfo *var,
280
                          struct mc68328_fb_par *par);
281
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
282
                         u_int *transp);
283
static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
284
                         u_int transp);
285
static void mc68328_blank(int blank);
286
 
287
 
288
   /*
289
    *    Internal routines
290
    */
291
 
292
static void mc68328_fb_get_par(struct mc68328_fb_par *par);
293
static void mc68328_fb_set_par(struct mc68328_fb_par *par);
294
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
295
static struct fb_cmap *get_default_colormap(int bpp);
296
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
297
                          int kspc);
298
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
299
                          int kspc);
300
static void do_install_cmap(int con);
301
static void memcpy_fs(int fsfromto, void *to, void *from, int len);
302
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
303
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
304
static void mc68328_fb_set_disp(int con);
305
static int get_video_mode(const char *name);
306
 
307
 
308
/* -------------------- Hardware specific routines -------------------------- */
309
 
310
 
311
   /*
312
    *    Initialization
313
    *
314
    *    Set the default video mode for this chipset. If a video mode was
315
    *    specified on the command line, it will override the default mode.
316
    */
317
 
318
static int mc68328_init(void)
319
{
320
        /*int i;
321
        char size;
322
        volatile u_long *CursorBase;
323
        unsigned long board_addr;
324
        struct ConfigDev *cd;*/
325
 
326
        if (mc68328fb_mode == -1)
327
                mc68328fb_mode = PALM_DEFMODE;
328
 
329
        mc68328Mem = (*(volatile unsigned long*)0xFFFFFA00);
330
        /*kernel_map (board_addr + 0x01400000, 0x00400000,*/
331
        mc68328Size = 160*160/8;
332
 
333
        return (0);
334
}
335
 
336
 
337
   /*
338
    *    This function should fill in the `fix' structure based on the
339
    *    values in the `par' structure.
340
    */
341
 
342
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
343
                          struct mc68328_fb_par *par)
344
{
345
   int i;
346
 
347
   strcpy(fix->id, mc68328_fb_name);
348
   fix->smem_start = mc68328Mem;
349
   fix->smem_len = mc68328Size;
350
 
351
   fix->type = FB_TYPE_PACKED_PIXELS;
352
   fix->type_aux = 0;
353
   if (par->bpp == 1)
354
      fix->visual = FB_VISUAL_MONO01;
355
   else
356
      fix->visual = FB_VISUAL_DIRECTCOLOR;
357
 
358
   fix->xpanstep = 0;
359
   fix->ypanstep = 0;
360
   fix->ywrapstep = 0;
361
 
362
   for (i = 0; i < arraysize(fix->reserved); i++)
363
      fix->reserved[i] = 0;
364
 
365
   return(0);
366
}
367
 
368
 
369
   /*
370
    *    Get the video params out of `var'. If a value doesn't fit, round
371
    *    it up, if it's too big, return -EINVAL.
372
    */
373
 
374
static int mc68328_decode_var(struct fb_var_screeninfo *var,
375
                          struct mc68328_fb_par *par)
376
{
377
   par->xres = PALM_WIDTH;
378
   par->yres = PALM_HEIGHT;
379
   par->bpp = 1;
380
   return(0);
381
}
382
 
383
 
384
   /*
385
    *    Fill the `var' structure based on the values in `par' and maybe
386
    *    other values read out of the hardware.
387
    */
388
 
389
static int mc68328_encode_var(struct fb_var_screeninfo *var,
390
                          struct mc68328_fb_par *par)
391
{
392
   int i;
393
 
394
   var->xres = par->xres;
395
   var->yres = par->yres;
396
   var->xres_virtual = par->xres;
397
   var->yres_virtual = par->yres;
398
   var->xoffset = 0;
399
   var->yoffset = 0;
400
 
401
   var->bits_per_pixel = par->bpp;
402
   var->grayscale = -1;
403
 
404
   var->red.offset = 0;
405
   var->red.length = par->bpp;
406
   var->red.msb_right = 0;
407
   var->blue = var->green = var->red;
408
 
409
   var->transp.offset = 0;
410
   var->transp.length = 0;
411
   var->transp.msb_right = 0;
412
 
413
   var->nonstd = 0;
414
   var->activate = 0;
415
 
416
   var->height = -1;
417
   var->width = -1;
418
   var->accel = FB_ACCEL_NONE;
419
   var->vmode = FB_VMODE_NONINTERLACED;
420
 
421
   /* Dummy values */
422
 
423
   var->pixclock = 0;
424
   var->sync = 0;
425
   var->left_margin = 0;
426
   var->right_margin = 0;
427
   var->upper_margin = 0;
428
   var->lower_margin = 0;
429
   var->hsync_len = 0;
430
   var->vsync_len = 0;
431
 
432
   for (i = 0; i < arraysize(var->reserved); i++)
433
      var->reserved[i] = 0;
434
 
435
   return(0);
436
}
437
 
438
 
439
   /*
440
    *    Set a single color register. The values supplied are already
441
    *    rounded down to the hardware's capabilities (according to the
442
    *    entries in the var structure). Return != 0 for invalid regno.
443
    */
444
 
445
static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
446
                         u_int transp)
447
{
448
        return 1;
449
#if 0
450
if (regno > 255)
451
  return (1);
452
 
453
*(mc68328Regs + 0x3c8) = (char)regno;
454
mc68328_colour_table [regno][0] = red & 0xff;
455
mc68328_colour_table [regno][1] = green & 0xff;
456
mc68328_colour_table [regno][2] = blue & 0xff;
457
mc68328_colour_table [regno][3] = transp;
458
 
459
*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
460
*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
461
*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
462
 
463
return (0);
464
#endif
465
}
466
 
467
 
468
   /*
469
    *    Read a single color register and split it into
470
    *    colors/transparent. Return != 0 for invalid regno.
471
    */
472
 
473
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
474
                         u_int *transp)
475
{
476
        return 1;
477
#if 0
478
if (regno >= 256)
479
  return (1);
480
*red    = mc68328_colour_table [regno][0];
481
*green  = mc68328_colour_table [regno][1];
482
*blue   = mc68328_colour_table [regno][2];
483
*transp = mc68328_colour_table [regno][3];
484
return (0);
485
#endif
486
}
487
 
488
 
489
   /*
490
    *    (Un)Blank the screen
491
    */
492
 
493
void mc68328_blank(int blank)
494
{
495
#if 0
496
        if (blank)
497
                (*(volatile unsigned char*)0xFFFFFA27) &= ~128;
498
        else
499
                (*(volatile unsigned char*)0xFFFFFA27) |= 128;
500
#endif
501
}
502
 
503
 
504
/**************************************************************
505
 * We are waiting for "fifo" FIFO-slots empty
506
 */
507
void mc68328_WaitQueue (u_short fifo)
508
{
509
}
510
 
511
/**************************************************************
512
 * We are waiting for Hardware (Graphics Engine) not busy
513
 */
514
void mc68328_WaitBlit (void)
515
{
516
}
517
 
518
/**************************************************************
519
 * BitBLT - Through the Plane
520
 */
521
void mc68328_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
522
                   u_short width, u_short height, u_short mode)
523
{
524
#if 0
525
u_short blitcmd = S3_BITBLT;
526
 
527
/* Set drawing direction */
528
/* -Y, X maj, -X (default) */
529
if (curx > destx)
530
  blitcmd |= 0x0020;  /* Drawing direction +X */
531
else
532
  {
533
  curx  += (width - 1);
534
  destx += (width - 1);
535
  }
536
 
537
if (cury > desty)
538
  blitcmd |= 0x0080;  /* Drawing direction +Y */
539
else
540
  {
541
  cury  += (height - 1);
542
  desty += (height - 1);
543
  }
544
 
545
mc68328_WaitQueue (0x8000);
546
 
547
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
548
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0060 | mode);
549
 
550
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = curx;
551
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = cury;
552
 
553
*((u_short volatile *)(mc68328Regs + S3_DESTX_DIASTP)) = destx;
554
*((u_short volatile *)(mc68328Regs + S3_DESTY_AXSTP)) = desty;
555
 
556
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
557
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
558
 
559
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
560
#endif
561
}
562
 
563
/**************************************************************
564
 * Rectangle Fill Solid
565
 */
566
void mc68328_RectFill (u_short x, u_short y, u_short width, u_short height,
567
                     u_short mode, u_short color)
568
{
569
#if 0
570
u_short blitcmd = S3_FILLEDRECT;
571
 
572
mc68328_WaitQueue (0x8000);
573
 
574
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
575
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0020 | mode);
576
 
577
*((u_short volatile *)(mc68328Regs + S3_MULT_MISC)) = 0xe000;
578
*((u_short volatile *)(mc68328Regs + S3_FRGD_COLOR)) = color;
579
 
580
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = x;
581
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = y;
582
 
583
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
584
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
585
 
586
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
587
#endif
588
}
589
 
590
 
591
/**************************************************************
592
 * Move cursor to x, y
593
 */
594
void mc68328_MoveCursor (u_short x, u_short y)
595
{
596
        (*(volatile unsigned short*)0xFFFFFA18) = (mc68328fbCursorMode << 14) | x;
597
        (*(volatile unsigned short*)0xFFFFFA1A) = y;
598
#if 0
599
*(mc68328Regs + S3_CRTC_ADR)  = 0x39;
600
*(mc68328Regs + S3_CRTC_DATA) = 0xa0;
601
 
602
*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
603
*(mc68328Regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
604
*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
605
*(mc68328Regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
606
 
607
*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
608
*(mc68328Regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
609
*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
610
*(mc68328Regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
611
#endif
612
}
613
 
614
 
615
/* -------------------- Interfaces to hardware functions -------------------- */
616
 
617
 
618
static struct fb_hwswitch mc68328_switch = {
619
   mc68328_init, mc68328_encode_fix, mc68328_decode_var, mc68328_encode_var,
620
   mc68328_getcolreg, mc68328_setcolreg, mc68328_blank
621
};
622
 
623
 
624
/* -------------------- Generic routines ------------------------------------ */
625
 
626
 
627
   /*
628
    *    Fill the hardware's `par' structure.
629
    */
630
 
631
static void mc68328_fb_get_par(struct mc68328_fb_par *par)
632
{
633
   if (current_par_valid)
634
      *par = current_par;
635
   else
636
      fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], par);
637
}
638
 
639
 
640
static void mc68328_fb_set_par(struct mc68328_fb_par *par)
641
{
642
   current_par = *par;
643
   current_par_valid = 1;
644
}
645
 
646
 
647
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
648
{
649
   int err, activate;
650
   struct mc68328_fb_par par;
651
 
652
   if ((err = fbhw->decode_var(var, &par)))
653
      return(err);
654
   activate = var->activate;
655
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
656
      mc68328_fb_set_par(&par);
657
   fbhw->encode_var(var, &par);
658
   var->activate = activate;
659
   return(0);
660
}
661
 
662
 
663
   /*
664
    *    Default Colormaps
665
    */
666
 
667
static u_short red16[] =
668
   { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
669
     0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff};
670
static u_short green16[] =
671
   { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
672
     0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff};
673
static u_short blue16[] =
674
   { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
675
     0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff};
676
 
677
 
678
static struct fb_cmap default_16_colors =
679
   { 0, 16, red16, green16, blue16, NULL };
680
 
681
 
682
static struct fb_cmap *get_default_colormap(int bpp)
683
{
684
   return(&default_16_colors);
685
}
686
 
687
 
688
#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
689
#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
690
                                              ((1<<(width))-1)) : 0))
691
 
692
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
693
                          int kspc)
694
{
695
   int i, start;
696
   u_short *red, *green, *blue, *transp;
697
   u_int hred, hgreen, hblue, htransp;
698
 
699
   red = cmap->red;
700
   green = cmap->green;
701
   blue = cmap->blue;
702
   transp = cmap->transp;
703
   start = cmap->start;
704
   if (start < 0)
705
      return(-EINVAL);
706
   for (i = 0; i < cmap->len; i++) {
707
      if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
708
         return(0);
709
      hred = CNVT_FROMHW(hred, var->red.length);
710
      hgreen = CNVT_FROMHW(hgreen, var->green.length);
711
      hblue = CNVT_FROMHW(hblue, var->blue.length);
712
      htransp = CNVT_FROMHW(htransp, var->transp.length);
713
      if (kspc) {
714
         *red = hred;
715
         *green = hgreen;
716
         *blue = hblue;
717
         if (transp)
718
            *transp = htransp;
719
      } else {
720
         put_fs_word(hred, red);
721
         put_fs_word(hgreen, green);
722
         put_fs_word(hblue, blue);
723
         if (transp)
724
            put_fs_word(htransp, transp);
725
      }
726
      red++;
727
      green++;
728
      blue++;
729
      if (transp)
730
         transp++;
731
   }
732
   return(0);
733
}
734
 
735
 
736
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
737
                          int kspc)
738
{
739
   int i, start;
740
   u_short *red, *green, *blue, *transp;
741
   u_int hred, hgreen, hblue, htransp;
742
 
743
   red = cmap->red;
744
   green = cmap->green;
745
   blue = cmap->blue;
746
   transp = cmap->transp;
747
   start = cmap->start;
748
 
749
   if (start < 0)
750
      return(-EINVAL);
751
   for (i = 0; i < cmap->len; i++) {
752
      if (kspc) {
753
         hred = *red;
754
         hgreen = *green;
755
         hblue = *blue;
756
         htransp = transp ? *transp : 0;
757
      } else {
758
         hred = get_fs_word(red);
759
         hgreen = get_fs_word(green);
760
         hblue = get_fs_word(blue);
761
         htransp = transp ? get_fs_word(transp) : 0;
762
      }
763
      hred = CNVT_TOHW(hred, var->red.length);
764
      hgreen = CNVT_TOHW(hgreen, var->green.length);
765
      hblue = CNVT_TOHW(hblue, var->blue.length);
766
      htransp = CNVT_TOHW(htransp, var->transp.length);
767
      red++;
768
      green++;
769
      blue++;
770
      if (transp)
771
         transp++;
772
      if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
773
         return(0);
774
   }
775
   return(0);
776
}
777
 
778
 
779
static void do_install_cmap(int con)
780
{
781
   if (con != currcon)
782
      return;
783
   if (disp[con].cmap.len)
784
      do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
785
   else
786
      do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
787
                                          &disp[con].var, 1);
788
}
789
 
790
 
791
static void memcpy_fs(int fsfromto, void *to, void *from, int len)
792
{
793
   switch (fsfromto) {
794
      case 0:
795
         memcpy(to, from, len);
796
         return;
797
      case 1:
798
         memcpy_fromfs(to, from, len);
799
         return;
800
      case 2:
801
         memcpy_tofs(to, from, len);
802
         return;
803
   }
804
}
805
 
806
 
807
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
808
{
809
   int size;
810
   int tooff = 0, fromoff = 0;
811
 
812
   if (to->start > from->start)
813
      fromoff = to->start-from->start;
814
   else
815
      tooff = from->start-to->start;
816
   size = to->len-tooff;
817
   if (size > from->len-fromoff)
818
      size = from->len-fromoff;
819
   if (size < 0)
820
      return;
821
   size *= sizeof(u_short);
822
   memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
823
   memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
824
   memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
825
   if (from->transp && to->transp)
826
      memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
827
}
828
 
829
 
830
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
831
{
832
   int size = len*sizeof(u_short);
833
 
834
   if (cmap->len != len) {
835
      if (cmap->red)
836
         kfree(cmap->red);
837
      if (cmap->green)
838
         kfree(cmap->green);
839
      if (cmap->blue)
840
         kfree(cmap->blue);
841
      if (cmap->transp)
842
         kfree(cmap->transp);
843
      cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
844
      cmap->len = 0;
845
      if (!len)
846
         return(0);
847
      if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
848
         return(-1);
849
      if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
850
         return(-1);
851
      if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
852
         return(-1);
853
      if (transp) {
854
         if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
855
            return(-1);
856
      } else
857
         cmap->transp = NULL;
858
   }
859
   cmap->start = 0;
860
   cmap->len = len;
861
   copy_cmap(get_default_colormap(len), cmap, 0);
862
   return(0);
863
}
864
 
865
 
866
   /*
867
    *    Get the Fixed Part of the Display
868
    */
869
 
870
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
871
{
872
   struct mc68328_fb_par par;
873
   int error = 0;
874
 
875
   if (con == -1)
876
      mc68328_fb_get_par(&par);
877
   else
878
      error = fbhw->decode_var(&disp[con].var, &par);
879
   return(error ? error : fbhw->encode_fix(fix, &par));
880
}
881
 
882
 
883
   /*
884
    *    Get the User Defined Part of the Display
885
    */
886
 
887
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con)
888
{
889
   struct mc68328_fb_par par;
890
   int error = 0;
891
 
892
   if (con == -1) {
893
      mc68328_fb_get_par(&par);
894
      error = fbhw->encode_var(var, &par);
895
   } else
896
      *var = disp[con].var;
897
   return(error);
898
}
899
 
900
 
901
static void mc68328_fb_set_disp(int con)
902
{
903
   struct fb_fix_screeninfo fix;
904
 
905
   mc68328_fb_get_fix(&fix, con);
906
   if (con == -1)
907
      con = 0;
908
   disp[con].screen_base = (u_char *)fix.smem_start;
909
   disp[con].visual = fix.visual;
910
   disp[con].type = fix.type;
911
   disp[con].type_aux = fix.type_aux;
912
   disp[con].ypanstep = fix.ypanstep;
913
   disp[con].ywrapstep = fix.ywrapstep;
914
   disp[con].can_soft_blank = 1;
915
   disp[con].inverse = mc68328fb_inverse;
916
}
917
 
918
 
919
   /*
920
    *    Set the User Defined Part of the Display
921
    */
922
 
923
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con)
924
{
925
   int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
926
 
927
   if ((err = do_fb_set_var(var, con == currcon)))
928
      return(err);
929
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
930
      oldxres = disp[con].var.xres;
931
      oldyres = disp[con].var.yres;
932
      oldvxres = disp[con].var.xres_virtual;
933
      oldvyres = disp[con].var.yres_virtual;
934
      oldbpp = disp[con].var.bits_per_pixel;
935
      disp[con].var = *var;
936
      if (oldxres != var->xres || oldyres != var->yres ||
937
          oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
938
          oldbpp != var->bits_per_pixel) {
939
         mc68328_fb_set_disp(con);
940
         (*fb_info.changevar)(con);
941
         alloc_cmap(&disp[con].cmap, 0, 0);
942
         do_install_cmap(con);
943
      }
944
   }
945
   var->activate = 0;
946
   return(0);
947
}
948
 
949
 
950
   /*
951
    *    Get the Colormap
952
    */
953
 
954
static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
955
{
956
   if (con == currcon) /* current console? */
957
      return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
958
   else if (disp[con].cmap.len) /* non default colormap? */
959
      copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
960
   else
961
      copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
962
                kspc ? 0 : 2);
963
   return(0);
964
}
965
 
966
 
967
   /*
968
    *    Set the Colormap
969
    */
970
 
971
static int mc68328_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
972
{
973
   int err;
974
 
975
   if (!disp[con].cmap.len) {       /* no colormap allocated? */
976
      if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
977
                            0)))
978
         return(err);
979
   }
980
   if (con == currcon)              /* current console? */
981
      return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
982
   else
983
      copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
984
   return(0);
985
}
986
 
987
 
988
   /*
989
    *    Pan or Wrap the Display
990
    *
991
    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
992
    */
993
 
994
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con)
995
{
996
   return(-EINVAL);
997
}
998
 
999
 
1000
   /*
1001
    *    mc68328 Frame Buffer Specific ioctls
1002
    */
1003
 
1004
static int mc68328_fb_ioctl(struct inode *inode, struct file *file,
1005
                          u_int cmd, u_long arg, int con)
1006
{
1007
   return(-EINVAL);
1008
}
1009
 
1010
 
1011
static struct fb_ops mc68328_fb_ops = {
1012
   mc68328_fb_get_fix, mc68328_fb_get_var, mc68328_fb_set_var, mc68328_fb_get_cmap,
1013
   mc68328_fb_set_cmap, mc68328_fb_pan_display, mc68328_fb_ioctl
1014
};
1015
 
1016
 
1017
void mc68328_video_setup(char *options, int *ints)
1018
{
1019
   char *this_opt;
1020
   int i;
1021
 
1022
   fb_info.fontname[0] = '\0';
1023
 
1024
   if (!options || !*options)
1025
      return;
1026
 
1027
   for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
1028
      if (!strcmp(this_opt, "inverse")) {
1029
         mc68328fb_inverse = 1;
1030
         for (i = 0; i < 16; i++) {
1031
            red16[i] = ~red16[i];
1032
            green16[i] = ~green16[i];
1033
            blue16[i] = ~blue16[i];
1034
         }
1035
      } else if (!strncmp(this_opt, "font:", 5))
1036
         strcpy(fb_info.fontname, this_opt+5);
1037
      else
1038
         mc68328fb_mode = get_video_mode(this_opt);
1039
}
1040
 
1041
 
1042
   /*
1043
    *    Initialization
1044
    */
1045
 
1046
struct fb_info *mc68328_fb_init(long *mem_start)
1047
{
1048
   int err;
1049
   struct mc68328_fb_par par;
1050
 
1051
   memstart = mem_start;
1052
 
1053
   fbhw = &mc68328_switch;
1054
 
1055
   err = register_framebuffer(mc68328_fb_name, &node, &mc68328_fb_ops,
1056
                              NUM_TOTAL_MODES, mc68328_fb_predefined);
1057
   if (err < 0)
1058
      panic("Cannot register frame buffer\n");
1059
 
1060
   fbhw->init();
1061
   fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], &par);
1062
   fbhw->encode_var(&mc68328_fb_predefined[0], &par);
1063
 
1064
   strcpy(fb_info.modename, mc68328_fb_name);
1065
   fb_info.disp = disp;
1066
   fb_info.switch_con = &mc68328fb_switch;
1067
   fb_info.updatevar = &mc68328fb_updatevar;
1068
   fb_info.blank = &mc68328fb_blank;
1069
 
1070
   do_fb_set_var(&mc68328_fb_predefined[0], 1);
1071
   mc68328_fb_get_var(&disp[0].var, -1);
1072
   mc68328_fb_set_disp(-1);
1073
   do_install_cmap(0);
1074
   return(&fb_info);
1075
}
1076
 
1077
 
1078
static int mc68328fb_switch(int con)
1079
{
1080
   /* Do we have to save the colormap? */
1081
   if (disp[currcon].cmap.len)
1082
      do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
1083
 
1084
   do_fb_set_var(&disp[con].var, 1);
1085
   currcon = con;
1086
   /* Install new colormap */
1087
   do_install_cmap(con);
1088
   return(0);
1089
}
1090
 
1091
 
1092
   /*
1093
    *    Update the `var' structure (called by fbcon.c)
1094
    *
1095
    *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1096
    *    Since it's called by a kernel driver, no range checking is done.
1097
    */
1098
 
1099
static int mc68328fb_updatevar(int con)
1100
{
1101
   return(0);
1102
}
1103
 
1104
 
1105
   /*
1106
    *    Blank the display.
1107
    */
1108
 
1109
static void mc68328fb_blank(int blank)
1110
{
1111
   fbhw->blank(blank);
1112
}
1113
 
1114
 
1115
   /*
1116
    *    Get a Video Mode
1117
    */
1118
 
1119
static int get_video_mode(const char *name)
1120
{
1121
   int i;
1122
 
1123
   for (i = 1; i < NUM_PREDEF_MODES; i++)
1124
      if (!strcmp(name, mc68328_fb_modenames[i]))
1125
         return(i);
1126
   return(0);
1127
}

powered by: WebSVN 2.1.0

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