2 * epson1356fb.c -- Epson SED1356 Framebuffer Driver
4 * Copyright 2001, 2002 MontaVista Software Inc.
5 * Author: MontaVista Software, Inc.
6 * stevel@mvista.com or source@mvista.com
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.
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.
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.
32 * 03.12.2001 0.1 Initial release
36 #include <linux/config.h>
37 #include <linux/version.h>
38 #include <linux/module.h>
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/string.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>
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>
56 #include <linux/vt_kern.h>
58 #include <asm/uaccess.h>
59 #include <linux/timer.h>
60 #include <linux/pagemap.h>
62 #include <asm/pgalloc.h>
63 #include <asm/uaccess.h>
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>
76 #include <linux/spinlock.h>
78 #include <linux/e1356fb.h>
80 #ifdef CONFIG_MIPS_AU1000
81 #include <asm/au1000.h>
84 #define E1356FB_DEBUG 1
85 #undef E1356FB_VERBOSE_DEBUG
86 #undef SHADOW_FRAME_BUFFER
87 #include "epson1356fb.h"
90 MODULE_PARM(options, "s");
93 * Frame buffer device API
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,
100 static int e1356fb_get_var(struct fb_var_screeninfo* var,
103 static int e1356fb_set_var(struct fb_var_screeninfo* var,
106 static int e1356fb_pan_display(struct fb_var_screeninfo* var,
109 static int e1356fb_get_cmap(struct fb_cmap *cmap,
112 struct fb_info* info);
113 static int e1356fb_set_cmap(struct fb_cmap* cmap,
116 struct fb_info* info);
117 static int e1356fb_ioctl(struct inode* inode,
122 struct fb_info* info);
123 static int e1356fb_mmap(struct fb_info *info,
125 struct vm_area_struct *vma);
128 * Interface to the low level console driver
130 static int e1356fb_switch_con(int con,
132 static int e1356fb_updatevar(int con,
134 static void e1356fb_blank(int blank,
140 static void e1356fb_set_par(const struct e1356fb_par* par,
141 struct fb_info_e1356*
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,
156 static int e1356fb_getcolreg(u_int regno,
162 static int e1356fb_setcolreg(u_int regno,
168 static void e1356fb_install_cmap(struct display *d,
169 struct fb_info *info);
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);
176 * do_xxx: Hardware-specific functions
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,
184 static void doBlt_SolidFill(const struct e1356fb_par* par,
185 struct fb_info_e1356* i,
189 * Interface used by the world
191 int e1356fb_init(void);
192 void e1356fb_setup(char *options, int *ints);
194 static int currcon = 0;
196 static struct fb_ops e1356fb_ops = {
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,
209 #define PCI_VENDOR_ID_EPSON 0x10f4
210 #define PCI_DEVICE_ID_EPSON_SDU1356 0x1300
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
217 static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot);
220 /* -------------------------------------------------------------------------
221 * Hardware-specific funcions
222 * ------------------------------------------------------------------------- */
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.
233 fbfill(u16* fbaddr, u8 val, int size)
235 u16 valw = (u16)val | ((u16)val << 8);
236 for ( ; size >= 2; size -= 2)
237 writew(valw, fbaddr++);
239 writeb(val, (u8*)fbaddr);
243 e1356_wait_bitclr(u8* reg, u8 bit, int timeout)
245 while (readb(reg) & bit) {
254 e1356_wait_bitset(u8* reg, u8 bit, int timeout)
256 while (!(readb(reg) & bit)) {
265 static struct fb_videomode panel_modedb[] = {
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
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
277 /* 800x600 @ 76 Hz, 46.3 kHz hsync */
278 NULL, 76, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1),
280 0, FB_VMODE_NONINTERLACED
283 static struct fb_videomode crt_modedb[] = {
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
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
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
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
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
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
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
323 static struct fb_videomode ntsc_modedb[] = {
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
332 static struct fb_videomode pal_modedb[] = {
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
343 fb_videomode_to_var(struct fb_videomode* mode,
344 struct fb_var_screeninfo*var)
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;
361 e1356fb_get_mode(const struct fb_info_e1356 *info,
364 struct fb_videomode ** modedb,
365 struct fb_videomode ** mode)
367 struct fb_videomode * ret;
370 if (IS_PANEL(info->fix.disp_type)) {
372 dbsize = sizeof(panel_modedb)/sizeof(struct fb_videomode);
373 } else if (info->fix.disp_type == DISP_TYPE_CRT) {
375 dbsize = sizeof(crt_modedb)/sizeof(struct fb_videomode);
376 } else if (info->fix.disp_type == DISP_TYPE_NTSC) {
378 dbsize = sizeof(ntsc_modedb)/sizeof(struct fb_videomode);
381 dbsize = sizeof(pal_modedb)/sizeof(struct fb_videomode);
386 for (i=0; i<dbsize; i++) {
387 if (xres == ret[i].xres && yres == ret[i].yres) {
399 #ifdef E1356FB_VERBOSE_DEBUG
401 dump_par(const struct e1356fb_par* par)
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);
421 dump_display_regs(reg_dispcfg_t* dispcfg, reg_dispmode_t* dispmode)
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));
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));
447 dump_fb(u8* base, int len)
450 DPRINTK("FB memory dump, start 0x%p, len %d", base, len);
451 for (i=0; i<len; i++) {
453 printk("\n%p: %02x ", &base[i], readb(&base[i]));
455 printk("%02x ", readb(&base[i]));
460 #endif // E1356FB_VERBOSE_DEBUG
464 // Input: ipclk->clksrc, ipclk->pixclk_d
465 // Output: ipclk->pixclk, ipclk->error, and ipclk->divisor
467 get_nearest_pixclk_div(pixclock_info_t* ipclk, int x2)
469 int pixclk_d = ipclk->pixclk_d;
470 int clksrc = ipclk->clksrc;
474 if (clksrc < (3*pixclk_d+1)/2)
476 else if (clksrc < (5*pixclk_d+1)/2)
478 else if (clksrc < (7*pixclk_d+1)/2)
480 else if (clksrc < (9*pixclk_d+1)/2)
485 ipclk->pixclk = clksrc / ipclk->divisor;
486 ipclk->error = (100*(pixclk_d - ipclk->pixclk)) / pixclk_d;
491 e1356_calc_pixclock(const struct fb_info_e1356 *info,
492 pixclock_info_t* ipclk)
494 int src_sel=-1, flicker_mult=0;
495 pixclock_info_t test, ret;
497 if (ipclk->pixclk > info->max_pixclock)
500 test.pixclk_d = ipclk->pixclk_d;
503 if (IS_TV(info->fix.disp_type) &&
504 (info->fix.tv_filt & TV_FILT_FLICKER))
507 test.clksrc = info->fix.busclk;
508 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
509 abs(test.error) < abs(ret.error)) {
514 test.clksrc = info->fix.mclk;
515 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
516 abs(test.error) < abs(ret.error)) {
521 test.clksrc = info->fix.clki;
522 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
523 abs(test.error) < abs(ret.error)) {
528 test.clksrc = info->fix.clki2;
529 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
530 abs(test.error) < abs(ret.error)) {
535 if (ret.error > MAX_PCLK_ERROR_LOWER ||
536 ret.error < MAX_PCLK_ERROR_HIGHER)
539 ret.pixclk_bits = flicker_mult | ((ret.divisor-1)<<4) | src_sel;
545 e1356_engine_wait_complete(reg_bitblt_t* bltreg)
547 return e1356_wait_bitclr(&bltreg->ctrl0, 0x80, 5000);
550 e1356_engine_wait_busy(reg_bitblt_t* bltreg)
552 return e1356_wait_bitset(&bltreg->ctrl0, 0x80, 5000);
556 e1356fb_engine_init(const struct e1356fb_par* par,
557 struct fb_info_e1356* info)
559 reg_bitblt_t* bltreg = info->reg.bitblt;
561 e1356_engine_wait_complete(bltreg);
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);
581 static void doBlt_Write(const struct e1356fb_par* par,
582 struct fb_info_e1356* info,
585 reg_bitblt_t* bltreg = info->reg.bitblt;
586 int nWords, nTotalWords;
587 u32 srcphase, dstAddr;
589 u32 stride = par->width_virt * par->Bpp;
591 dstAddr = blt->dst_x * par->Bpp + blt->dst_y * stride;
592 srcphase = (u32)blt->src & 1;
594 if (blt->attribute & BLT_ATTR_TRANSPARENT)
595 writew(blt->bg_color, &bltreg->bg_color0);
597 writeb(blt->rop, &bltreg->rop_code);
599 writeb(blt->operation, &bltreg->operation);
600 writeb((u8)srcphase, &bltreg->src_start_addr0);
601 writew(stride/2, &bltreg->mem_addr_offset0);
603 writeb(dstAddr, &bltreg->dest_start_addr0);
604 writeb(dstAddr>>8, &bltreg->dest_start_addr1);
605 writeb(dstAddr>>16, &bltreg->dest_start_addr2);
607 writew(blt->dst_width-1, &bltreg->width0);
608 writew(blt->dst_height-1, &bltreg->height0);
610 // program color format operation
611 writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
614 writeb(0x80, &bltreg->ctrl0);
616 // wait for it to actually start
617 e1356_engine_wait_busy(bltreg);
619 // calculate the number of 16 bit words per one blt line
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
625 while (nTotalWords > 0) {
629 // read the FIFO status
630 ctrl0 = readb(&bltreg->ctrl0);
632 if ((ctrl0 & 0x30) == 0x20)
633 // FIFO is at least half full, but not full
635 else if ((ctrl0 & 0x40) == 0)
642 for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)
643 writew(*w16++, info->reg.bitblt_data);
646 e1356_engine_wait_complete(bltreg);
651 doBlt_SolidFill(const struct e1356fb_par* par,
652 struct fb_info_e1356* info,
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);
660 if (width == 0 || height == 0)
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);
668 // program width and height of solid-fill blit
669 writew(width-1, &bltreg->width0);
670 writew(height-1, &bltreg->height0);
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);
681 // start it up (self completes)
682 writeb(0x80, &bltreg->ctrl0);
684 e1356_engine_wait_complete(bltreg);
689 doBlt_Move(const struct e1356fb_par* par,
690 struct fb_info_e1356* info,
693 reg_bitblt_t* bltreg = info->reg.bitblt;
695 u32 dest_addr, src_addr;
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;
702 if (width == 0 || height == 0)
705 src_addr = srcx*par->Bpp + srcy*stride;
706 dest_addr = dstx*par->Bpp + dsty*stride;
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.
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)) {
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);
724 // program BLIT memory offset
725 writew(stride/2, &bltreg->mem_addr_offset0);
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);
735 // program width and height of blit
736 writew(width-1, &bltreg->width0);
737 writew(height-1, &bltreg->height0);
739 // program color format operation
740 writeb(bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
743 if (blt->attribute & BLT_ATTR_TRANSPARENT) {
744 writew(blt->bg_color, &bltreg->bg_color0);
745 writeb(BLT_MOVE_POS_TRANSP, &bltreg->operation);
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,
753 // start it up (self completes)
754 writeb(0x80, &bltreg->ctrl0);
756 e1356_engine_wait_complete(bltreg);
760 static void doBlt_ColorExpand(const struct e1356fb_par* par,
761 struct fb_info_e1356* info,
764 reg_bitblt_t* bltreg = info->reg.bitblt;
765 int i, j, nWords, Sx, Sy;
768 u32 stride = par->width_virt * par->Bpp;
770 if (blt->dst_width == 0 || blt->dst_height == 0)
776 writeb((7 - Sx%8), &bltreg->rop_code);
778 writeb(blt->operation, &bltreg->operation);
780 writeb((u8)(Sx & 1), &bltreg->src_start_addr0);
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);
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);
796 writeb(0x80, &bltreg->ctrl0);
798 // wait for it to actually start
799 e1356_engine_wait_busy(bltreg);
801 // calculate the number of 16 bit words per one blt line
803 nWords = (Sx%16 + blt->dst_width + 15)/16;
805 wpt = blt->src + (Sy*blt->srcstride + Sx/16)/2;
807 for (i = 0; i < blt->dst_height; i++) {
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);
816 wpt += blt->srcstride/2;
819 e1356_engine_wait_complete(bltreg);
824 * The BitBLT operation dispatcher
827 doBlt(const struct e1356fb_par* par,
828 struct fb_info_e1356* info,
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.
838 if (readb(&info->reg.bitblt->ctrl0) & 0x80)
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);
848 case BLT_COLOR_EXP_TRANSP:
849 doBlt_ColorExpand(par, info, blt);
852 doBlt_SolidFill(par, info, blt);
855 case BLT_WRITE_TRANSP:
856 doBlt_Write(par, info, blt);
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",
867 DPRINTK("Unknown BitBLT operation 0x%02x\n", blt->operation);
875 // Initializes blt->src and blt->srcstride
876 static void fill_putcs_buffer(struct display *p,
878 const unsigned short* str,
883 u32 fw = fontwidth(p);
884 u32 fwb = (fw + 7) >> 3;
885 u32 fh = fontheight(p);
886 int bytesPerChar = fwb * fh;
888 if (count*bytesPerChar > PAGE_SIZE) {
889 // Truncate the string if it overflows putcs_buffer, which is
891 count = PAGE_SIZE/bytesPerChar - 1;
894 blt->srcstride = (fwb*count + 1) & ~1; //round up to be even
898 for (row = 0; row < fh; row++) {
900 for (i = 0; i < count; i++) {
901 for (j=0; j<fwb; j++)
902 *b2++ = p->fontdata[(str[i] & p->charmask) *
906 b1 += blt->srcstride;
912 * Set the color of a palette entry in 8bpp mode
915 do_setpalentry(reg_lut_t* lut, unsigned regno,
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);
927 do_pan_var(struct fb_var_screeninfo* var, struct fb_info_e1356* info)
929 u32 pixel_start, start_addr;
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;
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;
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;
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);
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);
958 * Invert the hardware cursor image (timerfunc)
961 do_flashcursor(unsigned long ptr)
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;
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);
977 #ifdef SHADOW_FRAME_BUFFER
979 * Write BLT the shadow frame buffer to the real fb (timerfunc)
982 do_write_shadow_fb(unsigned long ptr)
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;
990 unsigned long j_start = jiffies;
992 blt.src_x = blt.src_y = 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);
1003 doBlt(par, info, &blt);
1005 info->shadow.timer.expires = jiffies+HZ/2;
1006 add_timer(&info->shadow.timer);
1008 //DPRINTK("delta jiffies = %ld\n", jiffies - j_start);
1013 /* -------------------------------------------------------------------------
1014 * Hardware independent part, interface to the world
1015 * ------------------------------------------------------------------------- */
1018 e1356_cfbX_clear_margins(struct vc_data* conp, struct display* p,
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;
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;
1038 blt.operation = BLT_SOLID_FILL;
1039 doBlt (&fb_info.current_par, &fb_info, &blt);
1043 blt.dst_x = p->var.xoffset;
1044 blt.dst_y = p->var.yoffset+bs;
1045 blt.dst_height = bh;
1049 blt.operation = BLT_SOLID_FILL;
1050 doBlt (&fb_info.current_par, &fb_info, &blt);
1055 e1356_cfbX_bmove(struct display* p,
1065 //DPRINTK("(%d,%d) to (%d,%d) size (%d,%d)\n", sx,sy,dx,dy,width,height);
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;
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.
1080 blt.operation = BLT_MOVE_POS_ROP;
1082 doBlt (&fb_info.current_par, &fb_info, &blt);
1086 e1356_cfb8_putc(struct vc_data* conp,
1088 int c, int yy,int xx)
1092 u32 fw = fontwidth_x8(p);
1093 u32 fh = fontheight(p);
1096 fgx = attr_fgcol(p, c);
1097 bgx = attr_bgcol(p, c);
1099 blt.src_x = blt.src_y = 0;
1102 blt.dst_height = fh;
1103 blt.dst_y = yy * fh;
1104 blt.dst_x = xx * fw;
1107 blt.operation = BLT_COLOR_EXP;
1108 blt.src = fb_info.putcs_buffer;
1109 fill_putcs_buffer(p, &blt, &cs, 1);
1111 doBlt(&fb_info.current_par, &fb_info, &blt);
1116 e1356_cfb16_putc(struct vc_data* conp,
1118 int c, int yy,int xx)
1122 u32 fw = fontwidth_x8(p);
1123 u32 fh = fontheight(p);
1126 fgx = ((u16*)p->dispsw_data)[attr_fgcol(p,c)];
1127 bgx = ((u16*)p->dispsw_data)[attr_bgcol(p,c)];
1129 blt.src_x = blt.src_y = 0;
1132 blt.dst_height = fh;
1133 blt.dst_y = yy * fh;
1134 blt.dst_x = xx * fw;
1137 blt.operation = BLT_COLOR_EXP;
1138 blt.src = fb_info.putcs_buffer;
1139 fill_putcs_buffer(p, &blt, &cs, 1);
1141 doBlt(&fb_info.current_par, &fb_info, &blt);
1146 e1356_cfb8_putcs(struct vc_data* conp,
1148 const unsigned short *s,int count,int yy,int xx)
1152 u32 fw = fontwidth_x8(p);
1153 u32 fh = fontheight(p);
1157 fgx=attr_fgcol(p, *s);
1158 bgx=attr_bgcol(p, *s);
1160 blt.src_x = blt.src_y = 0;
1162 blt.dst_width = count * fw;
1163 blt.dst_height = fh;
1164 blt.dst_y = yy * fh;
1165 blt.dst_x = xx * fw;
1168 blt.operation = BLT_COLOR_EXP;
1169 blt.src = fb_info.putcs_buffer;
1170 fill_putcs_buffer(p, &blt, s, count);
1172 doBlt(&fb_info.current_par, &fb_info, &blt);
1176 e1356_cfb16_putcs(struct vc_data* conp,
1178 const unsigned short *s,int count,int yy,int xx)
1182 u32 fw = fontwidth_x8(p);
1183 u32 fh = fontheight(p);
1187 fgx=((u16*)p->dispsw_data)[attr_fgcol(p,*s)];
1188 bgx=((u16*)p->dispsw_data)[attr_bgcol(p,*s)];
1190 blt.src_x = blt.src_y = 0;
1192 blt.dst_width = count * fw;
1193 blt.dst_height = fh;
1194 blt.dst_y = yy * fh;
1195 blt.dst_x = xx * fw;
1198 blt.operation = BLT_COLOR_EXP;
1199 blt.src = fb_info.putcs_buffer;
1200 fill_putcs_buffer(p, &blt, s, count);
1202 doBlt(&fb_info.current_par, &fb_info, &blt);
1207 e1356_cfb8_clear(struct vc_data* conp,
1215 u32 bg = attr_bgcol_ec(p,conp);
1217 //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height);
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;
1225 blt.operation = BLT_SOLID_FILL;
1227 doBlt (&fb_info.current_par, &fb_info, &blt);
1231 e1356_cfb16_clear(struct vc_data* conp,
1239 u32 bg = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
1241 //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height);
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;
1249 blt.operation = BLT_SOLID_FILL;
1251 doBlt (&fb_info.current_par, &fb_info, &blt);
1256 e1356_cfbX_revc(struct display *p, int xx, int yy)
1258 // not used if h/w cursor
1263 e1356_cfbX_cursor(struct display *p, int mode, int x, int y)
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;
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);
1283 if ((p->conp->vc_cursor_type & CUR_HWMASK) != info->cursor.type)
1284 e1356fb_createcursor(p);
1286 x *= fontwidth_x8(p);
1288 x -= p->var.xoffset;
1289 y -= p->var.yoffset;
1291 spin_lock_irqsave(&info->cursor.lock,flags);
1292 if ((x != info->cursor.x) || (y != info->cursor.y) ||
1293 (info->cursor.redraw)) {
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);
1309 info->cursor.state = CM_DRAW;
1310 mod_timer(&info->cursor.timer, jiffies+HZ/2);
1311 spin_unlock_irqrestore(&info->cursor.lock,flags);
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)
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)
1342 /* ------------------------------------------------------------------------- */
1345 e1356fb_set_par(const struct e1356fb_par* par,
1346 struct fb_info_e1356* info)
1348 reg_dispcfg_t* dispcfg=NULL;
1349 reg_dispmode_t* dispmode=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;
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
1364 info->current_par = *par;
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;
1373 switch (disp_type) {
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;
1380 hsync_width = par->hsync_pol ? 0x00 : 0x80;
1381 vsync_width = par->vsync_pol ? 0x00 : 0x80;
1382 main_display_mode = 0x01;
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;
1393 (par->hsync_pol ? 0x80 : 0x00) |
1394 ((par->hsync_width >> 3) - 1);
1396 (par->vsync_pol ? 0x80 : 0x00) |
1397 (par->vsync_width - 1);
1398 main_display_mode = 0x01;
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;
1409 (par->hsync_pol ? 0x80 : 0x00) |
1410 ((par->hsync_width >> 3) - 1);
1412 (par->vsync_pol ? 0x80 : 0x00) |
1413 (par->vsync_width - 1);
1414 main_display_mode = 0x02;
1416 case DISP_TYPE_NTSC:
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;
1429 main_display_mode = (info->fix.tv_filt & TV_FILT_FLICKER) ?
1435 // note: reset panning/scrolling (set start-addr and
1436 // pixel pan regs to 0). Panning is handled by pan_display.
1438 e1356_engine_wait_complete(info->reg.bitblt);
1440 // disable display while initializing
1441 writeb(0, &info->reg.misc->disp_mode);
1443 writeb(par->ipclk.pixclk_bits, pclk_cfg);
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);
1454 writeb(display_mode, &dispmode->disp_mode);
1455 if (info->fix.mmunalign && info->mmaped)
1456 writeb(1, &dispmode->start_addr0);
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);
1464 // reset BitBlt engine
1465 e1356fb_engine_init(par, info);
1467 #ifdef E1356FB_VERBOSE_DEBUG
1468 dump_display_regs(dispcfg, dispmode);
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);
1479 e1356fb_verify_timing(struct e1356fb_par* par,
1480 const struct fb_info_e1356* info)
1482 int disp_type = info->fix.disp_type;
1484 // timing boundary checks
1485 if (par->horiz_ndp > max_hndp[disp_type]) {
1486 DPRINTK("horiz_ndp too big: %d\n", par->horiz_ndp);
1489 if (par->vert_ndp > max_vndp[disp_type]) {
1490 DPRINTK("vert_ndp too big: %d\n", par->vert_ndp);
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",
1501 if (par->vsync_start > max_vsync_start[disp_type]) {
1502 DPRINTK("vsync_start too big: %d\n",
1506 if (!IS_TV(disp_type)) {
1507 if (par->hsync_width > max_hsync_width[disp_type]) {
1508 DPRINTK("hsync_width too big: %d\n",
1512 if (par->vsync_width > max_vsync_width[disp_type]) {
1513 DPRINTK("vsync_width too big: %d\n",
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)
1526 if (par->ipclk.pixclk_d != tv_pixclk) {
1527 DPRINTK("invalid TV pixel clock %u kHz\n",
1528 par->ipclk.pixclk_d);
1533 if (e1356_calc_pixclock(info, &par->ipclk) < 0) {
1534 DPRINTK("can't set pixel clock %u kHz\n",
1535 par->ipclk.pixclk_d);
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);
1544 if (disp_type != DISP_TYPE_LCD) {
1545 if (par->horiz_ndp < par->hsync_start + par->hsync_width) {
1546 DPRINTK("invalid horiz. timing\n");
1549 if (par->vert_ndp < par->vsync_start + par->vsync_width) {
1550 DPRINTK("invalid vert. timing\n");
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");
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");
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);
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",
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",
1589 e1356fb_verify_par(struct e1356fb_par* par,
1590 const struct fb_info_e1356* info)
1592 int disp_type = info->fix.disp_type;
1594 if (par->bpp != 8 && par->bpp != 16) {
1595 DPRINTK("depth not supported: %u bpp\n", par->bpp);
1599 if (par->width > par->width_virt) {
1600 DPRINTK("virtual x resolution < physical x resolution not possible\n");
1604 if (par->height > par->height_virt) {
1605 DPRINTK("virtual y resolution < physical y resolution not possible\n");
1609 if (par->width < 320 || par->width > 1024) {
1610 DPRINTK("width not supported: %u\n", par->width);
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);
1620 if (par->height < 200 || par->height > 1024) {
1621 DPRINTK("height not supported: %u\n", par->height);
1625 if (par->width_virt * par->height_virt * par->Bpp >
1627 DPRINTK("not enough memory for virtual screen (%ux%ux%u)\n",
1628 par->width_virt, par->height_virt, par->bpp);
1632 return e1356fb_verify_timing(par, info);
1637 e1356fb_var_to_par(const struct fb_var_screeninfo* var,
1638 struct e1356fb_par* par,
1639 const struct fb_info_e1356* info)
1641 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1642 DPRINTK("interlace not supported\n");
1646 memset(par, 0, sizeof(struct e1356fb_par));
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;
1655 par->ipclk.pixclk_d = PICOS2KHZ(var->pixclock);
1657 par->hsync_start = var->right_margin;
1658 par->hsync_width = var->hsync_len;
1660 par->vsync_start = var->lower_margin;
1661 par->vsync_width = var->vsync_len;
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;
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;
1669 par->cmap_len = (par->bpp == 8) ? 256 : 16;
1671 return e1356fb_verify_par(par, info);
1675 e1356fb_par_to_var(struct fb_var_screeninfo* var,
1676 struct e1356fb_par* par,
1677 const struct fb_info_e1356* info)
1679 struct fb_var_screeninfo v;
1682 // First, make sure par is valid.
1683 if ((ret = e1356fb_verify_par(par, info)))
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;
1701 v.red.offset = v.green.offset = v.blue.offset = 0;
1702 v.red.length = v.green.length = v.blue.length = 4;
1714 v.height = v.width = -1;
1715 v.pixclock = KHZ2PICOS(par->ipclk.pixclk);
1718 v.sync |= FB_SYNC_HOR_HIGH_ACT;
1720 v.sync |= FB_SYNC_VERT_HIGH_ACT;
1727 e1356fb_encode_fix(struct fb_fix_screeninfo* fix,
1728 const struct e1356fb_par* par,
1729 const struct fb_info_e1356* info)
1731 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
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;
1741 fix->line_length = par->width_virt * par->Bpp;
1743 (par->bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1745 fix->xpanstep = info->fix.nopan ? 0 : 1;
1746 fix->ypanstep = info->fix.nopan ? 0 : 1;
1752 static int e1356fb_open(struct fb_info *fb, int user)
1754 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1762 static int e1356fb_release(struct fb_info *fb, int user)
1764 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1765 if (user && info->open) {
1767 if (info->open == 0)
1775 e1356fb_get_fix(struct fb_fix_screeninfo *fix,
1779 const struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1780 struct e1356fb_par par;
1785 par = info->current_par;
1787 e1356fb_var_to_par(&fb_display[con].var, &par, info);
1788 e1356fb_encode_fix(fix, &par, info);
1793 e1356fb_get_var(struct fb_var_screeninfo *var,
1797 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
1802 e1356fb_par_to_var(var, &info->current_par, info);
1804 *var = fb_display[con].var;
1809 e1356fb_set_dispsw(struct display *disp,
1810 struct fb_info_e1356 *info,
1814 struct e1356fb_fix* fix = &info->fix;
1817 if (disp->dispsw && disp->conp)
1818 fb_con.con_cursor(disp->conp, CM_ERASE);
1820 #ifdef FBCON_HAS_CFB8
1822 disp->dispsw = fix->noaccel ? &fbcon_cfb8 : &fbcon_e1356_8;
1823 if (fix->nohwcursor)
1824 fbcon_e1356_8.cursor = NULL;
1827 #ifdef FBCON_HAS_CFB16
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;
1836 disp->dispsw = &fbcon_dummy;
1842 e1356fb_set_var(struct fb_var_screeninfo *var,
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;
1856 display = &fb_display[con];
1858 display = fb->disp; /* used during initialization */
1860 if ((err = e1356fb_var_to_par(var, &par, info))) {
1861 struct fb_videomode *dm;
1863 * this mode didn't pass the tests. Try the
1864 * corresponding mode from our own modedb.
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);
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);
1882 if (info->fix.tv_filt & TV_FILT_FLICKER)
1883 printk("e1356fb: TV flicker filter enabled\n");
1885 e1356fb_par_to_var(var, &par, info);
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;
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;
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);
1918 if (info->fix.nopan)
1919 display->scrollmode = SCROLL_YREDRAW;
1921 if (info->fb_info.changevar)
1922 (*info->fb_info.changevar)(con);
1924 if (var->bits_per_pixel==8)
1925 for(j = 0; j < 16; 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];
1932 del_timer(&(info->cursor.timer));
1933 fb_info.cursor.state=CM_ERASE;
1935 if (!info->fb_info.display_fg ||
1936 info->fb_info.display_fg->vc_num == con || con < 0)
1937 e1356fb_set_par(&par, info);
1939 if (!info->fix.nohwcursor)
1940 if (display && display->conp)
1941 e1356fb_createcursor( display );
1942 info->cursor.redraw = 1;
1944 if (oldbpp != var->bits_per_pixel || con < 0) {
1945 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
1947 e1356fb_install_cmap(display, &(info->fb_info));
1955 e1356fb_pan_display(struct fb_var_screeninfo* var,
1959 struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
1960 struct e1356fb_par* par = &info->current_par;
1964 if (info->fix.nopan)
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)
1974 do_pan_var(var, info);
1976 fb_display[con].var.xoffset = var->xoffset;
1977 fb_display[con].var.yoffset = var->yoffset;
1983 e1356fb_get_cmap(struct fb_cmap *cmap,
1988 struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
1989 struct display *d = (con<0) ? fb->disp : fb_display + con;
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);
2000 fb_copy_cmap(fb_default_cmap(info->current_par.cmap_len),
2001 cmap, kspc ? 0 : 2);
2007 e1356fb_set_cmap(struct fb_cmap *cmap,
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;
2018 if (d->cmap.len!=cmap_len) {
2020 if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0)))
2024 if (con == currcon) {
2025 /* current console? */
2026 return fb_set_cmap(cmap, kspc, e1356fb_setcolreg, fb);
2028 fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
2034 e1356fb_mmap(struct fb_info *fb,
2036 struct vm_area_struct *vma)
2038 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2040 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
2043 unsigned long start=0, off;
2046 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
2047 DPRINTK("invalid vma->vm_pgoff\n");
2051 #ifdef SHADOW_FRAME_BUFFER
2052 if (!info->shadow.fb) {
2054 while (info->fb_size > (PAGE_SIZE * (1 << order)))
2056 info->shadow.fb = (void*)__get_free_pages(GFP_KERNEL, order);
2057 if (!info->shadow.fb) {
2058 DPRINTK("shadow fb alloc failed\n");
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;
2066 mod_timer(&info->shadow.timer, jiffies+HZ/2);
2067 start = virt_to_phys(info->shadow.fb) & PAGE_MASK;
2069 start = info->fix.membase_phys & PAGE_MASK;
2072 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fb_size);
2074 off = vma->vm_pgoff << PAGE_SHIFT;
2076 if ((vma->vm_end - vma->vm_start + off) > len) {
2077 DPRINTK("invalid vma\n");
2082 vma->vm_pgoff = off >> PAGE_SHIFT;
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;
2089 pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
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);
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).
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.
2122 if (info->fix.mmunalign)
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,
2131 if (io_remap_page_range(vma->vm_start, off,
2132 vma->vm_end - vma->vm_start,
2145 struct fb_var_screeninfo var;
2146 struct e1356fb_fix * epfix = &fb_info.fix;
2149 char* name = "SED1356";
2150 int periodMCLK, periodBCLK;
2151 int dram_timing, rr_div, mclk_src;
2152 u8 rev_code, btmp, mclk_cfg;
2155 e1356fb_setup(options, 0);
2158 // clear out fb_info
2159 memset(&fb_info, 0, sizeof(struct fb_info_e1356));
2161 // copy boot options
2162 fb_info.fix = boot_fix;
2163 fb_info.default_par = boot_par;
2165 fb_info.regbase_size = E1356_REG_SIZE;
2167 if (!epfix->system) {
2168 printk(KERN_ERR "e1356/86fb: no valid system found\n");
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! */
2177 if (!(pdev = pci_find_device(PCI_VENDOR_ID_EPSON,
2178 PCI_DEVICE_ID_EPSON_SDU1356, pdev)))
2180 if (pci_enable_device(pdev))
2182 epfix->regbase_phys = pci_resource_start(pdev, 0);
2183 epfix->membase_phys = epfix->regbase_phys + E1356_REG_SIZE;
2186 fb_info.regbase_virt = ioremap_nocache(epfix->regbase_phys,
2189 if (!fb_info.regbase_virt) {
2190 printk("e1356fb: Can't remap %s register area.\n", name);
2194 regbase = fb_info.regbase_virt;
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);
2217 // Enable all register access
2218 writeb(0, ®->basic->misc);
2220 rev_code = readb(®->basic->rev_code);
2221 if ((rev_code >> 2) == 0x04) {
2222 printk("Found EPSON1356 Display Controller\n");
2224 else if ((rev_code >> 2) == 0x07) {
2225 printk("Found EPSON13806 Display Controller\n");
2228 iounmap(fb_info.regbase_virt);
2229 printk("e1356/806fb: %s not found, rev_code=0x%02x.\n",
2234 fb_info.chip_rev = rev_code & 0x03;
2236 // Determine frame-buffer size
2237 switch (readb(®->md_cfg->md_cfg_stat0) >> 6) {
2240 fb_info.fb_size = 0x80000; /* 512K bytes */
2243 if ((rev_code >> 2) == 7) /* 806 */
2244 fb_info.fb_size = 0x140000; /* 1.2M bytes */
2246 fb_info.fb_size = 0x200000; /* 2M bytes */
2249 fb_info.fb_size = 0x200000; /* 2M bytes */
2253 fb_info.membase_virt = ioremap_nocache(epfix->membase_phys,
2256 if (!fb_info.membase_virt) {
2257 printk("e1356fb: Can't remap %s framebuffer.\n", name);
2258 iounmap(fb_info.regbase_virt);
2262 printk("e1356/806fb: Detected %dKB framebuffer\n",
2263 (unsigned)fb_info.fb_size/1000);
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");
2273 if (!boot_fix.noaccel) {
2275 Allocate a page for string BLTs. A 4K page is
2276 enough for a 256 character string at an 8x16 font.
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;
2285 // Begin SED1356 initialization
2287 // disable display while initializing
2288 writeb(0, ®->misc->disp_mode);
2289 // Set the GPIO1 and 2 to inputs
2290 writeb(0, ®->genio->gpio_cfg);
2291 writeb(0, ®->genio->gpio_ctrl);
2292 if (fb_info.chip_rev == 7) /* 806 */
2293 writeb(0, ®->genio->gpio_ctrl2);
2296 * Program the clocks
2299 #ifdef CONFIG_MIPS_AU1000
2300 if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
2301 epfix->busclk = get_au1000_lcd_clock();
2304 if (epfix->busclk > 80000) {
2305 printk("e1356fb: specified busclk too high\n");
2309 epfix->mclk = mclk_cfg = 0;
2310 if (epfix->system == SYS_PB1500) {
2311 epfix->mclk = epfix->busclk;
2315 // Find the highest allowable MCLK
2316 if (epfix->busclk <= MAX_PIXCLOCK &&
2317 epfix->busclk > epfix->mclk) {
2318 epfix->mclk = epfix->busclk;
2321 if (epfix->clki <= MAX_PIXCLOCK && epfix->clki > epfix->mclk) {
2322 epfix->mclk = epfix->clki;
2325 if (epfix->busclk/2 <= MAX_PIXCLOCK &&
2326 epfix->busclk/2 > epfix->mclk) {
2327 epfix->mclk = epfix->busclk/2;
2330 if (epfix->clki/2 <= MAX_PIXCLOCK &&
2331 epfix->clki/2 > epfix->mclk) {
2332 epfix->mclk = epfix->clki/2;
2338 printk("e1356fb: couldn't find an allowable MCLK!\n");
2342 // When changing mclk src, you must first set bit 4 to 1.
2343 writeb(readb(®->clk_cfg->mem_clk_cfg) | 0x10,
2344 ®->clk_cfg->mem_clk_cfg);
2345 writeb(mclk_cfg, ®->clk_cfg->mem_clk_cfg);
2347 printk("e1356fb: clocks (kHz): busclk=%d mclk=%d clki=%d clki2=%d\n",
2348 epfix->busclk, epfix->mclk, epfix->clki, epfix->clki2);
2350 // Set max pixel clock
2351 switch (epfix->disp_type) {
2355 fb_info.max_pixclock = epfix->mclk;
2357 case DISP_TYPE_NTSC:
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;
2365 printk("e1356fb: invalid specified display type\n");
2369 periodMCLK = 1000000L / epfix->mclk; // in nano-seconds
2370 periodBCLK = 1000000L / epfix->busclk; // in nano-seconds
2371 if (readb(®->md_cfg->md_cfg_stat1) & (1<<4))
2374 if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
2375 writeb(0x00, ®->clk_cfg->cpu2mem_wait_sel);
2376 else if (periodMCLK - 4 > periodBCLK)
2377 writeb(0x02, ®->clk_cfg->cpu2mem_wait_sel);
2378 else if (2*periodMCLK - 4 > periodBCLK)
2379 writeb(0x01, ®->clk_cfg->cpu2mem_wait_sel);
2381 writeb(0x00, ®->clk_cfg->cpu2mem_wait_sel);
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");
2389 writeb((u8)epfix->mem_type, ®->mem_cfg->mem_cfg);
2391 // calc closest refresh rate
2393 mclk_src = (mclk_cfg & 1) ? epfix->busclk : epfix->clki;
2394 while ((mclk_src >> (6 + rr_div)) < epfix->mem_refresh)
2396 printk("e1356fb: can't set specified refresh rate\n");
2400 DPRINTK("refresh rate = %d kHz\n", (mclk_src >> (6 + rr_div)));
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");
2407 writeb(rr_div | (epfix->mem_smr << 6), ®->mem_cfg->dram_refresh);
2410 switch (epfix->mem_speed) {
2412 dram_timing = epfix->mclk >= 33000 ? 0x0101 : 0x0212;
2415 if (epfix->mclk >= 30000)
2416 dram_timing = 0x0101;
2417 else if (epfix->mclk >= 25000)
2419 (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
2420 epfix->mem_type == MEM_TYPE_EDO_2WE) ?
2423 dram_timing = 0x0212;
2426 if (epfix->mclk >= 30000)
2427 dram_timing = 0x0000;
2428 else if (epfix->mclk >= 25000)
2429 dram_timing = 0x0101;
2432 (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
2433 epfix->mem_type == MEM_TYPE_EDO_2WE) ?
2437 if (epfix->mclk >= 25000)
2438 dram_timing = 0x0100;
2440 dram_timing = 0x0101;
2443 printk("e1356fb: invalid specified memory speed\n");
2447 writew(dram_timing, ®->mem_cfg->dram_timings_ctrl0);
2450 if (!epfix->nohwcursor)
2451 e1356fb_hwcursor_init(&fb_info);
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);
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;
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;
2473 // clear out unused stuff
2474 writeb(0, ®->panel_cfg->mod_rate);
2475 writeb(0x01, ®->lcd_mode->lcd_misc);
2476 writeb(0, ®->lcd_mode->fifo_high_thresh);
2477 writeb(0, ®->lcd_mode->fifo_low_thresh);
2478 writeb(0, ®->crttv_mode->fifo_high_thresh);
2479 writeb(0, ®->crttv_mode->fifo_low_thresh);
2481 switch (epfix->disp_type) {
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;
2488 printk("e1356fb: invalid specified LCD panel data width\n");
2491 writeb(btmp, ®->panel_cfg->panel_type);
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;
2499 printk("e1356fb: invalid specified TFT panel data width\n");
2502 writeb(btmp, ®->panel_cfg->panel_type);
2505 writeb(0x00, ®->crttv_cfg->tv_output_ctrl);
2507 case DISP_TYPE_NTSC:
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");
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, ®->crttv_cfg->tv_output_ctrl);
2522 memset(&var, 0, sizeof(var));
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
2529 if (epfix->mode_option) {
2530 struct fb_videomode* modedb, *dm;
2531 int dbsize = e1356fb_get_mode(&fb_info, 640, 480, &modedb, &dm);
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,
2541 modedb, dbsize, dm, boot_par.bpp)) {
2542 printk("e1356fb: mode %s failed e1356 modedb too, sorry\n",
2543 epfix->mode_option);
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;
2554 if (e1356fb_par_to_var(&var, &fb_info.default_par, &fb_info)) {
2555 printk("e1356fb: boot option mode failed\n");
2560 if (boot_fix.noaccel)
2561 var.accel_flags &= ~FB_ACCELF_TEXT;
2563 var.accel_flags |= FB_ACCELF_TEXT;
2565 if (e1356fb_var_to_par(&var, &fb_info.default_par, &fb_info)) {
2567 * Can't use the mode from the mode db or the default
2568 * mode or the boot options - give up
2570 printk("e1356fb: mode failed var_to_par\n");
2574 fb_info.disp.screen_base = fb_info.membase_virt;
2575 fb_info.disp.var = var; // struct copy
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");
2583 writeb(0, ®->pwr_save->cfg); // disable power-save mode
2584 writeb(0, ®->misc->cpu2mem_watchdog); // disable watchdog timer
2586 #ifdef E1356FB_VERBOSE_DEBUG
2587 dump_fb(fb_info.membase_virt + 0x100000, 512);
2590 if (register_framebuffer(&fb_info.fb_info) < 0) {
2591 writeb(0, ®->misc->disp_mode);
2592 printk("e1356fb: can't register framebuffer\n");
2596 printk("fb%d: %s frame buffer device\n",
2597 GET_FB_IDX(fb_info.fb_info.node),
2598 fb_info.fb_info.modename);
2604 free_pages((unsigned long)fb_info.putcs_buffer, 0);
2606 iounmap(fb_info.regbase_virt);
2607 iounmap(fb_info.membase_virt);
2612 * e1356fb_exit - Driver cleanup
2614 * Releases all resources allocated during the
2615 * course of the driver's lifetime.
2617 * FIXME - do results of fb_alloc_cmap need disposal?
2622 unregister_framebuffer(&fb_info.fb_info);
2623 del_timer_sync(&fb_info.cursor.timer);
2626 if (!fb_info.fix.nomtrr) {
2627 mtrr_del(fb_info.mtrr_idx, fb_info.fix.membase_phys,
2629 printk("fb: MTRR's turned off\n");
2633 free_pages((unsigned long)fb_info.putcs_buffer, 0);
2634 iounmap(fb_info.regbase_virt);
2635 iounmap(fb_info.membase_virt);
2638 MODULE_AUTHOR("Steve Longerbeam <stevel@mvista.com>");
2639 MODULE_DESCRIPTION("SED1356 framebuffer device driver");
2642 module_init(e1356fb_init);
2644 module_exit(e1356fb_exit);
2648 e1356fb_setup(char *options, int *ints)
2652 memset(&boot_fix, 0, sizeof(struct e1356fb_fix));
2653 memset(&boot_par, 0, sizeof(struct e1356fb_par));
2654 boot_fix.system = -1;
2656 if (!options || !*options)
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)) {
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,
2671 } else if (!strncmp(this_opt, "nomtrr", 6)) {
2672 boot_fix.nomtrr = 1;
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,
2680 } else if (!strncmp(this_opt, "membase:", 8)) {
2681 boot_fix.membase_phys = simple_strtoul(this_opt+8,
2683 } else if (!strncmp(this_opt, "memsp:", 6)) {
2684 boot_fix.mem_speed = simple_strtoul(this_opt+6,
2686 } else if (!strncmp(this_opt, "memtyp:", 7)) {
2687 boot_fix.mem_type = simple_strtoul(this_opt+7,
2689 } else if (!strncmp(this_opt, "memref:", 7)) {
2690 boot_fix.mem_refresh = simple_strtoul(this_opt+7,
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,
2721 } else if (!strncmp(this_opt, "pdataw:", 7)) {
2722 boot_fix.panel_width = simple_strtoul(this_opt+7,
2724 } else if (!strncmp(this_opt, "hndp:", 5)) {
2725 boot_par.horiz_ndp = simple_strtoul(this_opt+5,
2727 } else if (!strncmp(this_opt, "vndp:", 5)) {
2728 boot_par.vert_ndp = simple_strtoul(this_opt+5,
2730 } else if (!strncmp(this_opt, "hspol:", 6)) {
2731 boot_par.hsync_pol = simple_strtoul(this_opt+6,
2733 } else if (!strncmp(this_opt, "vspol:", 6)) {
2734 boot_par.vsync_pol = simple_strtoul(this_opt+6,
2736 } else if (!strncmp(this_opt, "hsstart:", 8)) {
2737 boot_par.hsync_start = simple_strtoul(this_opt+8,
2739 } else if (!strncmp(this_opt, "hswidth:", 8)) {
2740 boot_par.hsync_width = simple_strtoul(this_opt+8,
2742 } else if (!strncmp(this_opt, "vsstart:", 8)) {
2743 boot_par.vsync_start = simple_strtoul(this_opt+8,
2745 } else if (!strncmp(this_opt, "vswidth:", 8)) {
2746 boot_par.vsync_width = simple_strtoul(this_opt+8,
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;
2767 boot_fix.mode_option = this_opt;
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
2779 e1356fb_switch_con(int con, struct fb_info *fb)
2781 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
2782 struct e1356fb_par par;
2783 int old_con = currcon;
2788 /* Do we have to save the colormap? */
2790 if (fb_display[currcon].cmap.len)
2791 fb_get_cmap(&fb_display[currcon].cmap, 1,
2792 e1356fb_getcolreg, fb);
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 */
2805 e1356fb_set_par(&par, info);
2807 if (fb_display[con].dispsw && fb_display[con].conp)
2808 fb_con.con_cursor(fb_display[con].conp, CM_ERASE);
2810 del_timer(&(info->cursor.timer));
2811 fb_info.cursor.state=CM_ERASE;
2813 if (!info->fix.nohwcursor)
2814 if (fb_display[con].conp)
2815 e1356fb_createcursor( &fb_display[con] );
2817 info->cursor.redraw=1;
2819 e1356fb_set_dispsw(&fb_display[con],
2822 fb_display[con].var.accel_flags & FB_ACCELF_TEXT);
2824 e1356fb_install_cmap(&fb_display[con], fb);
2825 e1356fb_updatevar(con, fb);
2830 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
2832 e1356fb_blank(int blank, struct fb_info *fb)
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;
2843 // Get out of power save mode
2844 writeb(0x00, &pwrsave->cfg);
2845 writeb(readb(&dispmode->disp_mode) & ~0x80,
2846 &dispmode->disp_mode);
2849 // Get out of power save mode
2850 writeb(0x00, &pwrsave->cfg);
2851 writeb(readb(&dispmode->disp_mode) | 0x80,
2852 &dispmode->disp_mode);
2854 // No support for turning off horiz or vert sync, so just treat
2855 // it as a power off.
2859 writeb(0x01, &pwrsave->cfg);
2866 e1356fb_updatevar(int con, struct fb_info* fb)
2868 struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
2872 if ((con==currcon) && (!i->fix.nopan))
2873 do_pan_var(&fb_display[con].var,i);
2878 e1356fb_getcolreg(unsigned regno,
2885 struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
2887 if (regno > i->current_par.cmap_len)
2890 *red = i->palette[regno].red;
2891 *green = i->palette[regno].green;
2892 *blue = i->palette[regno].blue;
2899 e1356fb_setcolreg(unsigned regno,
2904 struct fb_info* info)
2906 struct fb_info_e1356* i = (struct fb_info_e1356*)info;
2911 i->palette[regno].red = red;
2912 i->palette[regno].green = green;
2913 i->palette[regno].blue = blue;
2915 switch(i->current_par.bpp) {
2916 #ifdef FBCON_HAS_CFB8
2918 do_setpalentry(i->reg.lut, regno,
2919 (u8)(red>>8), (u8)(green>>8), (u8)(blue>>8));
2922 #ifdef FBCON_HAS_CFB16
2924 i->fbcon_cmap16[regno] = (regno << 10) | (regno << 5) | regno;
2928 DPRINTK("bad depth %u\n", i->current_par.bpp);
2935 e1356fb_install_cmap(struct display *d, struct fb_info *info)
2937 struct fb_info_e1356* i = (struct fb_info_e1356*)info;
2942 fb_set_cmap(&(d->cmap), 1, e1356fb_setcolreg, info);
2944 fb_set_cmap(fb_default_cmap(i->current_par.cmap_len), 1,
2945 e1356fb_setcolreg, info);
2950 e1356fb_createcursorshape(struct display* p)
2956 fb_info.cursor.type = p->conp->vc_cursor_type & CUR_HWMASK;
2958 switch (fb_info.cursor.type) {
2965 case CUR_LOWER_THIRD:
2968 case CUR_LOWER_HALF:
2971 case CUR_TWO_THIRDS:
2980 fb_info.cursor.w = fontwidth_x8(p);
2981 fb_info.cursor.u = u;
2982 fb_info.cursor.h = h;
2986 e1356fb_createcursor(struct display *p)
2991 e1356fb_createcursorshape(p);
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;
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
3003 fbfill((u16*)memcursor, 0xff, w/4); // inverted b/g
3004 fbfill((u16*)memcursor + w/4, 0xaa, (64 - w)/4); // b/g
3011 e1356fb_hwcursor_init(struct fb_info_e1356* info)
3013 reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
3014 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
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);
3023 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
3026 * Return indicates whether a page was freed so caller can adjust rss
3028 static inline void forget_pte(pte_t page)
3030 if (!pte_none(page)) {
3031 printk("forget_pte: old mapping existed!\n");
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")
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)
3046 address &= ~PMD_MASK;
3047 end = address + size;
3053 oldpage = ptep_get_and_clear(pte);
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;
3062 } while (address && (address < end));
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)
3070 address &= ~PGDIR_MASK;
3071 end = address + size;
3072 if (end > PGDIR_SIZE)
3074 phys_addr -= address;
3076 pte_t * pte = pte_alloc(mm, pmd, address);
3079 e1356_remap_pte_range(pte, address, end - address, address + phys_addr, prot);
3080 address = (address + PMD_SIZE) & PMD_MASK;
3082 } while (address && (address < end));
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)
3092 phys_t end = from + size;
3093 struct mm_struct *mm = current->mm;
3096 dir = pgd_offset(mm, from);
3097 flush_cache_range(mm, beg, end);
3101 spin_lock(&mm->page_table_lock);
3103 pmd_t *pmd = pmd_alloc(mm, dir, from);
3107 error = e1356_remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
3110 from = (from + PGDIR_SIZE) & PGDIR_MASK;
3112 } while (from && (from < end));
3113 spin_unlock(&mm->page_table_lock);
3114 flush_tlb_range(mm, beg, end);