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