make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / video / epson1356fb.c
1 /*
2  *      epson1356fb.c  --  Epson SED1356 Framebuffer Driver
3  *
4  * Copyright 2001, 2002 MontaVista Software Inc.
5  * Author: MontaVista Software, Inc.
6  *              stevel@mvista.com or source@mvista.com
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
14  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
15  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
16  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
17  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
19  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
21  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  *  You should have received a copy of the  GNU General Public License along
25  *  with this program; if not, write  to the Free Software Foundation, Inc.,
26  *  675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * 
29  * TODO:
30  *
31  *  Revision history
32  *    03.12.2001  0.1   Initial release
33  *
34  */
35
36 #include <linux/config.h>
37 #include <linux/version.h>
38 #include <linux/module.h>
39
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <linux/mm.h>
44 #include <linux/tty.h>
45 #include <linux/slab.h>
46 #include <linux/vmalloc.h>
47 #include <linux/delay.h>
48 #include <linux/interrupt.h>
49 #include <linux/fb.h>
50 #include <linux/selection.h>
51 #include <linux/console.h>
52 #include <linux/init.h>
53 #include <linux/pci.h>
54 #include <linux/nvram.h>
55 #include <linux/kd.h>
56 #include <linux/vt_kern.h>
57 #include <asm/io.h>
58 #include <asm/uaccess.h>
59 #include <linux/timer.h>
60 #include <linux/pagemap.h>
61
62 #include <asm/pgalloc.h>
63 #include <asm/uaccess.h>
64 #include <asm/tlb.h>
65
66 #ifdef CONFIG_MTRR
67 #include <asm/mtrr.h>
68 #endif
69
70 #include <video/fbcon.h>
71 #include <video/fbcon-cfb8.h>
72 #include <video/fbcon-cfb16.h>
73 #include <video/fbcon-cfb24.h>
74 #include <video/fbcon-cfb32.h>
75
76 #include <linux/spinlock.h>
77
78 #include <linux/e1356fb.h>
79
80 #ifdef CONFIG_MIPS_AU1000
81 #include <asm/au1000.h>
82 #endif
83
84 #define E1356FB_DEBUG 1
85 #undef E1356FB_VERBOSE_DEBUG
86 #undef SHADOW_FRAME_BUFFER
87 #include "epson1356fb.h"
88
89 static char *options;
90 MODULE_PARM(options, "s");
91
92 /*
93  *  Frame buffer device API
94  */
95 static int e1356fb_open(struct fb_info *fb, int user);
96 static int e1356fb_release(struct fb_info *fb, int user);
97 static int e1356fb_get_fix(struct fb_fix_screeninfo* fix, 
98                            int con,
99                            struct fb_info* fb);
100 static int e1356fb_get_var(struct fb_var_screeninfo* var, 
101                            int con,
102                            struct fb_info* fb);
103 static int e1356fb_set_var(struct fb_var_screeninfo* var,
104                            int con,
105                            struct fb_info* fb);
106 static int e1356fb_pan_display(struct fb_var_screeninfo* var, 
107                                int con,
108                                struct fb_info* fb);
109 static int e1356fb_get_cmap(struct fb_cmap *cmap, 
110                             int kspc, 
111                             int con,
112                             struct fb_info* info);
113 static int e1356fb_set_cmap(struct fb_cmap* cmap, 
114                             int kspc, 
115                             int con,
116                             struct fb_info* info);
117 static int e1356fb_ioctl(struct inode* inode, 
118                          struct file* file, 
119                          u_int cmd,
120                          u_long arg, 
121                          int con, 
122                          struct fb_info* info);
123 static int e1356fb_mmap(struct fb_info *info,
124                         struct file *file,
125                         struct vm_area_struct *vma);
126
127 /*
128  *  Interface to the low level console driver
129  */
130 static int  e1356fb_switch_con(int con, 
131                                struct fb_info* fb);
132 static int  e1356fb_updatevar(int con, 
133                               struct fb_info* fb);
134 static void e1356fb_blank(int blank, 
135                           struct fb_info* fb);
136
137 /*
138  *  Internal routines
139  */
140 static void e1356fb_set_par(const struct e1356fb_par* par,
141                             struct fb_info_e1356* 
142                             info);
143 static int  e1356fb_var_to_par(const struct fb_var_screeninfo *var,
144                                struct e1356fb_par* par,
145                                const struct fb_info_e1356* info);
146 static int  e1356fb_par_to_var(struct fb_var_screeninfo* var,
147                                struct e1356fb_par* par,
148                                const struct fb_info_e1356* info);
149 static int  e1356fb_encode_fix(struct fb_fix_screeninfo* fix,
150                                const struct e1356fb_par* par,
151                                const struct fb_info_e1356* info);
152 static void e1356fb_set_dispsw(struct display* disp, 
153                                struct fb_info_e1356* info,
154                                int bpp, 
155                                int accel);
156 static int  e1356fb_getcolreg(u_int regno,
157                               u_int* red, 
158                               u_int* green, 
159                               u_int* blue,
160                               u_int* transp, 
161                               struct fb_info* fb);
162 static int  e1356fb_setcolreg(u_int regno, 
163                               u_int red, 
164                               u_int green, 
165                               u_int blue,
166                               u_int transp, 
167                               struct fb_info* fb);
168 static void  e1356fb_install_cmap(struct display *d, 
169                                   struct fb_info *info);
170
171 static void e1356fb_hwcursor_init(struct fb_info_e1356* info);
172 static void e1356fb_createcursorshape(struct display* p);
173 static void e1356fb_createcursor(struct display * p);  
174
175 /*
176  * do_xxx: Hardware-specific functions
177  */
178 static void  do_pan_var(struct fb_var_screeninfo* var,
179                         struct fb_info_e1356* i);
180 static void  do_flashcursor(unsigned long ptr);
181 static void  doBlt_Move(const struct e1356fb_par* par,
182                         struct fb_info_e1356* i,
183                         blt_info_t* blt);
184 static void  doBlt_SolidFill(const struct e1356fb_par* par,
185                              struct fb_info_e1356* i,
186                              blt_info_t* blt);
187
188 /*
189  *  Interface used by the world
190  */
191 int e1356fb_init(void);
192 void e1356fb_setup(char *options, int *ints);
193
194 static int currcon = 0;
195
196 static struct fb_ops e1356fb_ops = {
197         owner:  THIS_MODULE,
198         fb_open:        e1356fb_open,
199         fb_release:     e1356fb_release,
200         fb_get_fix:     e1356fb_get_fix,
201         fb_get_var:     e1356fb_get_var,
202         fb_set_var:     e1356fb_set_var,
203         fb_get_cmap:    e1356fb_get_cmap,
204         fb_set_cmap:    e1356fb_set_cmap,
205         fb_pan_display: e1356fb_pan_display,
206         fb_mmap:        e1356fb_mmap,
207 };
208
209 #define PCI_VENDOR_ID_EPSON         0x10f4
210 #define PCI_DEVICE_ID_EPSON_SDU1356 0x1300
211
212
213 static struct fb_info_e1356 fb_info;
214 static struct e1356fb_fix boot_fix; // boot options
215 static struct e1356fb_par boot_par; // boot options
216
217 static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot);
218
219
220 /* ------------------------------------------------------------------------- 
221  *                      Hardware-specific funcions
222  * ------------------------------------------------------------------------- */
223
224 /*
225  * The SED1356 has only a 16-bit wide data bus, so some embedded
226  * implementations with 32-bit CPU's (Alchemy Pb1000) may not
227  * correctly emulate a 32-bit write to the framebuffer by splitting
228  * the write into two seperate 16-bit writes. So it is safest to
229  * only do byte or half-word writes to the fb. This routine assumes
230  * fbaddr is atleast aligned on a half-word boundary.
231  */
232 static inline void
233 fbfill(u16* fbaddr, u8 val, int size)
234 {
235         u16 valw = (u16)val | ((u16)val << 8);
236         for ( ; size >= 2; size -= 2)
237                 writew(valw, fbaddr++);
238         if (size)
239                 writeb(val, (u8*)fbaddr);
240 }
241
242 static inline int
243 e1356_wait_bitclr(u8* reg, u8 bit, int timeout)
244 {
245         while (readb(reg) & bit) {
246                 udelay(10);
247                 if (!--timeout)
248                         break;
249         }
250         return timeout;
251 }
252
253 static inline int
254 e1356_wait_bitset(u8* reg, u8 bit, int timeout)
255 {
256         while (!(readb(reg) & bit)) {
257                 udelay(10);
258                 if (!--timeout)
259                         break;
260         }
261         return timeout;
262 }
263
264
265 static struct fb_videomode panel_modedb[] = {
266         {
267                 /* 320x240 @ 109 Hz, 33.3 kHz hsync */
268                 NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3),
269                 16, 16, 32, 24, 48, 8,
270                 0, FB_VMODE_NONINTERLACED
271         }, {
272                 /* 640x480 @ 84 Hz, 48.1 kHz hsync */
273                 NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1),
274                 96, 32, 32, 48, 64, 8,
275                 0, FB_VMODE_NONINTERLACED
276         }, {
277                 /* 800x600 @ 76 Hz, 46.3 kHz hsync */
278                 NULL, 76, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1),
279                 32, 10, 1, 1, 22, 1,
280                 0, FB_VMODE_NONINTERLACED
281         }
282 };
283 static struct fb_videomode crt_modedb[] = {
284         {
285                 /* 320x240 @ 84 Hz, 31.25 kHz hsync */
286                 NULL, 84, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/2),
287                 128, 128, 60, 60, 64, 8,
288                 0, FB_VMODE_NONINTERLACED
289         }, {
290                 /* 320x240 @ 109 Hz, 33.3 kHz hsync */
291                 NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3),
292                 16, 16, 32, 24, 48, 8,
293                 0, FB_VMODE_NONINTERLACED
294         }, {
295                 /* 512x384 @ 77 Hz, 31.25 kHz hsync */
296                 NULL, 77, 512, 384, KHZ2PICOS(MAX_PIXCLOCK/2),
297                 48, 16, 16, 1, 64, 3,
298                 0, FB_VMODE_NONINTERLACED
299         }, {
300                 /* 640x400 @ 88 Hz, 43.1 kHz hsync */
301                 NULL, 88, 640, 400, KHZ2PICOS(MAX_PIXCLOCK/1),
302                 128, 96, 32, 48, 64, 8,
303                 0, FB_VMODE_NONINTERLACED
304         }, {
305                 /* 640x480 @ 84 Hz, 48.1 kHz hsync */
306                 NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1),
307                 96, 32, 32, 48, 64, 8,
308                 0, FB_VMODE_NONINTERLACED
309         }, {
310                 /* 768x576 @ 62 Hz, 38.5 kHz hsync */
311                 NULL, 62, 768, 576, KHZ2PICOS(MAX_PIXCLOCK/1),
312                 144, 16, 28, 6, 112, 4,
313                 0, FB_VMODE_NONINTERLACED
314         }, {
315                 /* 800x600 @ 60 Hz, 37.9 kHz hsync */
316                 NULL, 60, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1),
317                 88, 40, 23, 1, 128, 4,
318                 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
319                 FB_VMODE_NONINTERLACED
320         }
321 };
322
323 static struct fb_videomode ntsc_modedb[] = {
324         {
325                 /* 640x480 @ 62 Hz, requires flicker filter */
326                 //NULL, 62, 640, 480, 34921, 213, 57, 20, 2, 0, 0,
327                 NULL, 62, 640, 480, KHZ2PICOS(2*NTSC_PIXCLOCK),
328                 200, 70, 15, 7, 0, 0,
329                 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
330         }
331 };
332 static struct fb_videomode pal_modedb[] = {
333         {
334                 /* 640x480 @ 56 Hz, requires flicker filter */
335                 NULL, 56, 640, 480, KHZ2PICOS(2*PAL_PIXCLOCK),
336                 350, 145, 49, 23, 0, 0,
337                 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
338         }
339 };
340
341
342 static inline void
343 fb_videomode_to_var(struct fb_videomode* mode,
344                     struct fb_var_screeninfo*var)
345 {
346         var->xres = mode->xres;
347         var->yres = mode->yres;
348         var->pixclock = mode->pixclock;
349         var->left_margin = mode->left_margin;
350         var->right_margin = mode->right_margin;
351         var->upper_margin = mode->upper_margin;
352         var->lower_margin = mode->lower_margin;
353         var->hsync_len = mode->hsync_len;
354         var->vsync_len = mode->vsync_len;
355         var->sync = mode->sync;
356         var->vmode = mode->vmode;
357 }
358
359
360 static int
361 e1356fb_get_mode(const struct fb_info_e1356 *info,
362                  int xres,
363                  int yres,
364                  struct fb_videomode ** modedb,
365                  struct fb_videomode ** mode)
366 {
367         struct fb_videomode * ret;
368         int i, dbsize;
369
370         if (IS_PANEL(info->fix.disp_type)) {
371                 ret = panel_modedb;
372                 dbsize = sizeof(panel_modedb)/sizeof(struct fb_videomode);
373         } else if (info->fix.disp_type == DISP_TYPE_CRT) {
374                 ret = crt_modedb;
375                 dbsize = sizeof(crt_modedb)/sizeof(struct fb_videomode);
376         } else if (info->fix.disp_type == DISP_TYPE_NTSC) {
377                 ret = ntsc_modedb;
378                 dbsize = sizeof(ntsc_modedb)/sizeof(struct fb_videomode);
379         } else {
380                 ret = pal_modedb;
381                 dbsize = sizeof(pal_modedb)/sizeof(struct fb_videomode);
382         }
383         
384         if (modedb)
385                 *modedb = ret;
386         for (i=0; i<dbsize; i++) {
387                 if (xres == ret[i].xres && yres == ret[i].yres) {
388                         *mode = &ret[i];
389                         break;
390                 }
391         }
392         if (i == dbsize)
393                 return -EINVAL;
394         return dbsize;
395 }
396
397
398
399 #ifdef E1356FB_VERBOSE_DEBUG
400 static void
401 dump_par(const struct e1356fb_par* par)
402 {
403         DPRINTK("width:       %d\n", par->width);
404         DPRINTK("height:      %d\n", par->height);
405         DPRINTK("width_virt:  %d\n", par->width_virt);
406         DPRINTK("height_virt: %d\n", par->height_virt);
407         DPRINTK("bpp:         %d\n", par->bpp);
408         DPRINTK("pixclock:    %d\n", par->ipclk.pixclk);
409         DPRINTK("horiz_ndp:   %d\n", par->horiz_ndp);
410         DPRINTK("vert_ndp:    %d\n", par->vert_ndp);
411         DPRINTK("hsync_pol:   %d\n", par->hsync_pol);
412         DPRINTK("hsync_start: %d\n", par->hsync_start);
413         DPRINTK("hsync_width: %d\n", par->hsync_width);
414         DPRINTK("vsync_pol:   %d\n", par->vsync_pol);
415         DPRINTK("vsync_start: %d\n", par->vsync_start);
416         DPRINTK("vsync_width: %d\n", par->vsync_width);
417         DPRINTK("cmap_len:    %d\n", par->cmap_len);
418 }
419
420 static void
421 dump_display_regs(reg_dispcfg_t* dispcfg, reg_dispmode_t* dispmode)
422 {
423         DPRINTK("hdw:            0x%02x\n", readb(&dispcfg->hdw));
424         DPRINTK("hndp:           0x%02x\n", readb(&dispcfg->hndp));
425         DPRINTK("hsync_start:    0x%02x\n", readb(&dispcfg->hsync_start));
426         DPRINTK("hsync_pulse:    0x%02x\n", readb(&dispcfg->hsync_pulse));
427         DPRINTK("vdh0:           0x%02x\n", readb(&dispcfg->vdh0));
428         DPRINTK("vdh1:           0x%02x\n", readb(&dispcfg->vdh1));
429         DPRINTK("vndp:           0x%02x\n", readb(&dispcfg->vndp));
430         DPRINTK("vsync_start:    0x%02x\n", readb(&dispcfg->vsync_start));
431         DPRINTK("vsync_pulse:    0x%02x\n", readb(&dispcfg->vsync_pulse));
432         DPRINTK("tv_output_ctrl: 0x%02x\n\n", readb(&dispcfg->tv_output_ctrl));
433
434         DPRINTK("disp_mode:        0x%02x\n", readb(&dispmode->disp_mode));
435         DPRINTK("lcd_misc:         0x%02x\n", readb(&dispmode->lcd_misc));
436         DPRINTK("start_addr0:      0x%02x\n", readb(&dispmode->start_addr0));
437         DPRINTK("start_addr1:      0x%02x\n", readb(&dispmode->start_addr1));
438         DPRINTK("start_addr2:      0x%02x\n", readb(&dispmode->start_addr2));
439         DPRINTK("mem_addr_offset0: 0x%02x\n", readb(&dispmode->mem_addr_offset0));
440         DPRINTK("mem_addr_offset1: 0x%02x\n", readb(&dispmode->mem_addr_offset1));
441         DPRINTK("pixel_panning:    0x%02x\n", readb(&dispmode->pixel_panning));
442         DPRINTK("fifo_high_thresh: 0x%02x\n", readb(&dispmode->fifo_high_thresh));
443         DPRINTK("fifo_low_thresh:  0x%02x\n", readb(&dispmode->fifo_low_thresh));
444 }
445
446 static void
447 dump_fb(u8* base, int len)
448 {
449         int i;
450         DPRINTK("FB memory dump, start 0x%p, len %d", base, len);
451         for (i=0; i<len; i++) {
452                 if (!(i%16))
453                         printk("\n%p: %02x ", &base[i], readb(&base[i]));
454                 else
455                         printk("%02x ", readb(&base[i]));
456         }
457         printk("\n");
458 }
459
460 #endif // E1356FB_VERBOSE_DEBUG
461
462
463
464 // Input:  ipclk->clksrc, ipclk->pixclk_d
465 // Output: ipclk->pixclk, ipclk->error, and ipclk->divisor
466 static int
467 get_nearest_pixclk_div(pixclock_info_t* ipclk, int x2)
468 {
469         int pixclk_d = ipclk->pixclk_d;
470         int clksrc = ipclk->clksrc;
471
472         if (x2) clksrc *= 2;
473
474         if (clksrc < (3*pixclk_d+1)/2)
475                 ipclk->divisor = 1;
476         else if (clksrc < (5*pixclk_d+1)/2)
477                 ipclk->divisor = 2;
478         else if (clksrc < (7*pixclk_d+1)/2)
479                 ipclk->divisor = 3;
480         else if (clksrc < (9*pixclk_d+1)/2)
481                 ipclk->divisor = 4;
482         else
483                 return -ENXIO;
484
485         ipclk->pixclk = clksrc / ipclk->divisor;
486         ipclk->error = (100*(pixclk_d - ipclk->pixclk)) / pixclk_d;
487         return 0;
488 }
489
490 static int
491 e1356_calc_pixclock(const struct fb_info_e1356 *info,
492                     pixclock_info_t* ipclk)
493 {
494         int src_sel=-1, flicker_mult=0;
495         pixclock_info_t test, ret;
496     
497         if (ipclk->pixclk > info->max_pixclock)
498                 return -ENXIO;
499
500         test.pixclk_d = ipclk->pixclk_d;
501         ret.error = 100;
502         
503         if (IS_TV(info->fix.disp_type) &&
504             (info->fix.tv_filt & TV_FILT_FLICKER))
505                 flicker_mult = 0x80;
506         
507         test.clksrc = info->fix.busclk;
508         if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
509             abs(test.error) < abs(ret.error)) {
510                 ret = test;
511                 src_sel = 0x01;
512         }
513
514         test.clksrc = info->fix.mclk;
515         if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
516             abs(test.error) < abs(ret.error)) {
517                 ret = test;
518                 src_sel = 0x03;
519         }
520
521         test.clksrc = info->fix.clki;
522         if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
523             abs(test.error) < abs(ret.error)) {
524                 ret = test;
525                 src_sel = 0x00;
526         }
527
528         test.clksrc = info->fix.clki2;
529         if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
530             abs(test.error) < abs(ret.error)) {
531                 ret = test;
532                 src_sel = 0x02;
533         }
534
535         if (ret.error > MAX_PCLK_ERROR_LOWER ||
536             ret.error < MAX_PCLK_ERROR_HIGHER)
537                 return -ENXIO;
538     
539         ret.pixclk_bits = flicker_mult | ((ret.divisor-1)<<4) | src_sel;
540         *ipclk = ret;
541         return 0;
542 }
543
544 static inline int
545 e1356_engine_wait_complete(reg_bitblt_t* bltreg)
546 {
547         return e1356_wait_bitclr(&bltreg->ctrl0, 0x80, 5000);
548 }
549 static inline int
550 e1356_engine_wait_busy(reg_bitblt_t* bltreg)
551 {
552         return e1356_wait_bitset(&bltreg->ctrl0, 0x80, 5000);
553 }
554
555 static void
556 e1356fb_engine_init(const struct e1356fb_par* par,
557                     struct fb_info_e1356* info)
558 {
559         reg_bitblt_t* bltreg = info->reg.bitblt;
560     
561         e1356_engine_wait_complete(bltreg);
562
563         writeb(0, &bltreg->ctrl0);
564         writeb(0, &bltreg->ctrl1);
565         writeb(0, &bltreg->rop_code);
566         writeb(0, &bltreg->operation);
567         writeb(0, &bltreg->src_start_addr0);
568         writeb(0, &bltreg->src_start_addr1);
569         writeb(0, &bltreg->src_start_addr2);
570         writeb(0, &bltreg->dest_start_addr0);
571         writeb(0, &bltreg->dest_start_addr1);
572         writeb(0, &bltreg->dest_start_addr2);
573         writew(0, &bltreg->mem_addr_offset0);
574         writew(0, &bltreg->width0);
575         writew(0, &bltreg->height0);
576         writew(0, &bltreg->bg_color0);
577         writew(0, &bltreg->fg_color0);
578 }
579
580
581 static void doBlt_Write(const struct e1356fb_par* par,
582                         struct fb_info_e1356* info,
583                         blt_info_t* blt)
584 {
585         reg_bitblt_t* bltreg = info->reg.bitblt;
586         int nWords, nTotalWords;
587         u32 srcphase, dstAddr;
588         u16* w16;
589         u32 stride = par->width_virt * par->Bpp;
590
591         dstAddr = blt->dst_x * par->Bpp + blt->dst_y * stride;
592         srcphase = (u32)blt->src & 1;
593     
594         if (blt->attribute & BLT_ATTR_TRANSPARENT)
595                 writew(blt->bg_color, &bltreg->bg_color0);
596         else
597                 writeb(blt->rop, &bltreg->rop_code);
598     
599         writeb(blt->operation, &bltreg->operation);
600         writeb((u8)srcphase, &bltreg->src_start_addr0);
601         writew(stride/2, &bltreg->mem_addr_offset0);
602
603         writeb(dstAddr, &bltreg->dest_start_addr0);
604         writeb(dstAddr>>8, &bltreg->dest_start_addr1);
605         writeb(dstAddr>>16, &bltreg->dest_start_addr2);
606
607         writew(blt->dst_width-1, &bltreg->width0);
608         writew(blt->dst_height-1, &bltreg->height0);
609
610         // program color format operation
611         writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
612
613         // start it up
614         writeb(0x80, &bltreg->ctrl0);
615
616         // wait for it to actually start
617         e1356_engine_wait_busy(bltreg);
618
619         // calculate the number of 16 bit words per one blt line
620
621         nWords = srcphase + ((blt->dst_width - srcphase)*par->Bpp + 1) / 2;
622         nTotalWords = nWords*blt->dst_height;
623         w16 = (u16*)((u32)blt->src & 0xfffffffe);   // Word aligned
624
625         while (nTotalWords > 0) {
626                 int j, nFIFO;
627                 u8 ctrl0;
628
629                 // read the FIFO status
630                 ctrl0 = readb(&bltreg->ctrl0);
631
632                 if ((ctrl0 & 0x30) == 0x20)
633                         // FIFO is at least half full, but not full
634                         nFIFO = 1;
635                 else if ((ctrl0 & 0x40) == 0)
636                         // FIFO is empty
637                         nFIFO = 16;
638                 else
639                         // FIFO is full
640                         continue;
641
642                 for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)
643                         writew(*w16++, info->reg.bitblt_data);
644         }
645
646         e1356_engine_wait_complete(bltreg);
647 }
648
649
650 static void
651 doBlt_SolidFill(const struct e1356fb_par* par,
652                 struct fb_info_e1356* info,
653                 blt_info_t* blt)
654 {
655         reg_bitblt_t* bltreg = info->reg.bitblt;
656         u32 width = blt->dst_width, height = blt->dst_height;
657         u32 stride = par->width_virt * par->Bpp;
658         u32 dest_addr = (blt->dst_y * stride) + (blt->dst_x * par->Bpp);
659
660         if (width == 0 || height == 0)
661                 return;
662
663         // program dest address
664         writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);
665         writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);
666         writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);
667
668         // program width and height of solid-fill blit
669         writew(width-1, &bltreg->width0);
670         writew(height-1, &bltreg->height0);
671
672         // program color of fill
673         writew(blt->fg_color, &bltreg->fg_color0);
674         // select solid-fill BLIT
675         writeb(BLT_SOLID_FILL, &bltreg->operation);
676         // program color format operation
677         writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
678         // program BLIT memory offset
679         writew(stride/2, &bltreg->mem_addr_offset0);
680
681         // start it up (self completes)
682         writeb(0x80, &bltreg->ctrl0);
683
684         e1356_engine_wait_complete(bltreg);
685 }
686
687
688 static void
689 doBlt_Move(const struct e1356fb_par* par,
690            struct fb_info_e1356* info,
691            blt_info_t* blt)
692 {
693         reg_bitblt_t* bltreg = info->reg.bitblt;
694         int neg_dir=0;
695         u32 dest_addr, src_addr;
696         u32 bpp = par->bpp;
697         u32 stride = par->width_virt * par->Bpp; // virt line length in bytes
698         u32 srcx = blt->src_x, srcy = blt->src_y;
699         u32 dstx = blt->dst_x, dsty = blt->dst_y;
700         u32 width = blt->dst_width, height = blt->dst_height;
701     
702         if (width == 0 || height == 0)
703                 return;
704    
705         src_addr = srcx*par->Bpp + srcy*stride;
706         dest_addr = dstx*par->Bpp + dsty*stride;
707
708         /*
709          * See if regions overlap and dest region is beyond source region.
710          * If so, we need to do a move BLT in negative direction. Only applies
711          * if the BLT is not transparent.
712          */
713         if (!(blt->attribute & BLT_ATTR_TRANSPARENT)) {
714                 if ((srcx + width  > dstx) && (srcx < dstx + width) &&
715                     (srcy + height > dsty) && (srcy < dsty + height) &&
716                     (dest_addr > src_addr)) {
717                         neg_dir = 1;
718                         // negative direction : get the coords of lower right corner
719                         src_addr += stride * (height-1) + par->Bpp * (width-1);
720                         dest_addr += stride * (height-1) + par->Bpp * (width-1);
721                 }
722         }
723     
724         // program BLIT memory offset
725         writew(stride/2, &bltreg->mem_addr_offset0);
726
727         // program src and dest addresses
728         writeb(src_addr & 0x00ff, &bltreg->src_start_addr0);
729         writeb((src_addr>>8) & 0x00ff, &bltreg->src_start_addr1);
730         writeb((src_addr>>16) & 0x00ff, &bltreg->src_start_addr2);
731         writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);
732         writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);
733         writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);
734
735         // program width and height of blit
736         writew(width-1, &bltreg->width0);
737         writew(height-1, &bltreg->height0);
738
739         // program color format operation
740         writeb(bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
741
742         // set the blt type
743         if (blt->attribute & BLT_ATTR_TRANSPARENT) {
744                 writew(blt->bg_color, &bltreg->bg_color0);
745                 writeb(BLT_MOVE_POS_TRANSP, &bltreg->operation); 
746         } else {
747                 writeb(blt->rop, &bltreg->rop_code);
748                 // select pos/neg move BLIT
749                 writeb(neg_dir ? BLT_MOVE_NEG_ROP : BLT_MOVE_POS_ROP,
750                        &bltreg->operation); 
751         }
752
753         // start it up (self completes)
754         writeb(0x80, &bltreg->ctrl0);
755
756         e1356_engine_wait_complete(bltreg);
757 }
758
759
760 static void doBlt_ColorExpand(const struct e1356fb_par* par,
761                               struct fb_info_e1356* info,
762                               blt_info_t* blt)
763 {
764         reg_bitblt_t* bltreg = info->reg.bitblt;
765         int i, j, nWords, Sx, Sy;
766         u32 dstAddr;
767         u16* wpt, *wpt1;
768         u32 stride = par->width_virt * par->Bpp;
769
770         if (blt->dst_width == 0 || blt->dst_height == 0)
771                 return;
772
773         Sx = blt->src_x;
774         Sy = blt->src_y;
775
776         writeb((7 - Sx%8), &bltreg->rop_code);
777
778         writeb(blt->operation, &bltreg->operation);
779
780         writeb((u8)(Sx & 1), &bltreg->src_start_addr0);
781
782         dstAddr = blt->dst_x*par->Bpp + blt->dst_y * stride;
783         writeb(dstAddr, &bltreg->dest_start_addr0);
784         writeb(dstAddr>>8, &bltreg->dest_start_addr1);
785         writeb(dstAddr>>16, &bltreg->dest_start_addr2);
786
787         // program color format operation
788         writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
789         writew(stride/2, &bltreg->mem_addr_offset0);
790         writew(blt->dst_width-1, &bltreg->width0);
791         writew(blt->dst_height-1, &bltreg->height0);
792         writew(blt->bg_color, &bltreg->bg_color0);
793         writew(blt->fg_color, &bltreg->fg_color0);
794
795         // start it up
796         writeb(0x80, &bltreg->ctrl0);
797
798         // wait for it to actually start
799         e1356_engine_wait_busy(bltreg);
800
801         // calculate the number of 16 bit words per one blt line
802
803         nWords = (Sx%16 + blt->dst_width + 15)/16;
804
805         wpt = blt->src + (Sy*blt->srcstride + Sx/16)/2;
806
807         for (i = 0; i < blt->dst_height; i++) {
808                 wpt1 = wpt;
809
810                 for (j = 0; j < nWords; j++) {
811                         // loop until FIFO becomes empty...
812                         e1356_wait_bitclr(&bltreg->ctrl0, 0x40, 10000);
813                         writew(*wpt1++, info->reg.bitblt_data);
814                 }
815         
816                 wpt += blt->srcstride/2;
817         }
818
819         e1356_engine_wait_complete(bltreg);
820 }
821
822
823 /*
824  * The BitBLT operation dispatcher
825  */
826 static int
827 doBlt(const struct e1356fb_par* par,
828       struct fb_info_e1356* info,
829       blt_info_t* blt)
830 {
831         /*
832          * Make sure we're not reentering in the middle of an
833          * active BitBLT operation. ALWAYS call this dispatcher
834          * and not one of the above BLT routines directly, or you
835          * run the risk of overlapping BLT operations, which can
836          * cause complete system hangs.
837      */
838         if (readb(&info->reg.bitblt->ctrl0) & 0x80)
839                 return -ENXIO;
840     
841         switch (blt->operation) {
842         case BLT_MOVE_POS_ROP:
843         case BLT_MOVE_NEG_ROP:
844         case BLT_MOVE_POS_TRANSP:
845                 doBlt_Move(par, info, blt);
846                 break;
847         case BLT_COLOR_EXP:
848         case BLT_COLOR_EXP_TRANSP:
849                 doBlt_ColorExpand(par, info, blt);
850                 break;
851         case BLT_SOLID_FILL:
852                 doBlt_SolidFill(par, info, blt);
853                 break;
854         case BLT_WRITE_ROP:
855         case BLT_WRITE_TRANSP:
856                 doBlt_Write(par, info, blt);
857                 break;
858         case BLT_READ:
859         case BLT_PAT_FILL_ROP:
860         case BLT_PAT_FILL_TRANSP:
861         case BLT_MOVE_COLOR_EXP:
862         case BLT_MOVE_COLOR_EXP_TRANSP:
863                 DPRINTK("BitBLT operation 0x%02x not implemented yet\n",
864                         blt->operation);
865                 return -ENXIO;
866         default:
867                 DPRINTK("Unknown BitBLT operation 0x%02x\n", blt->operation);
868                 return -ENXIO;
869         }
870     
871         return 0;
872 }
873
874
875 // Initializes blt->src and blt->srcstride
876 static void fill_putcs_buffer(struct display *p,
877                               blt_info_t* blt,
878                               const unsigned short* str,
879                               int count)
880 {   
881         int row, i, j;
882         u8* b1, *b2;
883         u32 fw = fontwidth(p);
884         u32 fwb = (fw + 7) >> 3;
885         u32 fh = fontheight(p);
886         int bytesPerChar = fwb * fh;
887
888         if (count*bytesPerChar > PAGE_SIZE) {
889                 // Truncate the string if it overflows putcs_buffer, which is
890                 // one page in size.
891                 count = PAGE_SIZE/bytesPerChar - 1;
892         }
893
894         blt->srcstride = (fwb*count + 1) & ~1; //round up to be even
895         
896         b1 = (u8*)blt->src;
897
898         for (row = 0; row < fh; row++) {
899                 b2 = b1;
900                 for (i = 0; i < count; i++) {
901                         for (j=0; j<fwb; j++)
902                                 *b2++ = p->fontdata[(str[i] & p->charmask) *
903                                                    bytesPerChar +
904                                                    row*fwb + j];
905                 }
906                 b1 += blt->srcstride;
907         }
908 }
909
910
911 /*
912  * Set the color of a palette entry in 8bpp mode 
913  */
914 static inline void
915 do_setpalentry(reg_lut_t* lut, unsigned regno,
916                u8 r, u8 g, u8 b)
917 {
918         writeb(0x00, &lut->mode);
919         writeb((u8)regno, &lut->addr);
920         writeb(r&0xf0, &lut->data);
921         writeb(g&0xf0, &lut->data);
922         writeb(b&0xf0, &lut->data);
923 }
924
925    
926 static void
927 do_pan_var(struct fb_var_screeninfo* var, struct fb_info_e1356* info)
928 {
929         u32 pixel_start, start_addr;
930         u8 pixel_pan;
931         struct e1356fb_par* par = &info->current_par;
932         reg_misc_t* misc = info->reg.misc;
933         reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ?
934                 info->reg.lcd_mode : info->reg.crttv_mode;
935         
936         pixel_start = var->yoffset * par->width_virt + var->xoffset;
937         start_addr = (pixel_start * par->Bpp) / 2;
938         pixel_pan = (par->bpp == 8) ? (u8)(pixel_start & 1) : 0;
939     
940         if (readb(&misc->disp_mode) != 0) {
941                 reg_dispcfg_t* dispcfg = (IS_PANEL(info->fix.disp_type)) ?
942                         info->reg.lcd_cfg : info->reg.crttv_cfg;
943
944                 // wait for the end of the current VNDP
945                 e1356_wait_bitclr(&dispcfg->vndp, 0x80, 5000);
946                 // now wait for the start of a new VNDP
947                 e1356_wait_bitset(&dispcfg->vndp, 0x80, 5000);
948         }
949     
950         writeb((u8)(start_addr & 0xff), &dispmode->start_addr0);
951         writeb((u8)((start_addr>>8) & 0xff), &dispmode->start_addr1);
952         writeb((u8)((start_addr>>16) & 0xff), &dispmode->start_addr2);
953         writeb(pixel_pan, &dispmode->pixel_panning);
954 }
955
956
957 /*
958  * Invert the hardware cursor image (timerfunc)  
959  */
960 static void
961 do_flashcursor(unsigned long ptr)
962 {
963         u8 curs_ctrl;
964         struct fb_info_e1356* info = (struct fb_info_e1356 *)ptr;
965         reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
966                 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
967
968         spin_lock(&info->cursor.lock);
969         // toggle cursor enable bit
970         curs_ctrl = readb(&inkcurs->ctrl);
971         writeb((curs_ctrl ^ 0x01) & 0x01, &inkcurs->ctrl);
972         info->cursor.timer.expires = jiffies+HZ/2;
973         add_timer(&info->cursor.timer);
974         spin_unlock(&info->cursor.lock);
975 }
976
977 #ifdef SHADOW_FRAME_BUFFER
978 /*
979  * Write BLT the shadow frame buffer to the real fb (timerfunc)  
980  */
981 static void
982 do_write_shadow_fb(unsigned long ptr)
983 {
984         blt_info_t blt;
985         struct fb_info_e1356 *info = (struct fb_info_e1356*)ptr;
986         struct fb_info* fb = &info->fb_info;
987         struct e1356fb_par* par = &info->current_par;
988         u32 stride = par->width_virt * par->Bpp;
989
990         unsigned long j_start = jiffies;
991     
992         blt.src_x = blt.src_y = 0;
993         blt.attribute = 0;
994         blt.dst_width = par->width;
995         blt.dst_height = par->height;
996         blt.dst_y = fb->var.yoffset;
997         blt.dst_x = fb->var.xoffset;
998         blt.operation = BLT_WRITE_ROP;
999         blt.rop = 0x0c; // ROP: destination = source
1000         blt.src = (u16*)(info->shadow.fb + blt.dst_x * par->Bpp +
1001                          blt.dst_y * stride);
1002
1003         doBlt(par, info, &blt);
1004     
1005         info->shadow.timer.expires = jiffies+HZ/2;
1006         add_timer(&info->shadow.timer);
1007
1008         //DPRINTK("delta jiffies = %ld\n", jiffies - j_start);
1009 }
1010 #endif
1011
1012
1013 /* ------------------------------------------------------------------------- 
1014  *              Hardware independent part, interface to the world
1015  * ------------------------------------------------------------------------- */
1016
1017 static void
1018 e1356_cfbX_clear_margins(struct vc_data* conp, struct display* p,
1019                          int bottom_only)
1020 {
1021         blt_info_t blt;
1022         unsigned int cw=fontwidth(p);
1023         unsigned int ch=fontheight(p);
1024         unsigned int rw=p->var.xres % cw;
1025         unsigned int bh=p->var.yres % ch;
1026         unsigned int rs=p->var.xres - rw;
1027         unsigned int bs=p->var.yres - bh;
1028
1029         //DPRINTK("\n");
1030
1031         if (!bottom_only && rw) { 
1032                 blt.dst_x = p->var.xoffset+rs;
1033                 blt.dst_y = p->var.yoffset;
1034                 blt.dst_height = p->var.yres;
1035                 blt.dst_width = rw;
1036                 blt.attribute = 0;
1037                 blt.fg_color = 0;
1038                 blt.operation = BLT_SOLID_FILL;
1039                 doBlt (&fb_info.current_par, &fb_info, &blt);
1040         }
1041     
1042         if (bh) { 
1043                 blt.dst_x = p->var.xoffset;
1044                 blt.dst_y = p->var.yoffset+bs;
1045                 blt.dst_height = bh;
1046                 blt.dst_width = rs;
1047                 blt.attribute = 0;
1048                 blt.fg_color = 0;
1049                 blt.operation = BLT_SOLID_FILL;
1050                 doBlt (&fb_info.current_par, &fb_info, &blt);
1051         }
1052 }
1053
1054 static void
1055 e1356_cfbX_bmove(struct display* p, 
1056                  int sy, 
1057                  int sx, 
1058                  int dy,
1059                  int dx, 
1060                  int height, 
1061                  int width)
1062 {
1063         blt_info_t blt;
1064     
1065         //DPRINTK("(%d,%d) to (%d,%d) size (%d,%d)\n", sx,sy,dx,dy,width,height);
1066
1067         blt.src_x = fontwidth_x8(p)*sx;
1068         blt.src_y = fontheight(p)*sy;
1069         blt.dst_x = fontwidth_x8(p)*dx;
1070         blt.dst_y = fontheight(p)*dy;
1071         blt.src_height = blt.dst_height = fontheight(p)*height;
1072         blt.src_width = blt.dst_width = fontwidth_x8(p)*width;
1073         blt.attribute = 0;
1074         blt.rop = 0x0c;
1075         /*
1076          * The move BLT routine will actually decide between a pos/neg
1077          * move BLT. This is just so that the BLT dispatcher knows to
1078          * call the move BLT routine.
1079          */
1080         blt.operation = BLT_MOVE_POS_ROP;
1081
1082         doBlt (&fb_info.current_par, &fb_info, &blt);
1083 }
1084
1085 static void
1086 e1356_cfb8_putc(struct vc_data* conp,
1087                 struct display* p,
1088                 int c, int yy,int xx)
1089 {   
1090         blt_info_t blt;
1091         u32 fgx,bgx;
1092         u32 fw = fontwidth_x8(p);
1093         u32 fh = fontheight(p);
1094         u16 cs = (u16)c;
1095
1096         fgx = attr_fgcol(p, c);
1097         bgx = attr_bgcol(p, c);
1098
1099         blt.src_x = blt.src_y = 0;
1100         blt.attribute = 0;
1101         blt.dst_width = fw;
1102         blt.dst_height = fh;
1103         blt.dst_y = yy * fh;
1104         blt.dst_x = xx * fw;
1105         blt.bg_color = bgx;
1106         blt.fg_color = fgx;
1107         blt.operation = BLT_COLOR_EXP;
1108         blt.src = fb_info.putcs_buffer;
1109         fill_putcs_buffer(p, &blt, &cs, 1);
1110
1111         doBlt(&fb_info.current_par, &fb_info, &blt);
1112
1113 }
1114
1115 static void
1116 e1356_cfb16_putc(struct vc_data* conp,
1117                  struct display* p,
1118                  int c, int yy,int xx)
1119 {   
1120         blt_info_t blt;
1121         u32 fgx,bgx;
1122         u32 fw = fontwidth_x8(p);
1123         u32 fh = fontheight(p);
1124         u16 cs = (u16)c;
1125     
1126         fgx = ((u16*)p->dispsw_data)[attr_fgcol(p,c)];
1127         bgx = ((u16*)p->dispsw_data)[attr_bgcol(p,c)];
1128
1129         blt.src_x = blt.src_y = 0;
1130         blt.attribute = 0;
1131         blt.dst_width = fw;
1132         blt.dst_height = fh;
1133         blt.dst_y = yy * fh;
1134         blt.dst_x = xx * fw;
1135         blt.bg_color = bgx;
1136         blt.fg_color = fgx;
1137         blt.operation = BLT_COLOR_EXP;
1138         blt.src = fb_info.putcs_buffer;
1139         fill_putcs_buffer(p, &blt, &cs, 1);
1140
1141         doBlt(&fb_info.current_par, &fb_info, &blt);
1142 }
1143
1144
1145 static void
1146 e1356_cfb8_putcs(struct vc_data* conp,
1147                  struct display* p,
1148                  const unsigned short *s,int count,int yy,int xx)
1149 {
1150         blt_info_t blt;
1151         u32 fgx,bgx;
1152         u32 fw = fontwidth_x8(p);
1153         u32 fh = fontheight(p);
1154
1155         //DPRINTK("\n");
1156
1157         fgx=attr_fgcol(p, *s);
1158         bgx=attr_bgcol(p, *s);
1159
1160         blt.src_x = blt.src_y = 0;
1161         blt.attribute = 0;
1162         blt.dst_width = count * fw;
1163         blt.dst_height = fh;
1164         blt.dst_y = yy * fh;
1165         blt.dst_x = xx * fw;
1166         blt.bg_color = bgx;
1167         blt.fg_color = fgx;
1168         blt.operation = BLT_COLOR_EXP;
1169         blt.src = fb_info.putcs_buffer;
1170         fill_putcs_buffer(p, &blt, s, count);
1171
1172         doBlt(&fb_info.current_par, &fb_info, &blt);
1173 }
1174
1175 static void
1176 e1356_cfb16_putcs(struct vc_data* conp,
1177                   struct display* p,
1178                   const unsigned short *s,int count,int yy,int xx)
1179 {
1180         blt_info_t blt;
1181         u32 fgx,bgx;
1182         u32 fw = fontwidth_x8(p);
1183         u32 fh = fontheight(p);
1184
1185         //DPRINTK("\n");
1186
1187         fgx=((u16*)p->dispsw_data)[attr_fgcol(p,*s)];
1188         bgx=((u16*)p->dispsw_data)[attr_bgcol(p,*s)];
1189
1190         blt.src_x = blt.src_y = 0;
1191         blt.attribute = 0;
1192         blt.dst_width = count * fw;
1193         blt.dst_height = fh;
1194         blt.dst_y = yy * fh;
1195         blt.dst_x = xx * fw;
1196         blt.bg_color = bgx;
1197         blt.fg_color = fgx;
1198         blt.operation = BLT_COLOR_EXP;
1199         blt.src = fb_info.putcs_buffer;
1200         fill_putcs_buffer(p, &blt, s, count);
1201
1202         doBlt(&fb_info.current_par, &fb_info, &blt);
1203 }
1204
1205
1206 static void
1207 e1356_cfb8_clear(struct vc_data* conp, 
1208                  struct display* p, 
1209                  int sy,
1210                  int sx, 
1211                  int height, 
1212                  int width)
1213 {
1214         blt_info_t blt;
1215         u32 bg = attr_bgcol_ec(p,conp);
1216
1217         //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height);
1218
1219         blt.dst_x = fontwidth_x8(p)*sx;
1220         blt.dst_y = fontheight(p)*sy;
1221         blt.dst_height = fontheight(p)*height;
1222         blt.dst_width = fontwidth_x8(p)*width;
1223         blt.attribute = 0;
1224         blt.fg_color = bg;
1225         blt.operation = BLT_SOLID_FILL;
1226
1227         doBlt (&fb_info.current_par, &fb_info, &blt);
1228 }
1229
1230 static void
1231 e1356_cfb16_clear(struct vc_data* conp, 
1232                   struct display* p, 
1233                   int sy,
1234                   int sx, 
1235                   int height, 
1236                   int width)
1237 {
1238         blt_info_t blt;
1239         u32 bg = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
1240
1241         //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height);
1242
1243         blt.dst_x = fontwidth_x8(p)*sx;
1244         blt.dst_y = fontheight(p)*sy;
1245         blt.dst_height = fontheight(p)*height;
1246         blt.dst_width = fontwidth_x8(p)*width;
1247         blt.attribute = 0;
1248         blt.fg_color = bg;
1249         blt.operation = BLT_SOLID_FILL;
1250
1251         doBlt (&fb_info.current_par, &fb_info, &blt);
1252 }
1253
1254
1255 static void
1256 e1356_cfbX_revc(struct display *p, int xx, int yy)
1257 {
1258         // not used if h/w cursor
1259         //DPRINTK("\n");
1260 }
1261
1262 static void
1263 e1356_cfbX_cursor(struct display *p, int mode, int x, int y) 
1264 {
1265         unsigned long flags;
1266         struct fb_info_e1356 *info=(struct fb_info_e1356 *)p->fb_info;
1267         reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
1268                 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
1269     
1270         //DPRINTK("\n");
1271
1272         if (mode == CM_ERASE) {
1273                 if (info->cursor.state != CM_ERASE) {
1274                         spin_lock_irqsave(&info->cursor.lock,flags);
1275                         info->cursor.state = CM_ERASE;
1276                         del_timer(&(info->cursor.timer));
1277                         writeb(0x00, &inkcurs->ctrl);
1278                         spin_unlock_irqrestore(&info->cursor.lock,flags);
1279                 }
1280                 return;
1281         }
1282     
1283         if ((p->conp->vc_cursor_type & CUR_HWMASK) != info->cursor.type)
1284                 e1356fb_createcursor(p);
1285     
1286         x *= fontwidth_x8(p);
1287         y *= fontheight(p);
1288         x -= p->var.xoffset;
1289         y -= p->var.yoffset;
1290     
1291         spin_lock_irqsave(&info->cursor.lock,flags);
1292         if ((x != info->cursor.x) || (y != info->cursor.y) ||
1293             (info->cursor.redraw)) {
1294                 info->cursor.x = x;
1295                 info->cursor.y = y;
1296                 info->cursor.redraw = 0;
1297                 writeb(0x01, &inkcurs->ctrl);
1298                 writew(x, &inkcurs->x_pos0);
1299                 writew(y, &inkcurs->y_pos0);
1300                 /* fix cursor color - XFree86 forgets to restore it properly */
1301                 writeb(0x00, &inkcurs->blue0);
1302                 writeb(0x00, &inkcurs->green0);
1303                 writeb(0x00, &inkcurs->red0);
1304                 writeb(0x1f, &inkcurs->blue1);
1305                 writeb(0x3f, &inkcurs->green1);
1306                 writeb(0x1f, &inkcurs->red1);
1307         }
1308
1309         info->cursor.state = CM_DRAW;
1310         mod_timer(&info->cursor.timer, jiffies+HZ/2);
1311         spin_unlock_irqrestore(&info->cursor.lock,flags);
1312 }
1313
1314 #ifdef FBCON_HAS_CFB8
1315 static struct display_switch fbcon_e1356_8 = {
1316         setup:          fbcon_cfb8_setup, 
1317         bmove:          e1356_cfbX_bmove, 
1318         clear:          e1356_cfb8_clear, 
1319         putc:           e1356_cfb8_putc,
1320         putcs:          e1356_cfb8_putcs, 
1321         revc:           e1356_cfbX_revc,   
1322         cursor:         e1356_cfbX_cursor, 
1323         clear_margins:  e1356_cfbX_clear_margins,
1324         fontwidthmask:  FONTWIDTHRANGE(6,16)
1325 };
1326 #endif
1327
1328 #ifdef FBCON_HAS_CFB16
1329 static struct display_switch fbcon_e1356_16 = {
1330         setup:          fbcon_cfb16_setup, 
1331         bmove:          e1356_cfbX_bmove, 
1332         clear:          e1356_cfb16_clear, 
1333         putc:           e1356_cfb16_putc,
1334         putcs:          e1356_cfb16_putcs, 
1335         revc:           e1356_cfbX_revc, 
1336         cursor:         e1356_cfbX_cursor, 
1337         clear_margins:  e1356_cfbX_clear_margins,
1338         fontwidthmask:  FONTWIDTHRANGE(6,16)
1339 };
1340 #endif
1341
1342 /* ------------------------------------------------------------------------- */
1343
1344 static void
1345 e1356fb_set_par(const struct e1356fb_par* par,
1346                 struct fb_info_e1356* info)
1347 {
1348         reg_dispcfg_t* dispcfg=NULL;
1349         reg_dispmode_t* dispmode=NULL;
1350         u8* pclk_cfg=NULL;
1351         u8 width, hndp=0, hsync_start=0, hsync_width=0;
1352         u8 vndp, vsync_start, vsync_width=0, display_mode;
1353         u8 main_display_mode=0;
1354         u16 height, addr_offset;
1355         int disp_type = info->fix.disp_type;
1356
1357         DPRINTK("%dx%d-%dbpp @ %d Hz, %d kHz hsync\n",
1358                 par->width, par->height, par->bpp,
1359                 par->vsync_freq, (((2*par->hsync_freq)/1000)+1)/2);
1360 #ifdef E1356FB_VERBOSE_DEBUG
1361         dump_par(par);
1362 #endif
1363     
1364         info->current_par = *par;
1365
1366         width = (par->width >> 3) - 1;
1367         display_mode = (par->bpp == 8) ? 0x03 : 0x05;
1368         addr_offset = (par->width_virt * par->Bpp) / 2;
1369         vsync_start = (disp_type == DISP_TYPE_LCD) ? 0 : par->vsync_start - 1;
1370         height = par->height - 1;
1371         vndp = par->vert_ndp - 1;
1372
1373         switch (disp_type) {
1374         case DISP_TYPE_LCD:
1375                 dispcfg = info->reg.lcd_cfg;
1376                 dispmode = info->reg.lcd_mode;
1377                 pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg;
1378                 hndp = (par->horiz_ndp >> 3) - 1;
1379                 hsync_start = 0;
1380                 hsync_width = par->hsync_pol ? 0x00 : 0x80;
1381                 vsync_width = par->vsync_pol ? 0x00 : 0x80;
1382                 main_display_mode = 0x01;
1383                 break;
1384         case DISP_TYPE_TFT:
1385                 dispcfg = info->reg.lcd_cfg;
1386                 dispmode = info->reg.lcd_mode;
1387                 pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg;
1388                 hndp = (par->horiz_ndp >> 3) - 1;
1389                 hsync_start = (par->bpp == 8) ?
1390                         (par->hsync_start - 4) >> 3 :
1391                                 (par->hsync_start - 6) >> 3;
1392                 hsync_width =
1393                         (par->hsync_pol ? 0x80 : 0x00) |
1394                         ((par->hsync_width >> 3) - 1);
1395                 vsync_width =
1396                         (par->vsync_pol ? 0x80 : 0x00) |
1397                         (par->vsync_width - 1);
1398                 main_display_mode = 0x01;
1399                 break;
1400         case DISP_TYPE_CRT:
1401                 dispcfg = info->reg.crttv_cfg;
1402                 dispmode = info->reg.crttv_mode;
1403                 pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg;
1404                 hndp = (par->horiz_ndp >> 3) - 1;
1405                 hsync_start = (par->bpp == 8) ?
1406                         (par->hsync_start - 3) >> 3 :
1407                                 (par->hsync_start - 5) >> 3;
1408                 hsync_width =
1409                         (par->hsync_pol ? 0x80 : 0x00) |
1410                         ((par->hsync_width >> 3) - 1);
1411                 vsync_width =
1412                         (par->vsync_pol ? 0x80 : 0x00) |
1413                         (par->vsync_width - 1);
1414                 main_display_mode = 0x02;
1415                 break;
1416         case DISP_TYPE_NTSC:
1417         case DISP_TYPE_PAL:
1418                 dispcfg = info->reg.crttv_cfg;
1419                 dispmode = info->reg.crttv_mode;
1420                 pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg;
1421                 hndp = (disp_type == DISP_TYPE_PAL) ?
1422                         (par->horiz_ndp - 7) >> 3 :
1423                                 (par->horiz_ndp - 6) >> 3;
1424                 hsync_start = (par->bpp == 8) ?
1425                         (par->hsync_start + 7) >> 3 :
1426                                 (par->hsync_start + 5) >> 3;
1427                 hsync_width = 0;
1428                 vsync_width = 0;
1429                 main_display_mode = (info->fix.tv_filt & TV_FILT_FLICKER) ?
1430                         0x06 : 0x04;
1431                 break;
1432         }
1433
1434         // Blast the regs!
1435         // note: reset panning/scrolling (set start-addr and
1436         // pixel pan regs to 0). Panning is handled by pan_display.
1437
1438         e1356_engine_wait_complete(info->reg.bitblt);
1439
1440         // disable display while initializing
1441         writeb(0, &info->reg.misc->disp_mode);
1442
1443         writeb(par->ipclk.pixclk_bits, pclk_cfg);
1444
1445         writeb(width, &dispcfg->hdw);
1446         writeb(hndp, &dispcfg->hndp);
1447         writeb(hsync_start, &dispcfg->hsync_start);
1448         writeb(hsync_width, &dispcfg->hsync_pulse);
1449         writew(height, &dispcfg->vdh0);
1450         writeb(vndp, &dispcfg->vndp);
1451         writeb(vsync_start, &dispcfg->vsync_start);
1452         writeb(vsync_width, &dispcfg->vsync_pulse);
1453
1454         writeb(display_mode, &dispmode->disp_mode);
1455         if (info->fix.mmunalign && info->mmaped)
1456                 writeb(1, &dispmode->start_addr0);
1457         else
1458                 writeb(0, &dispmode->start_addr0);
1459         writeb(0, &dispmode->start_addr1);
1460         writeb(0, &dispmode->start_addr2);
1461         writew(addr_offset, &dispmode->mem_addr_offset0);
1462         writeb(0, &dispmode->pixel_panning);
1463
1464         // reset BitBlt engine
1465         e1356fb_engine_init(par, info);
1466
1467 #ifdef E1356FB_VERBOSE_DEBUG
1468         dump_display_regs(dispcfg, dispmode);
1469 #endif
1470
1471         /* clear out framebuffer memory */
1472         fbfill(fb_info.membase_virt, 0, fb_info.fb_size);
1473         // finally, enable display!
1474         writeb(main_display_mode, &info->reg.misc->disp_mode); 
1475 }
1476
1477
1478 static int
1479 e1356fb_verify_timing(struct e1356fb_par* par,
1480                       const struct fb_info_e1356* info)
1481 {
1482         int disp_type = info->fix.disp_type;
1483
1484         // timing boundary checks
1485         if (par->horiz_ndp > max_hndp[disp_type]) {
1486                 DPRINTK("horiz_ndp too big: %d\n", par->horiz_ndp);
1487                 return -EINVAL;
1488         }
1489         if (par->vert_ndp > max_vndp[disp_type]) {
1490                 DPRINTK("vert_ndp too big: %d\n", par->vert_ndp);
1491                 return -EINVAL;
1492         }
1493
1494         if (disp_type != DISP_TYPE_LCD) {
1495                 if (par->hsync_start >
1496                     max_hsync_start[(par->bpp==16)][disp_type]) {
1497                         DPRINTK("hsync_start too big: %d\n",
1498                                 par->hsync_start);
1499                         return -EINVAL;
1500                 }
1501                 if (par->vsync_start > max_vsync_start[disp_type]) {
1502                         DPRINTK("vsync_start too big: %d\n",
1503                                 par->vsync_start);
1504                         return -EINVAL;
1505                 }
1506                 if (!IS_TV(disp_type)) {
1507                         if (par->hsync_width > max_hsync_width[disp_type]) {
1508                                 DPRINTK("hsync_width too big: %d\n",
1509                                         par->hsync_width);
1510                                 return -EINVAL;
1511                         }
1512                         if (par->vsync_width > max_vsync_width[disp_type]) {
1513                                 DPRINTK("vsync_width too big: %d\n",
1514                                         par->vsync_width);
1515                                 return -EINVAL;
1516                         }
1517                 }
1518         }
1519
1520         if (IS_TV(disp_type)) {
1521                 int tv_pixclk = (disp_type == DISP_TYPE_NTSC) ?
1522                         NTSC_PIXCLOCK : PAL_PIXCLOCK;
1523                 if (info->fix.tv_filt & TV_FILT_FLICKER)
1524                         tv_pixclk *= 2;
1525                 
1526                 if (par->ipclk.pixclk_d != tv_pixclk) {
1527                         DPRINTK("invalid TV pixel clock %u kHz\n",
1528                                 par->ipclk.pixclk_d);
1529                         return -EINVAL;
1530                 }
1531         }
1532         
1533         if (e1356_calc_pixclock(info, &par->ipclk) < 0) {
1534                 DPRINTK("can't set pixel clock %u kHz\n",
1535                         par->ipclk.pixclk_d);
1536                 return -EINVAL;
1537         }
1538  
1539 #ifdef E1356FB_VERBOSE_DEBUG
1540         DPRINTK("desired pixclock = %d kHz, actual = %d kHz, error = %d%%\n",
1541                 par->ipclk.pixclk_d, par->ipclk.pixclk, par->ipclk.error);
1542 #endif
1543     
1544         if (disp_type != DISP_TYPE_LCD) {
1545                 if (par->horiz_ndp < par->hsync_start + par->hsync_width) {
1546                         DPRINTK("invalid horiz. timing\n");
1547                         return -EINVAL;
1548                 }
1549                 if (par->vert_ndp < par->vsync_start + par->vsync_width) {
1550                         DPRINTK("invalid vert. timing\n");
1551                         return -EINVAL;
1552                 }
1553
1554                 // SED1356 Hardware Functional Spec, section 13.5
1555                 if (disp_type == DISP_TYPE_NTSC &&
1556                     ((par->width + par->horiz_ndp != 910) ||
1557                      (par->height + 2*par->vert_ndp+1 != 525))) {
1558                         DPRINTK("invalid NTSC timing\n");
1559                         return -EINVAL;
1560                 } else if (disp_type == DISP_TYPE_PAL &&
1561                            ((par->width + par->horiz_ndp != 1135) ||
1562                             (par->height + 2*par->vert_ndp+1 != 625))) {
1563                         DPRINTK("invalid PAL timing\n");
1564                         return -EINVAL;
1565                 }
1566         }
1567     
1568         par->hsync_freq = (1000 * par->ipclk.pixclk) /
1569                 (par->width + par->horiz_ndp);
1570         par->vsync_freq = par->hsync_freq / (par->height + par->vert_ndp);
1571         
1572         if (par->hsync_freq < 30000 || par->hsync_freq > 90000) {
1573                 DPRINTK("hsync freq too %s: %u Hz\n",
1574                         par->hsync_freq < 30000 ? "low" : "high",
1575                         par->hsync_freq);
1576                 return -EINVAL;
1577         }
1578         if (par->vsync_freq < 50 || par->vsync_freq > 110) {
1579                 DPRINTK("vsync freq too %s: %u Hz\n",
1580                         par->vsync_freq < 50 ? "low" : "high",
1581                         par->vsync_freq);
1582                 return -EINVAL;
1583         }
1584
1585         return 0;
1586 }
1587
1588 static int
1589 e1356fb_verify_par(struct e1356fb_par* par,
1590                    const struct fb_info_e1356* info)
1591 {
1592         int disp_type = info->fix.disp_type;
1593     
1594         if (par->bpp != 8 && par->bpp != 16) {
1595                 DPRINTK("depth not supported: %u bpp\n", par->bpp);
1596                 return -EINVAL;
1597         }
1598
1599         if (par->width > par->width_virt) {
1600                 DPRINTK("virtual x resolution < physical x resolution not possible\n");
1601                 return -EINVAL;
1602         }
1603
1604         if (par->height > par->height_virt) {
1605                 DPRINTK("virtual y resolution < physical y resolution not possible\n");
1606                 return -EINVAL;
1607         }
1608
1609         if (par->width < 320 || par->width > 1024) {
1610                 DPRINTK("width not supported: %u\n", par->width);
1611                 return -EINVAL;
1612         }
1613
1614         if ((disp_type == DISP_TYPE_LCD && (par->width % 16)) ||
1615             (disp_type == DISP_TYPE_TFT && (par->width % 8))) {
1616                 DPRINTK("invalid width for panel type: %u\n", par->width);
1617                 return -EINVAL;
1618         }
1619
1620         if (par->height < 200 || par->height > 1024) {
1621                 DPRINTK("height not supported: %u\n", par->height);
1622                 return -EINVAL;
1623         }
1624
1625         if (par->width_virt * par->height_virt * par->Bpp >
1626             info->fb_size) {
1627                 DPRINTK("not enough memory for virtual screen (%ux%ux%u)\n",
1628                         par->width_virt, par->height_virt, par->bpp);
1629                 return -EINVAL;
1630         }
1631
1632         return e1356fb_verify_timing(par, info);
1633 }
1634
1635
1636 static int
1637 e1356fb_var_to_par(const struct fb_var_screeninfo* var,
1638                    struct e1356fb_par* par,
1639                    const struct fb_info_e1356* info)
1640 {
1641         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1642                 DPRINTK("interlace not supported\n");
1643                 return -EINVAL;
1644         }
1645
1646         memset(par, 0, sizeof(struct e1356fb_par));
1647
1648         par->width       = (var->xres + 15) & ~15; /* could sometimes be 8 */
1649         par->width_virt  = var->xres_virtual;
1650         par->height      = var->yres;
1651         par->height_virt = var->yres_virtual;
1652         par->bpp         = var->bits_per_pixel;
1653         par->Bpp         = (par->bpp + 7) >> 3;
1654
1655         par->ipclk.pixclk_d = PICOS2KHZ(var->pixclock);
1656
1657         par->hsync_start = var->right_margin;
1658         par->hsync_width = var->hsync_len;
1659
1660         par->vsync_start = var->lower_margin;
1661         par->vsync_width = var->vsync_len;
1662
1663         par->horiz_ndp = var->left_margin + var->right_margin + var->hsync_len;
1664         par->vert_ndp = var->upper_margin + var->lower_margin + var->vsync_len;
1665
1666         par->hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
1667         par->vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
1668
1669         par->cmap_len  = (par->bpp == 8) ? 256 : 16;
1670
1671         return e1356fb_verify_par(par, info);
1672 }
1673
1674 static int
1675 e1356fb_par_to_var(struct fb_var_screeninfo* var,
1676                    struct e1356fb_par* par,
1677                    const struct fb_info_e1356* info)
1678 {
1679         struct fb_var_screeninfo v;
1680         int ret;
1681     
1682         // First, make sure par is valid.
1683         if ((ret = e1356fb_verify_par(par, info)))
1684                 return ret;
1685
1686         memset(&v, 0, sizeof(struct fb_var_screeninfo));
1687         v.xres_virtual   = par->width_virt;
1688         v.yres_virtual   = par->height_virt;
1689         v.xres           = par->width;
1690         v.yres           = par->height;
1691         v.right_margin   = par->hsync_start;
1692         v.hsync_len      = par->hsync_width;
1693         v.left_margin    = par->horiz_ndp - par->hsync_start - par->hsync_width;
1694         v.lower_margin   = par->vsync_start;
1695         v.vsync_len      = par->vsync_width;
1696         v.upper_margin   = par->vert_ndp - par->vsync_start - par->vsync_width;
1697         v.bits_per_pixel = par->bpp;
1698
1699         switch(par->bpp) {
1700         case 8:
1701                 v.red.offset = v.green.offset = v.blue.offset = 0;
1702                 v.red.length = v.green.length = v.blue.length = 4;
1703                 break;
1704         case 16:
1705                 v.red.offset   = 11;
1706                 v.red.length   = 5;
1707                 v.green.offset = 5;
1708                 v.green.length = 6;
1709                 v.blue.offset  = 0;
1710                 v.blue.length  = 5;
1711                 break;
1712         }
1713
1714         v.height = v.width = -1;
1715         v.pixclock = KHZ2PICOS(par->ipclk.pixclk);
1716
1717         if (par->hsync_pol)
1718                 v.sync |= FB_SYNC_HOR_HIGH_ACT;
1719         if (par->vsync_pol)
1720                 v.sync |= FB_SYNC_VERT_HIGH_ACT;
1721
1722         *var = v;
1723         return 0;
1724 }
1725
1726 static int
1727 e1356fb_encode_fix(struct fb_fix_screeninfo*  fix,
1728                    const struct e1356fb_par*   par,
1729                    const struct fb_info_e1356* info)
1730 {
1731         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1732     
1733         strcpy(fix->id, "Epson SED1356");
1734         fix->smem_start  = info->fix.membase_phys;
1735         fix->smem_len    = info->fb_size;
1736         fix->mmio_start  = info->fix.regbase_phys;
1737         fix->mmio_len    = info->regbase_size;
1738         fix->accel       = FB_ACCEL_EPSON_SED1356;
1739         fix->type        = FB_TYPE_PACKED_PIXELS;
1740         fix->type_aux    = 0;
1741         fix->line_length = par->width_virt * par->Bpp;
1742         fix->visual      =
1743                 (par->bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1744     
1745         fix->xpanstep    = info->fix.nopan ? 0 : 1;
1746         fix->ypanstep    = info->fix.nopan ? 0 : 1;
1747         fix->ywrapstep   = 0;
1748     
1749         return 0;
1750 }
1751
1752 static int e1356fb_open(struct fb_info *fb, int user)
1753 {
1754         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1755         if (user) {
1756                 info->open++;
1757         }
1758         MOD_INC_USE_COUNT;
1759         return 0;
1760 }
1761
1762 static int e1356fb_release(struct fb_info *fb, int user)
1763 {
1764         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1765         if (user && info->open) {
1766                 info->open--;
1767                 if (info->open == 0)
1768                         info->mmaped = 0;
1769         }
1770         MOD_DEC_USE_COUNT;
1771         return 0;
1772 }
1773
1774 static int
1775 e1356fb_get_fix(struct fb_fix_screeninfo *fix, 
1776                 int con,
1777                 struct fb_info *fb)
1778 {
1779         const struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1780         struct e1356fb_par par;
1781
1782         //DPRINTK("\n");
1783
1784         if (con == -1)
1785                 par = info->current_par;
1786         else
1787                 e1356fb_var_to_par(&fb_display[con].var, &par, info);
1788         e1356fb_encode_fix(fix, &par, info);
1789         return 0;
1790 }
1791
1792 static int
1793 e1356fb_get_var(struct fb_var_screeninfo *var, 
1794                 int con,
1795                 struct fb_info *fb)
1796 {
1797         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1798
1799         //DPRINTK("\n");
1800
1801         if (con == -1)
1802                 e1356fb_par_to_var(var, &info->current_par, info);
1803         else
1804                 *var = fb_display[con].var;
1805         return 0;
1806 }
1807  
1808 static void
1809 e1356fb_set_dispsw(struct display *disp, 
1810                    struct fb_info_e1356 *info,
1811                    int bpp, 
1812                    int accel)
1813 {
1814         struct e1356fb_fix* fix = &info->fix;
1815         //DPRINTK("\n");
1816
1817         if (disp->dispsw && disp->conp) 
1818                 fb_con.con_cursor(disp->conp, CM_ERASE);
1819         switch (bpp) {
1820 #ifdef FBCON_HAS_CFB8
1821         case 8:
1822                 disp->dispsw = fix->noaccel ? &fbcon_cfb8 : &fbcon_e1356_8;
1823                 if (fix->nohwcursor)
1824                         fbcon_e1356_8.cursor = NULL;
1825                 break;
1826 #endif
1827 #ifdef FBCON_HAS_CFB16
1828         case 16:
1829                 disp->dispsw = fix->noaccel ? &fbcon_cfb16 : &fbcon_e1356_16;
1830                 disp->dispsw_data = info->fbcon_cmap16;
1831                 if (fix->nohwcursor)
1832                         fbcon_e1356_16.cursor = NULL;
1833                 break;
1834 #endif
1835         default:
1836                 disp->dispsw = &fbcon_dummy;
1837         }
1838    
1839 }
1840
1841 static int
1842 e1356fb_set_var(struct fb_var_screeninfo *var, 
1843                 int con,
1844                 struct fb_info *fb)
1845 {
1846         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1847         struct e1356fb_par par;
1848         struct display *display;
1849         int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
1850         int activate = var->activate;
1851         int j,k;
1852     
1853         DPRINTK("\n");
1854         
1855         if (con >= 0)
1856                 display = &fb_display[con];
1857         else
1858                 display = fb->disp;     /* used during initialization */
1859    
1860         if ((err = e1356fb_var_to_par(var, &par, info))) {
1861                 struct fb_videomode *dm;
1862                 /*
1863                  * this mode didn't pass the tests. Try the
1864                  * corresponding mode from our own modedb.
1865                  */
1866                 DPRINTK("req mode failed, trying SED1356 %dx%d mode\n",
1867                         var->xres, var->yres);
1868                 if (e1356fb_get_mode(info, var->xres,
1869                                      var->yres, NULL, &dm) < 0) {
1870                         DPRINTK("no SED1356 %dx%d mode found, failed\n",
1871                                 var->xres, var->yres);
1872                         return err;
1873                 }
1874                 fb_videomode_to_var(dm, var);
1875                 if ((err = e1356fb_var_to_par(var, &par, info))) {
1876                         DPRINTK("SED1356 %dx%d mode failed\n",
1877                                 var->xres, var->yres);
1878                         return err;
1879                 }
1880         }
1881         
1882         if (info->fix.tv_filt & TV_FILT_FLICKER)
1883                 printk("e1356fb: TV flicker filter enabled\n");
1884     
1885         e1356fb_par_to_var(var, &par, info);
1886    
1887         if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1888                 oldxres  = display->var.xres;
1889                 oldyres  = display->var.yres;
1890                 oldvxres = display->var.xres_virtual;
1891                 oldvyres = display->var.yres_virtual;
1892                 oldbpp   = display->var.bits_per_pixel;
1893                 oldaccel = display->var.accel_flags;
1894                 display->var = *var;
1895                 if (con < 0                         ||
1896                     oldxres  != var->xres           || 
1897                     oldyres  != var->yres           ||
1898                     oldvxres != var->xres_virtual   || 
1899                     oldvyres != var->yres_virtual   ||
1900                     oldbpp   != var->bits_per_pixel || 
1901                     oldaccel != var->accel_flags) {
1902                         struct fb_fix_screeninfo fix;
1903             
1904                         e1356fb_encode_fix(&fix, &par, info);
1905                         display->screen_base    = info->membase_virt;
1906                         display->visual         = fix.visual;
1907                         display->type           = fix.type;
1908                         display->type_aux       = fix.type_aux;
1909                         display->ypanstep       = fix.ypanstep;
1910                         display->ywrapstep      = fix.ywrapstep;
1911                         display->line_length    = fix.line_length;
1912                         display->next_line      = fix.line_length;
1913                         display->can_soft_blank = 1;
1914                         display->inverse        = 0;
1915                         accel = var->accel_flags & FB_ACCELF_TEXT;
1916                         e1356fb_set_dispsw(display, info, par.bpp, accel);
1917          
1918                         if (info->fix.nopan)
1919                                 display->scrollmode = SCROLL_YREDRAW;
1920         
1921                         if (info->fb_info.changevar)
1922                                 (*info->fb_info.changevar)(con);
1923                 }
1924                 if (var->bits_per_pixel==8)
1925                         for(j = 0; j < 16; j++) {
1926                                 k = color_table[j];
1927                                 fb_info.palette[j].red   = default_red[k];
1928                                 fb_info.palette[j].green = default_grn[k];
1929                                 fb_info.palette[j].blue  = default_blu[k];
1930                         }
1931       
1932                 del_timer(&(info->cursor.timer)); 
1933                 fb_info.cursor.state=CM_ERASE;
1934         
1935                 if (!info->fb_info.display_fg ||
1936                     info->fb_info.display_fg->vc_num == con || con < 0)
1937                         e1356fb_set_par(&par, info);
1938
1939                 if (!info->fix.nohwcursor) 
1940                         if (display && display->conp)
1941                                 e1356fb_createcursor( display );
1942                 info->cursor.redraw = 1;
1943
1944                 if (oldbpp != var->bits_per_pixel || con < 0) {
1945                         if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
1946                                 return err;
1947                         e1356fb_install_cmap(display, &(info->fb_info));
1948                 }
1949         }
1950   
1951         return 0;
1952 }
1953
1954 static int
1955 e1356fb_pan_display(struct fb_var_screeninfo* var, 
1956                     int con,
1957                     struct fb_info* fb)
1958 {
1959         struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
1960         struct e1356fb_par* par = &info->current_par;
1961     
1962         //DPRINTK("\n");
1963
1964         if (info->fix.nopan)
1965                 return -EINVAL;
1966
1967         if ((int)var->xoffset < 0 ||
1968             var->xoffset + par->width > par->width_virt ||
1969             (int)var->yoffset < 0 ||
1970             var->yoffset + par->height > par->height_virt)
1971                 return -EINVAL;
1972     
1973         if (con == currcon)
1974                 do_pan_var(var, info);
1975     
1976         fb_display[con].var.xoffset = var->xoffset;
1977         fb_display[con].var.yoffset = var->yoffset; 
1978
1979         return 0;
1980 }
1981
1982 static int
1983 e1356fb_get_cmap(struct fb_cmap *cmap, 
1984                  int kspc, 
1985                  int con,
1986                  struct fb_info *fb)
1987 {
1988         struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
1989         struct display *d = (con<0) ? fb->disp : fb_display + con;
1990    
1991         //DPRINTK("\n");
1992
1993         if (con == currcon) {
1994                 /* current console? */
1995                 return fb_get_cmap(cmap, kspc, e1356fb_getcolreg, fb);
1996         } else if (d->cmap.len) {
1997                 /* non default colormap? */
1998                 fb_copy_cmap(&d->cmap, cmap, kspc ? 0 : 2);
1999         } else {
2000                 fb_copy_cmap(fb_default_cmap(info->current_par.cmap_len),
2001                              cmap, kspc ? 0 : 2);
2002         }
2003         return 0;
2004 }
2005
2006 static int
2007 e1356fb_set_cmap(struct fb_cmap *cmap, 
2008                  int kspc, 
2009                  int con,
2010                  struct fb_info *fb)
2011 {
2012         struct display *d = (con<0) ? fb->disp : fb_display + con;
2013         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2014         int cmap_len = (info->current_par.bpp == 8) ? 256 : 16;
2015
2016         //DPRINTK("\n");
2017
2018         if (d->cmap.len!=cmap_len) {
2019                 int err;
2020                 if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0)))
2021                         return err;
2022         }
2023     
2024         if (con == currcon) {
2025                 /* current console? */
2026                 return fb_set_cmap(cmap, kspc, e1356fb_setcolreg, fb);
2027         } else {
2028                 fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
2029         }
2030         return 0;
2031 }
2032
2033 static int
2034 e1356fb_mmap(struct fb_info *fb,
2035              struct file *file,
2036              struct vm_area_struct *vma)
2037 {
2038         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2039         unsigned int len;
2040 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
2041         u64 start=0, off;
2042 #else
2043         unsigned long start=0, off;
2044 #endif
2045
2046         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
2047                 DPRINTK("invalid vma->vm_pgoff\n");
2048                 return -EINVAL;
2049         }
2050     
2051 #ifdef SHADOW_FRAME_BUFFER
2052         if (!info->shadow.fb) {
2053                 int order = 0;
2054                 while (info->fb_size > (PAGE_SIZE * (1 << order)))
2055                         order++;
2056                 info->shadow.fb = (void*)__get_free_pages(GFP_KERNEL, order);
2057                 if (!info->shadow.fb) {
2058                         DPRINTK("shadow fb alloc failed\n");
2059                         return -ENXIO;
2060                 }
2061                 memset(info->shadow.fb, 0, info->fb_size);
2062                 init_timer(&info->shadow.timer);
2063                 info->shadow.timer.function = do_write_shadow_fb;
2064                 info->shadow.timer.data = (unsigned long)info;
2065         }
2066         mod_timer(&info->shadow.timer, jiffies+HZ/2);
2067         start = virt_to_phys(info->shadow.fb) & PAGE_MASK;
2068 #else
2069         start = info->fix.membase_phys & PAGE_MASK;
2070 #endif
2071
2072         len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fb_size);
2073
2074         off = vma->vm_pgoff << PAGE_SHIFT;
2075     
2076         if ((vma->vm_end - vma->vm_start + off) > len) {
2077                 DPRINTK("invalid vma\n");
2078                 return -EINVAL;
2079         }
2080
2081         off += start;
2082         vma->vm_pgoff = off >> PAGE_SHIFT;
2083
2084         pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
2085 #ifdef SHADOW_FRAME_BUFFER
2086         vma->vm_flags |= VM_RESERVED;
2087         pgprot_val(vma->vm_page_prot) &= ~_CACHE_UNCACHED;
2088 #else
2089         pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
2090 #endif
2091
2092         /* This is an IO map - tell maydump to skip this VMA */
2093         vma->vm_flags |= VM_IO;
2094         // FIXME: shouldn't have to do this. If the pages are marked writeable,
2095         // the TLB fault handlers should set these.
2096         pgprot_val(vma->vm_page_prot) |= (_PAGE_DIRTY | _PAGE_VALID);
2097     
2098         /*
2099          * The SED1356 has only a 16-bit wide data bus, and some
2100          * embedded platforms, such as the Pb1000, do not automatically
2101          * split 32-bit word accesses to the framebuffer into
2102          * seperate half-word accesses. Hence the upper half-word
2103          * never gets to the framebuffer. The following solution is
2104          * to intentionally return a non-32-bit-aligned VA. As long
2105          * as the user app assumes (and doesn't check) that the returned
2106          * VA is 32-bit aligned, all (assumed aligned) 32-bit accesses
2107          * will actually be unaligned and will get trapped by the MIPS
2108          * unaligned exception handler. This handler will emulate the
2109          * load/store instructions by splitting up the load/store
2110          * into two 16-bit load/stores. (This emulation is currently
2111          * enabled by default, but may be disabled in the future, when
2112          * alignment problems in user-level programs get fixed. When
2113          * that happens, this solution won't work anymore, unless the
2114          * process that mmap's the fb also calls sysmips(MIPS_FIXADE, 1),
2115          * which turns address-error emulation back on).
2116          *
2117          * Furthermore, this solution only seems to work for TinyX
2118          * (Xfbdev). Others, like Qt/E, do snoop the returned VA
2119          * and compensate, or do originally unaligned 32-bit accesses
2120          * which then become aligned, hence breaking this solution.
2121          */
2122         if (info->fix.mmunalign)
2123                 vma->vm_start += 2;
2124         
2125 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
2126         if (e1356_remap_page_range(vma->vm_start, off,
2127                                 vma->vm_end - vma->vm_start,
2128                                 vma->vm_page_prot))
2129                 return -EAGAIN;
2130 #else
2131         if (io_remap_page_range(vma->vm_start, off,
2132                                 vma->vm_end - vma->vm_start,
2133                                 vma->vm_page_prot))
2134                 return -EAGAIN;
2135 #endif
2136
2137         info->mmaped = 1;
2138         return 0;
2139 }
2140
2141
2142 int __init
2143 e1356fb_init(void)
2144 {
2145         struct fb_var_screeninfo var;
2146         struct e1356fb_fix * epfix = &fb_info.fix;
2147         e1356_reg_t* reg;
2148         void* regbase;
2149         char* name = "SED1356";
2150         int periodMCLK, periodBCLK;
2151         int dram_timing, rr_div, mclk_src;
2152         u8 rev_code, btmp, mclk_cfg;
2153
2154         if (options) {
2155                 e1356fb_setup(options, 0);
2156         }
2157
2158         // clear out fb_info
2159         memset(&fb_info, 0, sizeof(struct fb_info_e1356));
2160
2161         // copy boot options
2162         fb_info.fix = boot_fix;
2163         fb_info.default_par = boot_par;
2164
2165         fb_info.regbase_size = E1356_REG_SIZE;
2166
2167         if (!epfix->system) {
2168                 printk(KERN_ERR "e1356/86fb: no valid system found\n");
2169                 return -ENODEV;
2170         }
2171
2172         if (epfix->system == SYS_SDU1356) {
2173                 // it's the SDU1356B0C PCI eval card.
2174                 struct pci_dev *pdev = NULL;
2175                 if (!pci_present())   /* No PCI bus in this machine! */
2176                         return -ENODEV;
2177                 if (!(pdev = pci_find_device(PCI_VENDOR_ID_EPSON,
2178                                              PCI_DEVICE_ID_EPSON_SDU1356, pdev)))
2179                         return -ENODEV;
2180                 if (pci_enable_device(pdev))
2181                         return -ENODEV;
2182                 epfix->regbase_phys = pci_resource_start(pdev, 0);
2183                 epfix->membase_phys = epfix->regbase_phys + E1356_REG_SIZE;
2184         }
2185         
2186         fb_info.regbase_virt = ioremap_nocache(epfix->regbase_phys,
2187                                                E1356_REG_SIZE);
2188
2189         if (!fb_info.regbase_virt) {
2190                 printk("e1356fb: Can't remap %s register area.\n", name);
2191                 return -ENXIO;
2192         }
2193
2194         regbase = fb_info.regbase_virt;
2195         reg = &fb_info.reg;
2196     
2197         // Initialize the register pointers
2198         reg->basic =         (reg_basic_t*)   (regbase + REG_BASE_BASIC);
2199         reg->genio =         (reg_genio_t*)   (regbase + REG_BASE_GENIO);
2200         reg->md_cfg =        (reg_mdcfg_t*)   (regbase + REG_BASE_MDCFG);
2201         reg->clk_cfg =       (reg_clkcfg_t*)  (regbase + REG_BASE_CLKCFG);
2202         reg->mem_cfg =       (reg_memcfg_t*)  (regbase + REG_BASE_MEMCFG);
2203         reg->panel_cfg =     (reg_panelcfg_t*)(regbase + REG_BASE_PANELCFG);
2204         reg->lcd_cfg =       (reg_dispcfg_t*) (regbase + REG_BASE_LCD_DISPCFG);
2205         reg->crttv_cfg =     (reg_dispcfg_t*) (regbase + REG_BASE_CRTTV_DISPCFG);
2206         reg->lcd_mode =      (reg_dispmode_t*)(regbase + REG_BASE_LCD_DISPMODE);
2207         reg->crttv_mode =    (reg_dispmode_t*)(regbase + REG_BASE_CRTTV_DISPMODE);
2208         reg->lcd_inkcurs =   (reg_inkcurs_t*) (regbase + REG_BASE_LCD_INKCURS);
2209         reg->crttv_inkcurs = (reg_inkcurs_t*) (regbase + REG_BASE_CRTTV_INKCURS);
2210         reg->bitblt =        (reg_bitblt_t*)  (regbase + REG_BASE_BITBLT);
2211         reg->lut =           (reg_lut_t*)     (regbase + REG_BASE_LUT);
2212         reg->pwr_save =      (reg_pwrsave_t*) (regbase + REG_BASE_PWRSAVE);
2213         reg->misc =          (reg_misc_t*)    (regbase + REG_BASE_MISC);
2214         reg->mediaplug =     (reg_mediaplug_t*)(regbase + REG_BASE_MEDIAPLUG);
2215         reg->bitblt_data =   (u16*)           (regbase + REG_BASE_BITBLT_DATA);
2216     
2217         // Enable all register access
2218         writeb(0, &reg->basic->misc);
2219
2220         rev_code = readb(&reg->basic->rev_code);
2221         if ((rev_code >> 2) == 0x04) {
2222                 printk("Found EPSON1356 Display Controller\n");
2223         }
2224         else if ((rev_code >> 2) == 0x07) {
2225                 printk("Found EPSON13806 Display Controller\n");
2226         }
2227         else {
2228                 iounmap(fb_info.regbase_virt);
2229                 printk("e1356/806fb: %s not found, rev_code=0x%02x.\n",
2230                        name, rev_code);
2231                 return -ENODEV;
2232         }
2233
2234         fb_info.chip_rev = rev_code & 0x03;
2235
2236         // Determine frame-buffer size
2237         switch (readb(&reg->md_cfg->md_cfg_stat0) >> 6) {
2238         case 0:
2239         case 2:
2240                 fb_info.fb_size = 0x80000;   /* 512K bytes */
2241                 break;
2242         case 1:
2243                 if ((rev_code >> 2) == 7) /* 806 */
2244                         fb_info.fb_size = 0x140000;  /* 1.2M bytes */
2245                 else
2246                         fb_info.fb_size = 0x200000;  /* 2M bytes */
2247                 break;
2248         default:
2249                 fb_info.fb_size = 0x200000;  /* 2M bytes */
2250                 break;
2251         }
2252
2253         fb_info.membase_virt = ioremap_nocache(epfix->membase_phys,
2254                                                fb_info.fb_size);
2255     
2256         if (!fb_info.membase_virt) {
2257                 printk("e1356fb: Can't remap %s framebuffer.\n", name);
2258                 iounmap(fb_info.regbase_virt);
2259                 return -ENXIO;
2260         }
2261     
2262         printk("e1356/806fb: Detected  %dKB framebuffer\n", 
2263                         (unsigned)fb_info.fb_size/1000);
2264
2265 #ifdef CONFIG_MTRR
2266         if (!epfix->nomtrr) {
2267                 fb_info.mtrr_idx = mtrr_add(epfix->membase_phys, fb_info.fb_size,
2268                                             MTRR_TYPE_WRCOMB, 1);
2269                 printk("e1356fb: MTRR's turned on\n");
2270         }
2271 #endif
2272     
2273         if (!boot_fix.noaccel) {
2274                 /*
2275                   Allocate a page for string BLTs. A 4K page is
2276                   enough for a 256 character string at an 8x16 font.
2277                 */
2278                 fb_info.putcs_buffer = (void*)__get_free_pages(GFP_KERNEL, 0);
2279                 if (fb_info.putcs_buffer == NULL) {
2280                         printk("e1356fb: Can't allocate putcs buffer\n");
2281                         goto unmap_ret_enxio;
2282                 }
2283         }
2284
2285         // Begin SED1356 initialization
2286
2287         // disable display while initializing
2288         writeb(0, &reg->misc->disp_mode);
2289         // Set the GPIO1 and 2 to inputs
2290         writeb(0, &reg->genio->gpio_cfg);
2291         writeb(0, &reg->genio->gpio_ctrl);
2292         if (fb_info.chip_rev == 7) /* 806 */
2293                 writeb(0, &reg->genio->gpio_ctrl2);
2294
2295         /*
2296          * Program the clocks
2297          */
2298
2299 #ifdef CONFIG_MIPS_AU1000
2300         if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
2301                 epfix->busclk = get_au1000_lcd_clock();
2302 #endif
2303         
2304         if (epfix->busclk > 80000) {
2305                 printk("e1356fb: specified busclk too high\n");
2306                 goto ret_enxio;
2307         }
2308
2309         epfix->mclk = mclk_cfg = 0;
2310         if (epfix->system == SYS_PB1500) {
2311                 epfix->mclk = epfix->busclk;
2312                 mclk_cfg = 0x01;
2313         }
2314         else {
2315                 // Find the highest allowable MCLK
2316                 if (epfix->busclk <= MAX_PIXCLOCK && 
2317                                 epfix->busclk > epfix->mclk) {
2318                         epfix->mclk = epfix->busclk;
2319                         mclk_cfg = 0x01;
2320                 }
2321                 if (epfix->clki <= MAX_PIXCLOCK && epfix->clki > epfix->mclk) {
2322                         epfix->mclk = epfix->clki;
2323                         mclk_cfg = 0x00;
2324                 }
2325                 if (epfix->busclk/2 <= MAX_PIXCLOCK && 
2326                                 epfix->busclk/2 > epfix->mclk) {
2327                         epfix->mclk = epfix->busclk/2;
2328                         mclk_cfg = 0x11;
2329                 }
2330                 if (epfix->clki/2 <= MAX_PIXCLOCK && 
2331                                 epfix->clki/2 > epfix->mclk) {
2332                         epfix->mclk = epfix->clki/2;
2333                         mclk_cfg = 0x10;
2334                 }
2335         }
2336         
2337         if (!epfix->mclk) {
2338                 printk("e1356fb: couldn't find an allowable MCLK!\n");
2339                 goto ret_enxio;
2340         }
2341
2342         // When changing mclk src, you must first set bit 4 to 1.
2343         writeb(readb(&reg->clk_cfg->mem_clk_cfg) | 0x10,
2344                &reg->clk_cfg->mem_clk_cfg);
2345         writeb(mclk_cfg, &reg->clk_cfg->mem_clk_cfg);
2346
2347         printk("e1356fb: clocks (kHz): busclk=%d mclk=%d clki=%d clki2=%d\n",
2348                epfix->busclk, epfix->mclk, epfix->clki, epfix->clki2);
2349
2350         // Set max pixel clock
2351         switch (epfix->disp_type) {
2352         case DISP_TYPE_LCD:
2353         case DISP_TYPE_TFT:
2354         case DISP_TYPE_CRT:
2355                 fb_info.max_pixclock = epfix->mclk;
2356                 break;
2357         case DISP_TYPE_NTSC:
2358         case DISP_TYPE_PAL:
2359                 fb_info.max_pixclock = (epfix->disp_type == DISP_TYPE_NTSC) ?
2360                         NTSC_PIXCLOCK : PAL_PIXCLOCK;
2361                 if (epfix->tv_filt & TV_FILT_FLICKER)
2362                         fb_info.max_pixclock *= 2;
2363                 break;
2364         default:
2365                 printk("e1356fb: invalid specified display type\n");
2366                 goto ret_enxio;
2367         }
2368
2369         periodMCLK = 1000000L / epfix->mclk;   // in nano-seconds
2370         periodBCLK = 1000000L / epfix->busclk; // in nano-seconds
2371         if (readb(&reg->md_cfg->md_cfg_stat1) & (1<<4))
2372                 periodBCLK *= 2;
2373     
2374         if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
2375                 writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);
2376         else if (periodMCLK - 4 > periodBCLK)
2377                 writeb(0x02, &reg->clk_cfg->cpu2mem_wait_sel);
2378         else if (2*periodMCLK - 4 > periodBCLK)
2379                 writeb(0x01, &reg->clk_cfg->cpu2mem_wait_sel);
2380         else
2381                 writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);
2382
2383         // Program memory config
2384         if (epfix->mem_type < MEM_TYPE_EDO_2CAS ||
2385             epfix->mem_type > MEM_TYPE_EMBEDDED_SDRAM) {
2386                 printk("e1356fb: bad memory type specified\n");
2387                 goto ret_enxio;
2388         }
2389         writeb((u8)epfix->mem_type, &reg->mem_cfg->mem_cfg);
2390
2391         // calc closest refresh rate
2392         rr_div = 7;
2393         mclk_src = (mclk_cfg & 1) ? epfix->busclk : epfix->clki;
2394         while ((mclk_src >> (6 + rr_div)) < epfix->mem_refresh)
2395                 if (--rr_div < 0) {
2396                         printk("e1356fb: can't set specified refresh rate\n");
2397                         goto ret_enxio;
2398                 }
2399     
2400         DPRINTK("refresh rate = %d kHz\n", (mclk_src >> (6 + rr_div)));
2401
2402         // add Suspend-Mode Refresh bits
2403         if (epfix->mem_smr < MEM_SMR_CBR || epfix->mem_smr > MEM_SMR_NONE) {
2404                 printk("e1356fb: invalid specified suspend-mode refresh type\n");
2405                 goto ret_enxio;
2406         }
2407         writeb(rr_div | (epfix->mem_smr << 6), &reg->mem_cfg->dram_refresh);
2408
2409         // set DRAM speed
2410         switch (epfix->mem_speed) {
2411         case 50:
2412                 dram_timing = epfix->mclk >= 33000 ? 0x0101 : 0x0212;
2413                 break;
2414         case 60:
2415                 if (epfix->mclk >= 30000)
2416                         dram_timing = 0x0101;
2417                 else if (epfix->mclk >= 25000)
2418                         dram_timing =
2419                                 (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
2420                                  epfix->mem_type == MEM_TYPE_EDO_2WE) ?
2421                                 0x0212 : 0x0101;
2422                 else
2423                         dram_timing = 0x0212;
2424                 break;
2425         case 70:
2426                 if (epfix->mclk >= 30000)
2427                         dram_timing = 0x0000;
2428                 else if (epfix->mclk >= 25000)
2429                         dram_timing = 0x0101;
2430                 else
2431                         dram_timing =
2432                                 (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
2433                                  epfix->mem_type == MEM_TYPE_EDO_2WE) ?
2434                                 0x0212 : 0x0211;
2435                 break;
2436         case 80:
2437                 if (epfix->mclk >= 25000)
2438                         dram_timing = 0x0100;
2439                 else
2440                         dram_timing = 0x0101;
2441                 break;
2442         default:
2443                 printk("e1356fb: invalid specified memory speed\n");
2444                 goto ret_enxio;
2445         }
2446
2447         writew(dram_timing, &reg->mem_cfg->dram_timings_ctrl0);
2448     
2449         currcon = -1;
2450         if (!epfix->nohwcursor)
2451                 e1356fb_hwcursor_init(&fb_info);
2452     
2453         init_timer(&fb_info.cursor.timer);
2454         fb_info.cursor.timer.function = do_flashcursor; 
2455         fb_info.cursor.timer.data = (unsigned long)(&fb_info);
2456         fb_info.cursor.state = CM_ERASE;
2457         spin_lock_init(&fb_info.cursor.lock);
2458     
2459         strcpy(fb_info.fb_info.modename, "Epson "); 
2460         strcat(fb_info.fb_info.modename, name);
2461         fb_info.fb_info.changevar  = NULL;
2462         fb_info.fb_info.node       = -1;
2463
2464         fb_info.fb_info.fbops      = &e1356fb_ops;
2465         fb_info.fb_info.disp       = &fb_info.disp;
2466         strcpy(fb_info.fb_info.fontname, epfix->fontname);
2467         fb_info.fb_info.switch_con = &e1356fb_switch_con;
2468         fb_info.fb_info.updatevar  = &e1356fb_updatevar;
2469         fb_info.fb_info.blank      = &e1356fb_blank;
2470         fb_info.fb_info.flags      = FBINFO_FLAG_DEFAULT;
2471     
2472         // Set-up display
2473         // clear out unused stuff
2474         writeb(0, &reg->panel_cfg->mod_rate);
2475         writeb(0x01, &reg->lcd_mode->lcd_misc);
2476         writeb(0, &reg->lcd_mode->fifo_high_thresh);
2477         writeb(0, &reg->lcd_mode->fifo_low_thresh);
2478         writeb(0, &reg->crttv_mode->fifo_high_thresh);
2479         writeb(0, &reg->crttv_mode->fifo_low_thresh);
2480     
2481         switch (epfix->disp_type) {
2482         case DISP_TYPE_LCD:
2483                 switch (epfix->panel_width) {
2484                 case 4: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x04); break;
2485                 case 8: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x14); break;
2486                 case 16: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x24); break;
2487                 default:
2488                         printk("e1356fb: invalid specified LCD panel data width\n");
2489                         goto ret_enxio;
2490                 }
2491                 writeb(btmp, &reg->panel_cfg->panel_type);
2492                 break;
2493         case DISP_TYPE_TFT:
2494                 switch (epfix->panel_width) {
2495                 case 9: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x05); break;
2496                 case 12: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x15); break;
2497                 case 18: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x25); break;
2498                 default:
2499                         printk("e1356fb: invalid specified TFT panel data width\n");
2500                         goto ret_enxio;
2501                 }
2502                 writeb(btmp, &reg->panel_cfg->panel_type);
2503                 break;
2504         case DISP_TYPE_CRT:
2505                 writeb(0x00, &reg->crttv_cfg->tv_output_ctrl);
2506                 break;
2507         case DISP_TYPE_NTSC:
2508         case DISP_TYPE_PAL:
2509                 if (epfix->tv_fmt < TV_FMT_COMPOSITE ||
2510                     epfix->tv_fmt > TV_FMT_S_VIDEO) {
2511                         printk("e1356fb: invalid specified TV output format\n");
2512                         goto ret_enxio;
2513                 }
2514                 btmp = epfix->disp_type == DISP_TYPE_PAL ? 0x01 : 0x00;
2515                 btmp |= (epfix->tv_fmt == TV_FMT_S_VIDEO ? 0x02 : 0x00);
2516                 btmp |= ((epfix->tv_filt & TV_FILT_LUM) ? 0x10 : 0x00);
2517                 btmp |= ((epfix->tv_filt & TV_FILT_CHROM) ? 0x20 : 0x00);
2518                 writeb(btmp, &reg->crttv_cfg->tv_output_ctrl);
2519                 break;
2520         }
2521
2522         memset(&var, 0, sizeof(var));
2523         /*
2524          * If mode_option wasn't given at boot, assume all the boot
2525          * option timing parameters were specified individually, in
2526          * which case we convert par_to_var instead of calling
2527          * fb_find_mode.
2528          */
2529         if (epfix->mode_option) {
2530                 struct fb_videomode* modedb, *dm;
2531                 int dbsize = e1356fb_get_mode(&fb_info, 640, 480, &modedb, &dm);
2532
2533                 // first try the generic modedb
2534                 if (!fb_find_mode(&var, &fb_info.fb_info, epfix->mode_option,
2535                                   NULL, 0, NULL, boot_par.bpp)) {
2536                         printk("e1356fb: mode %s failed, trying e1356 modedb\n",
2537                                epfix->mode_option);
2538                         // didn't work in generic modedb, try ours
2539                         if (!fb_find_mode(&var, &fb_info.fb_info,
2540                                           epfix->mode_option,
2541                                           modedb, dbsize, dm, boot_par.bpp)) {
2542                                 printk("e1356fb: mode %s failed e1356 modedb too, sorry\n",
2543                                        epfix->mode_option);
2544                                 
2545                                 goto ret_enxio;
2546                         }
2547                 }
2548
2549                 var.xres_virtual = boot_par.width_virt ?
2550                         boot_par.width_virt : boot_par.width;
2551                 var.yres_virtual = boot_par.height_virt ?
2552                         boot_par.height_virt : boot_par.height;
2553         } else {
2554                 if (e1356fb_par_to_var(&var, &fb_info.default_par, &fb_info)) {
2555                         printk("e1356fb: boot option mode failed\n");
2556                         goto ret_enxio;
2557                 }
2558         }
2559     
2560         if (boot_fix.noaccel)
2561                 var.accel_flags &= ~FB_ACCELF_TEXT;
2562         else
2563                 var.accel_flags |= FB_ACCELF_TEXT;
2564     
2565         if (e1356fb_var_to_par(&var, &fb_info.default_par, &fb_info)) {
2566                 /*
2567                  * Can't use the mode from the mode db or the default
2568                  * mode or the boot options - give up
2569                  */
2570                 printk("e1356fb: mode failed var_to_par\n");
2571                 goto ret_enxio;
2572         }
2573     
2574         fb_info.disp.screen_base    = fb_info.membase_virt;
2575         fb_info.disp.var            = var; // struct copy
2576     
2577         // here's where the screen is actually initialized and enabled
2578         if (e1356fb_set_var(&var, -1, &fb_info.fb_info)) {
2579                 printk("e1356fb: can't set video mode\n");
2580                 goto ret_enxio;
2581         }
2582     
2583         writeb(0, &reg->pwr_save->cfg);     // disable power-save mode
2584         writeb(0, &reg->misc->cpu2mem_watchdog); // disable watchdog timer
2585
2586 #ifdef E1356FB_VERBOSE_DEBUG
2587         dump_fb(fb_info.membase_virt + 0x100000, 512);
2588 #endif
2589
2590         if (register_framebuffer(&fb_info.fb_info) < 0) {
2591                 writeb(0, &reg->misc->disp_mode); 
2592                 printk("e1356fb: can't register framebuffer\n");
2593                 goto ret_enxio;
2594         }
2595     
2596         printk("fb%d: %s frame buffer device\n", 
2597                GET_FB_IDX(fb_info.fb_info.node),
2598                fb_info.fb_info.modename);
2599     
2600     
2601         return 0;
2602
2603  ret_enxio:
2604         free_pages((unsigned long)fb_info.putcs_buffer, 0);
2605  unmap_ret_enxio:
2606         iounmap(fb_info.regbase_virt);
2607         iounmap(fb_info.membase_virt);
2608         return -ENXIO;
2609 }
2610
2611 /**
2612  *      e1356fb_exit - Driver cleanup
2613  *
2614  *      Releases all resources allocated during the
2615  *      course of the driver's lifetime.
2616  *
2617  *      FIXME - do results of fb_alloc_cmap need disposal?
2618  */
2619 static void __exit
2620 e1356fb_exit (void)
2621 {
2622         unregister_framebuffer(&fb_info.fb_info);
2623         del_timer_sync(&fb_info.cursor.timer);
2624
2625 #ifdef CONFIG_MTRR
2626         if (!fb_info.fix.nomtrr) {
2627                 mtrr_del(fb_info.mtrr_idx, fb_info.fix.membase_phys,
2628                          fb_info.fb_size);
2629                 printk("fb: MTRR's  turned off\n");
2630         }
2631 #endif
2632
2633         free_pages((unsigned long)fb_info.putcs_buffer, 0);
2634         iounmap(fb_info.regbase_virt);
2635         iounmap(fb_info.membase_virt);
2636 }
2637
2638 MODULE_AUTHOR("Steve Longerbeam <stevel@mvista.com>");
2639 MODULE_DESCRIPTION("SED1356 framebuffer device driver");
2640
2641 #ifdef MODULE
2642 module_init(e1356fb_init);
2643 #endif
2644 module_exit(e1356fb_exit);
2645
2646
2647 void
2648 e1356fb_setup(char *options, int *ints)
2649 {
2650         char* this_opt;
2651     
2652         memset(&boot_fix, 0, sizeof(struct e1356fb_fix));
2653         memset(&boot_par, 0, sizeof(struct e1356fb_par));
2654         boot_fix.system = -1;
2655     
2656         if (!options || !*options)
2657                 return;
2658     
2659         for(this_opt=strtok(options, ","); this_opt;
2660             this_opt=strtok(NULL, ",")) {
2661                 if (!strncmp(this_opt, "noaccel", 7)) {
2662                         boot_fix.noaccel = 1;
2663                 } else if (!strncmp(this_opt, "nopan", 5)) {
2664                         boot_fix.nopan = 1;
2665                 } else if (!strncmp(this_opt, "nohwcursor", 10)) {
2666                         boot_fix.nohwcursor = 1;
2667                 } else if (!strncmp(this_opt, "mmunalign:", 10)) {
2668                         boot_fix.mmunalign = simple_strtoul(this_opt+10,
2669                                                             NULL, 0);
2670 #ifdef CONFIG_MTRR
2671                 } else if (!strncmp(this_opt, "nomtrr", 6)) {
2672                         boot_fix.nomtrr = 1;
2673 #endif
2674                 } else if (!strncmp(this_opt, "font:", 5)) {
2675                         strncpy(boot_fix.fontname, this_opt+5,
2676                                 sizeof(boot_fix.fontname)-1);
2677                 } else if (!strncmp(this_opt, "regbase:", 8)) {
2678                         boot_fix.regbase_phys = simple_strtoul(this_opt+8,
2679                                                                NULL, 0);
2680                 } else if (!strncmp(this_opt, "membase:", 8)) {
2681                         boot_fix.membase_phys = simple_strtoul(this_opt+8,
2682                                                                NULL, 0);
2683                 } else if (!strncmp(this_opt, "memsp:", 6)) {
2684                         boot_fix.mem_speed = simple_strtoul(this_opt+6,
2685                                                             NULL, 0);
2686                 } else if (!strncmp(this_opt, "memtyp:", 7)) {
2687                         boot_fix.mem_type = simple_strtoul(this_opt+7,
2688                                                            NULL, 0);
2689                 } else if (!strncmp(this_opt, "memref:", 7)) {
2690                         boot_fix.mem_refresh = simple_strtoul(this_opt+7,
2691                                                               NULL, 0);
2692                 } else if (!strncmp(this_opt, "memsmr:", 7)) {
2693                         boot_fix.mem_smr = simple_strtoul(this_opt+7, NULL, 0);
2694                 } else if (!strncmp(this_opt, "busclk:", 7)) {
2695                         boot_fix.busclk = simple_strtoul(this_opt+7, NULL, 0);
2696                 } else if (!strncmp(this_opt, "clki:", 5)) {
2697                         boot_fix.clki = simple_strtoul(this_opt+5, NULL, 0);
2698                 } else if (!strncmp(this_opt, "clki2:", 6)) {
2699                         boot_fix.clki2 = simple_strtoul(this_opt+6, NULL, 0);
2700                 } else if (!strncmp(this_opt, "display:", 8)) {
2701                         if (!strncmp(this_opt+8, "lcd", 3))
2702                                 boot_fix.disp_type = DISP_TYPE_LCD;
2703                         else if (!strncmp(this_opt+8, "tft", 3))
2704                                 boot_fix.disp_type = DISP_TYPE_TFT;
2705                         else if (!strncmp(this_opt+8, "crt", 3))
2706                                 boot_fix.disp_type = DISP_TYPE_CRT;
2707                         else if (!strncmp(this_opt+8, "pal", 3))
2708                                 boot_fix.disp_type = DISP_TYPE_PAL;
2709                         else if (!strncmp(this_opt+8, "ntsc", 4))
2710                                 boot_fix.disp_type = DISP_TYPE_NTSC;
2711                 } else if (!strncmp(this_opt, "width:", 6)) {
2712                         boot_par.width = simple_strtoul(this_opt+6, NULL, 0);
2713                 } else if (!strncmp(this_opt, "height:", 7)) {
2714                         boot_par.height = simple_strtoul(this_opt+7, NULL, 0);
2715                 } else if (!strncmp(this_opt, "bpp:", 4)) {
2716                         boot_par.bpp = simple_strtoul(this_opt+4, NULL, 0);
2717                         boot_par.cmap_len = (boot_par.bpp == 8) ? 256 : 16;
2718                 } else if (!strncmp(this_opt, "elpanel:", 8)) {
2719                         boot_fix.panel_el = simple_strtoul(this_opt+8,
2720                                                            NULL, 0);
2721                 } else if (!strncmp(this_opt, "pdataw:", 7)) {
2722                         boot_fix.panel_width = simple_strtoul(this_opt+7,
2723                                                               NULL, 0);
2724                 } else if (!strncmp(this_opt, "hndp:", 5)) {
2725                         boot_par.horiz_ndp = simple_strtoul(this_opt+5,
2726                                                             NULL, 0);
2727                 } else if (!strncmp(this_opt, "vndp:", 5)) {
2728                         boot_par.vert_ndp = simple_strtoul(this_opt+5,
2729                                                            NULL, 0);
2730                 } else if (!strncmp(this_opt, "hspol:", 6)) {
2731                         boot_par.hsync_pol = simple_strtoul(this_opt+6,
2732                                                             NULL, 0);
2733                 } else if (!strncmp(this_opt, "vspol:", 6)) {
2734                         boot_par.vsync_pol = simple_strtoul(this_opt+6,
2735                                                             NULL, 0);
2736                 } else if (!strncmp(this_opt, "hsstart:", 8)) {
2737                         boot_par.hsync_start = simple_strtoul(this_opt+8,
2738                                                               NULL, 0);
2739                 } else if (!strncmp(this_opt, "hswidth:", 8)) {
2740                         boot_par.hsync_width = simple_strtoul(this_opt+8,
2741                                                               NULL, 0);
2742                 } else if (!strncmp(this_opt, "vsstart:", 8)) {
2743                         boot_par.vsync_start = simple_strtoul(this_opt+8,
2744                                                               NULL, 0);
2745                 } else if (!strncmp(this_opt, "vswidth:", 8)) {
2746                         boot_par.vsync_width = simple_strtoul(this_opt+8,
2747                                                               NULL, 0);
2748                 } else if (!strncmp(this_opt, "tvfilt:", 7)) {
2749                         boot_fix.tv_filt = simple_strtoul(this_opt+7, NULL, 0);
2750                 } else if (!strncmp(this_opt, "tvfmt:", 6)) {
2751                         boot_fix.tv_fmt = simple_strtoul(this_opt+6, NULL, 0);
2752                 } else if (!strncmp(this_opt, "system:", 7)) {
2753                         if (!strncmp(this_opt+7, "pb1000", 10)) {
2754                                 boot_fix = systems[SYS_PB1000].fix;
2755                                 boot_par = systems[SYS_PB1000].par;
2756                         } else if (!strncmp(this_opt+7, "pb1500", 7)) {
2757                                 boot_fix = systems[SYS_PB1500].fix;
2758                                 boot_par = systems[SYS_PB1500].par;
2759                         } else if (!strncmp(this_opt+7, "sdu1356", 7)) {
2760                                 boot_fix = systems[SYS_SDU1356].fix;
2761                                 boot_par = systems[SYS_SDU1356].par;
2762                         } else if (!strncmp(this_opt+7, "clio1050", 7)) {
2763                                 boot_fix = systems[SYS_CLIO1050].fix;
2764                                 boot_par = systems[SYS_CLIO1050].par;
2765                         }
2766                 } else {
2767                         boot_fix.mode_option = this_opt;
2768                 }
2769         } 
2770 }
2771
2772
2773 /*
2774  * FIXME: switching consoles could be dangerous. What if switching
2775  * from a panel to a CRT/TV, or vice versa? More needs to be
2776  * done here.
2777  */
2778 static int
2779 e1356fb_switch_con(int con, struct fb_info *fb)
2780 {
2781         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2782         struct e1356fb_par par;
2783         int old_con = currcon;
2784         int set_par = 1;
2785
2786         //DPRINTK("\n");
2787
2788         /* Do we have to save the colormap? */
2789         if (currcon>=0)
2790                 if (fb_display[currcon].cmap.len)
2791                         fb_get_cmap(&fb_display[currcon].cmap, 1,
2792                                     e1356fb_getcolreg, fb);
2793    
2794         currcon = con;
2795         fb_display[currcon].var.activate = FB_ACTIVATE_NOW; 
2796         e1356fb_var_to_par(&fb_display[con].var, &par, info);
2797         if (old_con>=0 && vt_cons[old_con]->vc_mode!=KD_GRAPHICS) {
2798                 /* check if we have to change video registers */
2799                 struct e1356fb_par old_par;
2800                 e1356fb_var_to_par(&fb_display[old_con].var, &old_par, info);
2801                 if (!memcmp(&par,&old_par,sizeof(par)))
2802                         set_par = 0;    /* avoid flicker */
2803         }
2804         if (set_par)
2805                 e1356fb_set_par(&par, info);
2806     
2807         if (fb_display[con].dispsw && fb_display[con].conp)
2808                 fb_con.con_cursor(fb_display[con].conp, CM_ERASE);
2809    
2810         del_timer(&(info->cursor.timer));
2811         fb_info.cursor.state=CM_ERASE; 
2812    
2813         if (!info->fix.nohwcursor) 
2814                 if (fb_display[con].conp)
2815                         e1356fb_createcursor( &fb_display[con] );
2816    
2817         info->cursor.redraw=1;
2818    
2819         e1356fb_set_dispsw(&fb_display[con], 
2820                            info, 
2821                            par.bpp,
2822                            fb_display[con].var.accel_flags & FB_ACCELF_TEXT);
2823    
2824         e1356fb_install_cmap(&fb_display[con], fb);
2825         e1356fb_updatevar(con, fb);
2826    
2827         return 1;
2828 }
2829
2830 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
2831 static void
2832 e1356fb_blank(int blank, struct fb_info *fb)
2833 {
2834         struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2835         reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ?
2836                 info->reg.lcd_mode : info->reg.crttv_mode;
2837         reg_pwrsave_t* pwrsave = info->reg.pwr_save;
2838
2839         //DPRINTK("\n");
2840
2841         switch (blank) {
2842         case 0:
2843                 // Get out of power save mode
2844                 writeb(0x00, &pwrsave->cfg);
2845                 writeb(readb(&dispmode->disp_mode) & ~0x80,
2846                        &dispmode->disp_mode);
2847                 break;
2848         case 1:
2849                 // Get out of power save mode
2850                 writeb(0x00, &pwrsave->cfg);
2851                 writeb(readb(&dispmode->disp_mode) | 0x80,
2852                        &dispmode->disp_mode);
2853                 break;
2854                 // No support for turning off horiz or vert sync, so just treat
2855                 // it as a power off.
2856         case 2:
2857         case 3:
2858         case 4:
2859                 writeb(0x01, &pwrsave->cfg);
2860                 break;
2861         }
2862 }
2863
2864
2865 static int
2866 e1356fb_updatevar(int con, struct fb_info* fb)
2867 {
2868         struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
2869
2870         //DPRINTK("\n");
2871
2872         if ((con==currcon) && (!i->fix.nopan)) 
2873                 do_pan_var(&fb_display[con].var,i);
2874         return 0;
2875 }
2876
2877 static int
2878 e1356fb_getcolreg(unsigned        regno, 
2879                   unsigned*       red, 
2880                   unsigned*       green,
2881                   unsigned*       blue, 
2882                   unsigned*       transp,
2883                   struct fb_info* fb)
2884 {
2885         struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
2886
2887         if (regno > i->current_par.cmap_len)
2888                 return 1;
2889    
2890         *red    = i->palette[regno].red; 
2891         *green  = i->palette[regno].green; 
2892         *blue   = i->palette[regno].blue; 
2893         *transp = 0;
2894    
2895         return 0;
2896 }
2897
2898 static int
2899 e1356fb_setcolreg(unsigned        regno, 
2900                   unsigned        red, 
2901                   unsigned        green,
2902                   unsigned        blue, 
2903                   unsigned        transp,
2904                   struct fb_info* info)
2905 {
2906         struct fb_info_e1356* i = (struct fb_info_e1356*)info;
2907
2908         if (regno > 255)
2909                 return 1;
2910
2911         i->palette[regno].red    = red;
2912         i->palette[regno].green  = green;
2913         i->palette[regno].blue   = blue;
2914    
2915         switch(i->current_par.bpp) {
2916 #ifdef FBCON_HAS_CFB8
2917         case 8:
2918                 do_setpalentry(i->reg.lut, regno,
2919                                (u8)(red>>8), (u8)(green>>8), (u8)(blue>>8));
2920                 break;
2921 #endif
2922 #ifdef FBCON_HAS_CFB16
2923         case 16:
2924                 i->fbcon_cmap16[regno] = (regno << 10) | (regno << 5) | regno;
2925                 break;
2926 #endif
2927         default:
2928                 DPRINTK("bad depth %u\n", i->current_par.bpp);
2929                 break;
2930         }
2931         return 0;
2932 }
2933
2934 static void
2935 e1356fb_install_cmap(struct display *d, struct fb_info *info) 
2936 {
2937         struct fb_info_e1356* i = (struct fb_info_e1356*)info;
2938
2939         //DPRINTK("\n");
2940
2941         if (d->cmap.len) {
2942                 fb_set_cmap(&(d->cmap), 1, e1356fb_setcolreg, info);
2943         } else {
2944                 fb_set_cmap(fb_default_cmap(i->current_par.cmap_len), 1,
2945                             e1356fb_setcolreg, info);
2946         }
2947 }
2948
2949 static void
2950 e1356fb_createcursorshape(struct display* p) 
2951 {
2952         int h,u;
2953    
2954         h = fontheight(p);
2955
2956         fb_info.cursor.type = p->conp->vc_cursor_type & CUR_HWMASK;
2957
2958         switch (fb_info.cursor.type) {
2959         case CUR_NONE: 
2960                 u = h; 
2961                 break;
2962         case CUR_UNDERLINE: 
2963                 u = h - 2; 
2964                 break;
2965         case CUR_LOWER_THIRD: 
2966                 u = (h * 2) / 3; 
2967                 break;
2968         case CUR_LOWER_HALF: 
2969                 u = h / 2; 
2970                 break;
2971         case CUR_TWO_THIRDS: 
2972                 u = h / 3; 
2973                 break;
2974         case CUR_BLOCK:
2975         default:
2976                 u = 0;
2977                 break;
2978         }
2979     
2980         fb_info.cursor.w = fontwidth_x8(p);
2981         fb_info.cursor.u = u;
2982         fb_info.cursor.h = h;
2983 }
2984    
2985 static void
2986 e1356fb_createcursor(struct display *p)
2987 {
2988         void* memcursor;
2989         int y, w, h, u;
2990     
2991         e1356fb_createcursorshape(p);
2992
2993         h = fb_info.cursor.h;
2994         w = fb_info.cursor.w;
2995         u = fb_info.cursor.u;
2996         memcursor = fb_info.membase_virt + fb_info.fb_size;
2997
2998         // write cursor to display memory
2999         for (y=0; y<64; y++) {
3000                 if (y >= h || y < u) {
3001                         fbfill((u16*)memcursor, 0xaa, 16); // b/g
3002                 } else {
3003                         fbfill((u16*)memcursor, 0xff, w/4); // inverted b/g
3004                         fbfill((u16*)memcursor + w/4, 0xaa, (64 - w)/4); // b/g
3005                 }
3006                 memcursor += 16;
3007         }
3008 }
3009    
3010 static void
3011 e1356fb_hwcursor_init(struct fb_info_e1356* info)
3012 {
3013         reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
3014                 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
3015
3016         fb_info.fb_size -= 1024;
3017         // program cursor base address
3018         writeb(0x00, &inkcurs->start_addr);
3019         printk("e1356fb: reserving 1024 bytes for the hwcursor at %p\n",
3020                fb_info.membase_virt + fb_info.fb_size);
3021 }
3022
3023 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
3024
3025 /*
3026  * Return indicates whether a page was freed so caller can adjust rss
3027  */
3028 static inline void forget_pte(pte_t page)
3029 {
3030         if (!pte_none(page)) {
3031                 printk("forget_pte: old mapping existed!\n");
3032                 BUG();
3033         }
3034 }
3035
3036 /*
3037  * maps a range of physical memory into the requested pages. the old
3038  * mappings are removed. any references to nonexistent pages results
3039  * in null mappings (currently treated as "copy-on-access")
3040  */
3041 static inline void e1356_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
3042         phys_t phys_addr, pgprot_t prot)
3043 {
3044         unsigned long end;
3045
3046         address &= ~PMD_MASK;
3047         end = address + size;
3048         if (end > PMD_SIZE)
3049                 end = PMD_SIZE;
3050         do {
3051                 struct page *page;
3052                 pte_t oldpage;
3053                 oldpage = ptep_get_and_clear(pte);
3054
3055                 page = virt_to_page(__va(phys_addr));
3056                 if ((!VALID_PAGE(page)) || PageReserved(page))
3057                         set_pte(pte, mk_pte_phys(phys_addr, prot));
3058                 forget_pte(oldpage);
3059                 address += PAGE_SIZE;
3060                 phys_addr += PAGE_SIZE;
3061                 pte++;
3062         } while (address && (address < end));
3063 }
3064
3065 static inline int e1356_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
3066         phys_t phys_addr, pgprot_t prot)
3067 {
3068         unsigned long end;
3069
3070         address &= ~PGDIR_MASK;
3071         end = address + size;
3072         if (end > PGDIR_SIZE)
3073                 end = PGDIR_SIZE;
3074         phys_addr -= address;
3075         do {
3076                 pte_t * pte = pte_alloc(mm, pmd, address);
3077                 if (!pte)
3078                         return -ENOMEM;
3079                 e1356_remap_pte_range(pte, address, end - address, address + phys_addr, prot);
3080                 address = (address + PMD_SIZE) & PMD_MASK;
3081                 pmd++;
3082         } while (address && (address < end));
3083         return 0;
3084 }
3085
3086 /*  Note: this is only safe if the mm semaphore is held when called. */
3087 static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
3088 {
3089         int error = 0;
3090         pgd_t * dir;
3091         phys_t beg = from;
3092         phys_t end = from + size;
3093         struct mm_struct *mm = current->mm;
3094
3095         phys_addr -= from;
3096         dir = pgd_offset(mm, from);
3097         flush_cache_range(mm, beg, end);
3098         if (from >= end)
3099                 BUG();
3100
3101         spin_lock(&mm->page_table_lock);
3102         do {
3103                 pmd_t *pmd = pmd_alloc(mm, dir, from);
3104                 error = -ENOMEM;
3105                 if (!pmd)
3106                         break;
3107                 error = e1356_remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
3108                 if (error)
3109                         break;
3110                 from = (from + PGDIR_SIZE) & PGDIR_MASK;
3111                 dir++;
3112         } while (from && (from < end));
3113         spin_unlock(&mm->page_table_lock);
3114         flush_tlb_range(mm, beg, end);
3115         return error;
3116 }
3117 #endif