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