]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/video/w100fb.c
drivers/video/backlight/aat2870_bl.c: fix setting max_current
[linux-2.6.git] / drivers / video / w100fb.c
1 /*
2  * linux/drivers/video/w100fb.c
3  *
4  * Frame Buffer Device for ATI Imageon w100 (Wallaby)
5  *
6  * Copyright (C) 2002, ATI Corp.
7  * Copyright (C) 2004-2006 Richard Purdie
8  * Copyright (c) 2005 Ian Molton
9  * Copyright (c) 2006 Alberto Mardegan
10  *
11  * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
12  *
13  * Generic platform support by Ian Molton <spyro@f2s.com>
14  * and Richard Purdie <rpurdie@rpsys.net>
15  *
16  * w32xx support by Ian Molton
17  *
18  * Hardware acceleration support by Alberto Mardegan
19  * <mardy@users.sourceforge.net>
20  *
21  * This program is free software; you can redistribute it and/or modify
22  * it under the terms of the GNU General Public License version 2 as
23  * published by the Free Software Foundation.
24  *
25  */
26
27 #include <linux/delay.h>
28 #include <linux/fb.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/mm.h>
32 #include <linux/platform_device.h>
33 #include <linux/slab.h>
34 #include <linux/string.h>
35 #include <linux/vmalloc.h>
36 #include <asm/io.h>
37 #include <asm/uaccess.h>
38 #include <video/w100fb.h>
39 #include "w100fb.h"
40
41 /*
42  * Prototypes
43  */
44 static void w100_suspend(u32 mode);
45 static void w100_vsync(void);
46 static void w100_hw_init(struct w100fb_par*);
47 static void w100_pwm_setup(struct w100fb_par*);
48 static void w100_init_clocks(struct w100fb_par*);
49 static void w100_setup_memory(struct w100fb_par*);
50 static void w100_init_lcd(struct w100fb_par*);
51 static void w100_set_dispregs(struct w100fb_par*);
52 static void w100_update_enable(void);
53 static void w100_update_disable(void);
54 static void calc_hsync(struct w100fb_par *par);
55 static void w100_init_graphic_engine(struct w100fb_par *par);
56 struct w100_pll_info *w100_get_xtal_table(unsigned int freq) __devinit;
57
58 /* Pseudo palette size */
59 #define MAX_PALETTES      16
60
61 #define W100_SUSPEND_EXTMEM 0
62 #define W100_SUSPEND_ALL    1
63
64 #define BITS_PER_PIXEL    16
65
66 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
67 static void *remapped_base;
68 static void *remapped_regs;
69 static void *remapped_fbuf;
70
71 #define REMAPPED_FB_LEN   0x15ffff
72
73 /* This is the offset in the w100's address space we map the current
74    framebuffer memory to. We use the position of external memory as
75    we can remap internal memory to there if external isn't present. */
76 #define W100_FB_BASE MEM_EXT_BASE_VALUE
77
78
79 /*
80  * Sysfs functions
81  */
82 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
83 {
84         struct fb_info *info = dev_get_drvdata(dev);
85         struct w100fb_par *par=info->par;
86
87         return sprintf(buf, "%d\n",par->flip);
88 }
89
90 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
91 {
92         unsigned int flip;
93         struct fb_info *info = dev_get_drvdata(dev);
94         struct w100fb_par *par=info->par;
95
96         flip = simple_strtoul(buf, NULL, 10);
97
98         if (flip > 0)
99                 par->flip = 1;
100         else
101                 par->flip = 0;
102
103         w100_update_disable();
104         w100_set_dispregs(par);
105         w100_update_enable();
106
107         calc_hsync(par);
108
109         return count;
110 }
111
112 static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
113
114 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
115 {
116         unsigned long regs, param;
117         regs = simple_strtoul(buf, NULL, 16);
118         param = readl(remapped_regs + regs);
119         printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
120         return count;
121 }
122
123 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
124
125 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
126 {
127         unsigned long regs, param;
128         sscanf(buf, "%lx %lx", &regs, &param);
129
130         if (regs <= 0x2000) {
131                 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
132                 writel(param, remapped_regs + regs);
133         }
134
135         return count;
136 }
137
138 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
139
140
141 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
142 {
143         struct fb_info *info = dev_get_drvdata(dev);
144         struct w100fb_par *par=info->par;
145
146         return sprintf(buf, "%d\n",par->fastpll_mode);
147 }
148
149 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
150 {
151         struct fb_info *info = dev_get_drvdata(dev);
152         struct w100fb_par *par=info->par;
153
154         if (simple_strtoul(buf, NULL, 10) > 0) {
155                 par->fastpll_mode=1;
156                 printk("w100fb: Using fast system clock (if possible)\n");
157         } else {
158                 par->fastpll_mode=0;
159                 printk("w100fb: Using normal system clock\n");
160         }
161
162         w100_init_clocks(par);
163         calc_hsync(par);
164
165         return count;
166 }
167
168 static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
169
170 /*
171  * Some touchscreens need hsync information from the video driver to
172  * function correctly. We export it here.
173  */
174 unsigned long w100fb_get_hsynclen(struct device *dev)
175 {
176         struct fb_info *info = dev_get_drvdata(dev);
177         struct w100fb_par *par=info->par;
178
179         /* If display is blanked/suspended, hsync isn't active */
180         if (par->blanked)
181                 return 0;
182         else
183                 return par->hsync_len;
184 }
185 EXPORT_SYMBOL(w100fb_get_hsynclen);
186
187 static void w100fb_clear_screen(struct w100fb_par *par)
188 {
189         memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
190 }
191
192
193 /*
194  * Set a palette value from rgb components
195  */
196 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
197                              u_int trans, struct fb_info *info)
198 {
199         unsigned int val;
200         int ret = 1;
201
202         /*
203          * If greyscale is true, then we convert the RGB value
204          * to greyscale no matter what visual we are using.
205          */
206         if (info->var.grayscale)
207                 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
208
209         /*
210          * 16-bit True Colour.  We encode the RGB value
211          * according to the RGB bitfield information.
212          */
213         if (regno < MAX_PALETTES) {
214                 u32 *pal = info->pseudo_palette;
215
216                 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
217                 pal[regno] = val;
218                 ret = 0;
219         }
220         return ret;
221 }
222
223
224 /*
225  * Blank the display based on value in blank_mode
226  */
227 static int w100fb_blank(int blank_mode, struct fb_info *info)
228 {
229         struct w100fb_par *par = info->par;
230         struct w100_tg_info *tg = par->mach->tg;
231
232         switch(blank_mode) {
233
234         case FB_BLANK_NORMAL:         /* Normal blanking */
235         case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
236         case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
237         case FB_BLANK_POWERDOWN:      /* Poweroff */
238                 if (par->blanked == 0) {
239                         if(tg && tg->suspend)
240                                 tg->suspend(par);
241                         par->blanked = 1;
242                 }
243                 break;
244
245         case FB_BLANK_UNBLANK: /* Unblanking */
246                 if (par->blanked != 0) {
247                         if(tg && tg->resume)
248                                 tg->resume(par);
249                         par->blanked = 0;
250                 }
251                 break;
252         }
253         return 0;
254 }
255
256
257 static void w100_fifo_wait(int entries)
258 {
259         union rbbm_status_u status;
260         int i;
261
262         for (i = 0; i < 2000000; i++) {
263                 status.val = readl(remapped_regs + mmRBBM_STATUS);
264                 if (status.f.cmdfifo_avail >= entries)
265                         return;
266                 udelay(1);
267         }
268         printk(KERN_ERR "w100fb: FIFO Timeout!\n");
269 }
270
271
272 static int w100fb_sync(struct fb_info *info)
273 {
274         union rbbm_status_u status;
275         int i;
276
277         for (i = 0; i < 2000000; i++) {
278                 status.val = readl(remapped_regs + mmRBBM_STATUS);
279                 if (!status.f.gui_active)
280                         return 0;
281                 udelay(1);
282         }
283         printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
284         return -EBUSY;
285 }
286
287
288 static void w100_init_graphic_engine(struct w100fb_par *par)
289 {
290         union dp_gui_master_cntl_u gmc;
291         union dp_mix_u dp_mix;
292         union dp_datatype_u dp_datatype;
293         union dp_cntl_u dp_cntl;
294
295         w100_fifo_wait(4);
296         writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
297         writel(par->xres, remapped_regs + mmDST_PITCH);
298         writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
299         writel(par->xres, remapped_regs + mmSRC_PITCH);
300
301         w100_fifo_wait(3);
302         writel(0, remapped_regs + mmSC_TOP_LEFT);
303         writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
304         writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
305
306         w100_fifo_wait(4);
307         dp_cntl.val = 0;
308         dp_cntl.f.dst_x_dir = 1;
309         dp_cntl.f.dst_y_dir = 1;
310         dp_cntl.f.src_x_dir = 1;
311         dp_cntl.f.src_y_dir = 1;
312         dp_cntl.f.dst_major_x = 1;
313         dp_cntl.f.src_major_x = 1;
314         writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
315
316         gmc.val = 0;
317         gmc.f.gmc_src_pitch_offset_cntl = 1;
318         gmc.f.gmc_dst_pitch_offset_cntl = 1;
319         gmc.f.gmc_src_clipping = 1;
320         gmc.f.gmc_dst_clipping = 1;
321         gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
322         gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
323         gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
324         gmc.f.gmc_byte_pix_order = 1;
325         gmc.f.gmc_default_sel = 0;
326         gmc.f.gmc_rop3 = ROP3_SRCCOPY;
327         gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
328         gmc.f.gmc_clr_cmp_fcn_dis = 1;
329         gmc.f.gmc_wr_msk_dis = 1;
330         gmc.f.gmc_dp_op = DP_OP_ROP;
331         writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
332
333         dp_datatype.val = dp_mix.val = 0;
334         dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
335         dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
336         dp_datatype.f.dp_src2_type = 0;
337         dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
338         dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
339         dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
340         writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
341
342         dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
343         dp_mix.f.dp_src2_source = 1;
344         dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
345         dp_mix.f.dp_op = gmc.f.gmc_dp_op;
346         writel(dp_mix.val, remapped_regs + mmDP_MIX);
347 }
348
349
350 static void w100fb_fillrect(struct fb_info *info,
351                             const struct fb_fillrect *rect)
352 {
353         union dp_gui_master_cntl_u gmc;
354
355         if (info->state != FBINFO_STATE_RUNNING)
356                 return;
357         if (info->flags & FBINFO_HWACCEL_DISABLED) {
358                 cfb_fillrect(info, rect);
359                 return;
360         }
361
362         gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
363         gmc.f.gmc_rop3 = ROP3_PATCOPY;
364         gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
365         w100_fifo_wait(2);
366         writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
367         writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
368
369         w100_fifo_wait(2);
370         writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
371         writel((rect->width << 16) | (rect->height & 0xffff),
372                remapped_regs + mmDST_WIDTH_HEIGHT);
373 }
374
375
376 static void w100fb_copyarea(struct fb_info *info,
377                             const struct fb_copyarea *area)
378 {
379         u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
380         u32 h = area->height, w = area->width;
381         union dp_gui_master_cntl_u gmc;
382
383         if (info->state != FBINFO_STATE_RUNNING)
384                 return;
385         if (info->flags & FBINFO_HWACCEL_DISABLED) {
386                 cfb_copyarea(info, area);
387                 return;
388         }
389
390         gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
391         gmc.f.gmc_rop3 = ROP3_SRCCOPY;
392         gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
393         w100_fifo_wait(1);
394         writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
395
396         w100_fifo_wait(3);
397         writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
398         writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
399         writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
400 }
401
402
403 /*
404  *  Change the resolution by calling the appropriate hardware functions
405  */
406 static void w100fb_activate_var(struct w100fb_par *par)
407 {
408         struct w100_tg_info *tg = par->mach->tg;
409
410         w100_pwm_setup(par);
411         w100_setup_memory(par);
412         w100_init_clocks(par);
413         w100fb_clear_screen(par);
414         w100_vsync();
415
416         w100_update_disable();
417         w100_init_lcd(par);
418         w100_set_dispregs(par);
419         w100_update_enable();
420         w100_init_graphic_engine(par);
421
422         calc_hsync(par);
423
424         if (!par->blanked && tg && tg->change)
425                 tg->change(par);
426 }
427
428
429 /* Select the smallest mode that allows the desired resolution to be
430  * displayed. If desired, the x and y parameters can be rounded up to
431  * match the selected mode.
432  */
433 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
434 {
435         struct w100_mode *mode = NULL;
436         struct w100_mode *modelist = par->mach->modelist;
437         unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
438         unsigned int i;
439
440         for (i = 0 ; i < par->mach->num_modes ; i++) {
441                 if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
442                                 modelist[i].xres < best_x && modelist[i].yres < best_y) {
443                         best_x = modelist[i].xres;
444                         best_y = modelist[i].yres;
445                         mode = &modelist[i];
446                 } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
447                         modelist[i].xres < best_y && modelist[i].yres < best_x) {
448                         best_x = modelist[i].yres;
449                         best_y = modelist[i].xres;
450                         mode = &modelist[i];
451                 }
452         }
453
454         if (mode && saveval) {
455                 *x = best_x;
456                 *y = best_y;
457         }
458
459         return mode;
460 }
461
462
463 /*
464  *  w100fb_check_var():
465  *  Get the video params out of 'var'. If a value doesn't fit, round it up,
466  *  if it's too big, return -EINVAL.
467  */
468 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
469 {
470         struct w100fb_par *par=info->par;
471
472         if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
473                 return -EINVAL;
474
475         if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
476                 return -EINVAL;
477
478         if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
479                 return -EINVAL;
480
481         var->xres_virtual = max(var->xres_virtual, var->xres);
482         var->yres_virtual = max(var->yres_virtual, var->yres);
483
484         if (var->bits_per_pixel > BITS_PER_PIXEL)
485                 return -EINVAL;
486         else
487                 var->bits_per_pixel = BITS_PER_PIXEL;
488
489         var->red.offset = 11;
490         var->red.length = 5;
491         var->green.offset = 5;
492         var->green.length = 6;
493         var->blue.offset = 0;
494         var->blue.length = 5;
495         var->transp.offset = var->transp.length = 0;
496
497         var->nonstd = 0;
498         var->height = -1;
499         var->width = -1;
500         var->vmode = FB_VMODE_NONINTERLACED;
501         var->sync = 0;
502         var->pixclock = 0x04;  /* 171521; */
503
504         return 0;
505 }
506
507
508 /*
509  * w100fb_set_par():
510  *      Set the user defined part of the display for the specified console
511  *  by looking at the values in info.var
512  */
513 static int w100fb_set_par(struct fb_info *info)
514 {
515         struct w100fb_par *par=info->par;
516
517         if (par->xres != info->var.xres || par->yres != info->var.yres) {
518                 par->xres = info->var.xres;
519                 par->yres = info->var.yres;
520                 par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
521
522                 info->fix.visual = FB_VISUAL_TRUECOLOR;
523                 info->fix.ypanstep = 0;
524                 info->fix.ywrapstep = 0;
525                 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
526
527                 mutex_lock(&info->mm_lock);
528                 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
529                         par->extmem_active = 1;
530                         info->fix.smem_len = par->mach->mem->size+1;
531                 } else {
532                         par->extmem_active = 0;
533                         info->fix.smem_len = MEM_INT_SIZE+1;
534                 }
535                 mutex_unlock(&info->mm_lock);
536
537                 w100fb_activate_var(par);
538         }
539         return 0;
540 }
541
542
543 /*
544  *  Frame buffer operations
545  */
546 static struct fb_ops w100fb_ops = {
547         .owner        = THIS_MODULE,
548         .fb_check_var = w100fb_check_var,
549         .fb_set_par   = w100fb_set_par,
550         .fb_setcolreg = w100fb_setcolreg,
551         .fb_blank     = w100fb_blank,
552         .fb_fillrect  = w100fb_fillrect,
553         .fb_copyarea  = w100fb_copyarea,
554         .fb_imageblit = cfb_imageblit,
555         .fb_sync      = w100fb_sync,
556 };
557
558 #ifdef CONFIG_PM
559 static void w100fb_save_vidmem(struct w100fb_par *par)
560 {
561         int memsize;
562
563         if (par->extmem_active) {
564                 memsize=par->mach->mem->size;
565                 par->saved_extmem = vmalloc(memsize);
566                 if (par->saved_extmem)
567                         memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
568         }
569         memsize=MEM_INT_SIZE;
570         par->saved_intmem = vmalloc(memsize);
571         if (par->saved_intmem && par->extmem_active)
572                 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
573         else if (par->saved_intmem)
574                 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
575 }
576
577 static void w100fb_restore_vidmem(struct w100fb_par *par)
578 {
579         int memsize;
580
581         if (par->extmem_active && par->saved_extmem) {
582                 memsize=par->mach->mem->size;
583                 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
584                 vfree(par->saved_extmem);
585         }
586         if (par->saved_intmem) {
587                 memsize=MEM_INT_SIZE;
588                 if (par->extmem_active)
589                         memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
590                 else
591                         memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
592                 vfree(par->saved_intmem);
593         }
594 }
595
596 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
597 {
598         struct fb_info *info = platform_get_drvdata(dev);
599         struct w100fb_par *par=info->par;
600         struct w100_tg_info *tg = par->mach->tg;
601
602         w100fb_save_vidmem(par);
603         if(tg && tg->suspend)
604                 tg->suspend(par);
605         w100_suspend(W100_SUSPEND_ALL);
606         par->blanked = 1;
607
608         return 0;
609 }
610
611 static int w100fb_resume(struct platform_device *dev)
612 {
613         struct fb_info *info = platform_get_drvdata(dev);
614         struct w100fb_par *par=info->par;
615         struct w100_tg_info *tg = par->mach->tg;
616
617         w100_hw_init(par);
618         w100fb_activate_var(par);
619         w100fb_restore_vidmem(par);
620         if(tg && tg->resume)
621                 tg->resume(par);
622         par->blanked = 0;
623
624         return 0;
625 }
626 #else
627 #define w100fb_suspend  NULL
628 #define w100fb_resume   NULL
629 #endif
630
631
632 int __devinit w100fb_probe(struct platform_device *pdev)
633 {
634         int err = -EIO;
635         struct w100fb_mach_info *inf;
636         struct fb_info *info = NULL;
637         struct w100fb_par *par;
638         struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
639         unsigned int chip_id;
640
641         if (!mem)
642                 return -EINVAL;
643
644         /* Remap the chip base address */
645         remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
646         if (remapped_base == NULL)
647                 goto out;
648
649         /* Map the register space */
650         remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
651         if (remapped_regs == NULL)
652                 goto out;
653
654         /* Identify the chip */
655         printk("Found ");
656         chip_id = readl(remapped_regs + mmCHIP_ID);
657         switch(chip_id) {
658                 case CHIP_ID_W100:  printk("w100");  break;
659                 case CHIP_ID_W3200: printk("w3200"); break;
660                 case CHIP_ID_W3220: printk("w3220"); break;
661                 default:
662                         printk("Unknown imageon chip ID\n");
663                         err = -ENODEV;
664                         goto out;
665         }
666         printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
667
668         /* Remap the framebuffer */
669         remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
670         if (remapped_fbuf == NULL)
671                 goto out;
672
673         info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
674         if (!info) {
675                 err = -ENOMEM;
676                 goto out;
677         }
678
679         par = info->par;
680         platform_set_drvdata(pdev, info);
681
682         inf = pdev->dev.platform_data;
683         par->chip_id = chip_id;
684         par->mach = inf;
685         par->fastpll_mode = 0;
686         par->blanked = 0;
687
688         par->pll_table=w100_get_xtal_table(inf->xtal_freq);
689         if (!par->pll_table) {
690                 printk(KERN_ERR "No matching Xtal definition found\n");
691                 err = -EINVAL;
692                 goto out;
693         }
694
695         info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
696         if (!info->pseudo_palette) {
697                 err = -ENOMEM;
698                 goto out;
699         }
700
701         info->fbops = &w100fb_ops;
702         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
703                 FBINFO_HWACCEL_FILLRECT;
704         info->node = -1;
705         info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
706         info->screen_size = REMAPPED_FB_LEN;
707
708         strcpy(info->fix.id, "w100fb");
709         info->fix.type = FB_TYPE_PACKED_PIXELS;
710         info->fix.type_aux = 0;
711         info->fix.accel = FB_ACCEL_NONE;
712         info->fix.smem_start = mem->start+W100_FB_BASE;
713         info->fix.mmio_start = mem->start+W100_REG_BASE;
714         info->fix.mmio_len = W100_REG_LEN;
715
716         if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
717                 err = -ENOMEM;
718                 goto out;
719         }
720
721         par->mode = &inf->modelist[0];
722         if(inf->init_mode & INIT_MODE_ROTATED) {
723                 info->var.xres = par->mode->yres;
724                 info->var.yres = par->mode->xres;
725         }
726         else {
727                 info->var.xres = par->mode->xres;
728                 info->var.yres = par->mode->yres;
729         }
730
731         if(inf->init_mode &= INIT_MODE_FLIPPED)
732                 par->flip = 1;
733         else
734                 par->flip = 0;
735
736         info->var.xres_virtual = info->var.xres;
737         info->var.yres_virtual = info->var.yres;
738         info->var.pixclock = 0x04;  /* 171521; */
739         info->var.sync = 0;
740         info->var.grayscale = 0;
741         info->var.xoffset = info->var.yoffset = 0;
742         info->var.accel_flags = 0;
743         info->var.activate = FB_ACTIVATE_NOW;
744
745         w100_hw_init(par);
746
747         if (w100fb_check_var(&info->var, info) < 0) {
748                 err = -EINVAL;
749                 goto out;
750         }
751
752         if (register_framebuffer(info) < 0) {
753                 err = -EINVAL;
754                 goto out;
755         }
756
757         err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
758         err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
759         err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
760         err |= device_create_file(&pdev->dev, &dev_attr_flip);
761
762         if (err != 0)
763                 printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
764                                 info->node, err);
765
766         printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
767         return 0;
768 out:
769         if (info) {
770                 fb_dealloc_cmap(&info->cmap);
771                 kfree(info->pseudo_palette);
772         }
773         if (remapped_fbuf != NULL)
774                 iounmap(remapped_fbuf);
775         if (remapped_regs != NULL)
776                 iounmap(remapped_regs);
777         if (remapped_base != NULL)
778                 iounmap(remapped_base);
779         if (info)
780                 framebuffer_release(info);
781         return err;
782 }
783
784
785 static int __devexit w100fb_remove(struct platform_device *pdev)
786 {
787         struct fb_info *info = platform_get_drvdata(pdev);
788         struct w100fb_par *par=info->par;
789
790         device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
791         device_remove_file(&pdev->dev, &dev_attr_reg_read);
792         device_remove_file(&pdev->dev, &dev_attr_reg_write);
793         device_remove_file(&pdev->dev, &dev_attr_flip);
794
795         unregister_framebuffer(info);
796
797         vfree(par->saved_intmem);
798         vfree(par->saved_extmem);
799         kfree(info->pseudo_palette);
800         fb_dealloc_cmap(&info->cmap);
801
802         iounmap(remapped_base);
803         iounmap(remapped_regs);
804         iounmap(remapped_fbuf);
805
806         framebuffer_release(info);
807
808         return 0;
809 }
810
811
812 /* ------------------- chipset specific functions -------------------------- */
813
814
815 static void w100_soft_reset(void)
816 {
817         u16 val = readw((u16 *) remapped_base + cfgSTATUS);
818         writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
819         udelay(100);
820         writew(0x00, (u16 *) remapped_base + cfgSTATUS);
821         udelay(100);
822 }
823
824 static void w100_update_disable(void)
825 {
826         union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
827
828         /* Prevent display updates */
829         disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
830         disp_db_buf_wr_cntl.f.update_db_buf = 0;
831         disp_db_buf_wr_cntl.f.en_db_buf = 0;
832         writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
833 }
834
835 static void w100_update_enable(void)
836 {
837         union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
838
839         /* Enable display updates */
840         disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
841         disp_db_buf_wr_cntl.f.update_db_buf = 1;
842         disp_db_buf_wr_cntl.f.en_db_buf = 1;
843         writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
844 }
845
846 unsigned long w100fb_gpio_read(int port)
847 {
848         unsigned long value;
849
850         if (port==W100_GPIO_PORT_A)
851                 value = readl(remapped_regs + mmGPIO_DATA);
852         else
853                 value = readl(remapped_regs + mmGPIO_DATA2);
854
855         return value;
856 }
857
858 void w100fb_gpio_write(int port, unsigned long value)
859 {
860         if (port==W100_GPIO_PORT_A)
861                 writel(value, remapped_regs + mmGPIO_DATA);
862         else
863                 writel(value, remapped_regs + mmGPIO_DATA2);
864 }
865 EXPORT_SYMBOL(w100fb_gpio_read);
866 EXPORT_SYMBOL(w100fb_gpio_write);
867
868 /*
869  * Initialization of critical w100 hardware
870  */
871 static void w100_hw_init(struct w100fb_par *par)
872 {
873         u32 temp32;
874         union cif_cntl_u cif_cntl;
875         union intf_cntl_u intf_cntl;
876         union cfgreg_base_u cfgreg_base;
877         union wrap_top_dir_u wrap_top_dir;
878         union cif_read_dbg_u cif_read_dbg;
879         union cpu_defaults_u cpu_default;
880         union cif_write_dbg_u cif_write_dbg;
881         union wrap_start_dir_u wrap_start_dir;
882         union cif_io_u cif_io;
883         struct w100_gpio_regs *gpio = par->mach->gpio;
884
885         w100_soft_reset();
886
887         /* This is what the fpga_init code does on reset. May be wrong
888            but there is little info available */
889         writel(0x31, remapped_regs + mmSCRATCH_UMSK);
890         for (temp32 = 0; temp32 < 10000; temp32++)
891                 readl(remapped_regs + mmSCRATCH_UMSK);
892         writel(0x30, remapped_regs + mmSCRATCH_UMSK);
893
894         /* Set up CIF */
895         cif_io.val = defCIF_IO;
896         writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
897
898         cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
899         cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
900         cif_write_dbg.f.en_dword_split_to_rbbm = 1;
901         cif_write_dbg.f.dis_timeout_during_rbbm = 1;
902         writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
903
904         cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
905         cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
906         writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
907
908         cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
909         cif_cntl.f.dis_system_bits = 1;
910         cif_cntl.f.dis_mr = 1;
911         cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
912         cif_cntl.f.intb_oe = 1;
913         cif_cntl.f.interrupt_active_high = 1;
914         writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
915
916         /* Setup cfgINTF_CNTL and cfgCPU defaults */
917         intf_cntl.val = defINTF_CNTL;
918         intf_cntl.f.ad_inc_a = 1;
919         intf_cntl.f.ad_inc_b = 1;
920         intf_cntl.f.rd_data_rdy_a = 0;
921         intf_cntl.f.rd_data_rdy_b = 0;
922         writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
923
924         cpu_default.val = defCPU_DEFAULTS;
925         cpu_default.f.access_ind_addr_a = 1;
926         cpu_default.f.access_ind_addr_b = 1;
927         cpu_default.f.access_scratch_reg = 1;
928         cpu_default.f.transition_size = 0;
929         writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
930
931         /* set up the apertures */
932         writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
933
934         cfgreg_base.val = defCFGREG_BASE;
935         cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
936         writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
937
938         wrap_start_dir.val = defWRAP_START_DIR;
939         wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
940         writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
941
942         wrap_top_dir.val = defWRAP_TOP_DIR;
943         wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
944         writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
945
946         writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
947
948         /* Set the hardware to 565 colour */
949         temp32 = readl(remapped_regs + mmDISP_DEBUG2);
950         temp32 &= 0xff7fffff;
951         temp32 |= 0x00800000;
952         writel(temp32, remapped_regs + mmDISP_DEBUG2);
953
954         /* Initialise the GPIO lines */
955         if (gpio) {
956                 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
957                 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
958                 writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
959                 writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
960                 writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
961                 writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
962         }
963 }
964
965
966 struct power_state {
967         union clk_pin_cntl_u clk_pin_cntl;
968         union pll_ref_fb_div_u pll_ref_fb_div;
969         union pll_cntl_u pll_cntl;
970         union sclk_cntl_u sclk_cntl;
971         union pclk_cntl_u pclk_cntl;
972         union pwrmgt_cntl_u pwrmgt_cntl;
973         int auto_mode;  /* system clock auto changing? */
974 };
975
976
977 static struct power_state w100_pwr_state;
978
979 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
980
981 /* 12.5MHz Crystal PLL Table */
982 static struct w100_pll_info xtal_12500000[] = {
983         /*freq     M   N_int    N_fac  tfgoal  lock_time */
984         { 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
985         { 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
986         {100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
987         {125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
988         {150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
989         {  0,      0,   0,       0,        0,         0},  /* Terminator */
990 };
991
992 /* 14.318MHz Crystal PLL Table */
993 static struct w100_pll_info xtal_14318000[] = {
994         /*freq     M   N_int    N_fac  tfgoal  lock_time */
995         { 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
996         { 50,      1,   6,       0,     0xe0,        64}, /*  50.05 MHz */
997         { 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
998         { 75,      0,   4,       3,     0xe0,        43}, /*  75.08 MHz */
999         {100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
1000         {  0,      0,   0,       0,        0,         0},
1001 };
1002
1003 /* 16MHz Crystal PLL Table */
1004 static struct w100_pll_info xtal_16000000[] = {
1005         /*freq     M   N_int    N_fac  tfgoal  lock_time */
1006         { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
1007         { 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
1008         { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
1009         { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
1010         {  0,      0,   0,       0,        0,         0},
1011 };
1012
1013 static struct pll_entries {
1014         int xtal_freq;
1015         struct w100_pll_info *pll_table;
1016 } w100_pll_tables[] = {
1017         { 12500000, &xtal_12500000[0] },
1018         { 14318000, &xtal_14318000[0] },
1019         { 16000000, &xtal_16000000[0] },
1020         { 0 },
1021 };
1022
1023 struct w100_pll_info __devinit *w100_get_xtal_table(unsigned int freq)
1024 {
1025         struct pll_entries *pll_entry = w100_pll_tables;
1026
1027         do {
1028                 if (freq == pll_entry->xtal_freq)
1029                         return pll_entry->pll_table;
1030                 pll_entry++;
1031         } while (pll_entry->xtal_freq);
1032         return 0;
1033 }
1034
1035
1036 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1037 {
1038         union clk_test_cntl_u clk_test_cntl;
1039
1040         udelay(5);
1041
1042         /* Select the test clock source and reset */
1043         clk_test_cntl.f.start_check_freq = 0x0;
1044         clk_test_cntl.f.testclk_sel = testclk_sel;
1045         clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1046         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1047
1048         clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1049         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1050
1051         /* Run clock test */
1052         clk_test_cntl.f.start_check_freq = 0x1;
1053         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1054
1055         /* Give the test time to complete */
1056         udelay(20);
1057
1058         /* Return the result */
1059         clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1060         clk_test_cntl.f.start_check_freq = 0x0;
1061         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1062
1063         return clk_test_cntl.f.test_count;
1064 }
1065
1066
1067 static int w100_pll_adjust(struct w100_pll_info *pll)
1068 {
1069         unsigned int tf80;
1070         unsigned int tf20;
1071
1072         /* Initial Settings */
1073         w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
1074         w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
1075         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
1076         w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
1077         w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
1078         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
1079         w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1080
1081         /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1082          * therefore, commented out the following lines
1083          * tf80 meant tf100
1084          */
1085         do {
1086                 /* set VCO input = 0.8 * VDD */
1087                 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1088                 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1089
1090                 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1091                 if (tf80 >= (pll->tfgoal)) {
1092                         /* set VCO input = 0.2 * VDD */
1093                         w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1094                         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1095
1096                         tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1097                         if (tf20 <= (pll->tfgoal))
1098                                 return 1;  /* Success */
1099
1100                         if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1101                                 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1102                                 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1103                                 /* slow VCO config */
1104                                 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1105                                 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1106                                 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1107                                 continue;
1108                         }
1109                 }
1110                 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1111                         w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1112                 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1113                         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1114                         w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1115                 } else {
1116                         return 0;  /* Error */
1117                 }
1118         } while(1);
1119 }
1120
1121
1122 /*
1123  * w100_pll_calibration
1124  */
1125 static int w100_pll_calibration(struct w100_pll_info *pll)
1126 {
1127         int status;
1128
1129         status = w100_pll_adjust(pll);
1130
1131         /* PLL Reset And Lock */
1132         /* set VCO input = 0.5 * VDD */
1133         w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1134         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1135
1136         udelay(1);  /* reset time */
1137
1138         /* enable charge pump */
1139         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
1140         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1141
1142         /* set VCO input = Hi-Z, disable DAC */
1143         w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1144         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1145
1146         udelay(400);  /* lock time */
1147
1148         /* PLL locked */
1149
1150         return status;
1151 }
1152
1153
1154 static int w100_pll_set_clk(struct w100_pll_info *pll)
1155 {
1156         int status;
1157
1158         if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1159         {
1160                 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
1161                 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
1162                 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1163         }
1164
1165         /* Set system clock source to XTAL whilst adjusting the PLL! */
1166         w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1167         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1168
1169         w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1170         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1171         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1172         w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1173         writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1174
1175         w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1176         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1177
1178         status = w100_pll_calibration(pll);
1179
1180         if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1181         {
1182                 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
1183                 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
1184                 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1185         }
1186         return status;
1187 }
1188
1189 /* freq = target frequency of the PLL */
1190 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1191 {
1192         struct w100_pll_info *pll = par->pll_table;
1193
1194         do {
1195                 if (freq == pll->freq) {
1196                         return w100_pll_set_clk(pll);
1197                 }
1198                 pll++;
1199         } while(pll->freq);
1200         return 0;
1201 }
1202
1203 /* Set up an initial state.  Some values/fields set
1204    here will be overwritten. */
1205 static void w100_pwm_setup(struct w100fb_par *par)
1206 {
1207         w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1208         w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1209         w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1210         w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1211         w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1212         w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1213         writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1214
1215         w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1216         w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
1217         w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1218         w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
1219         w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1220         w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
1221         w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
1222         w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
1223         w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
1224         w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
1225         w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
1226         w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
1227         w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
1228         w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
1229         w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1230         w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1231         w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1232         w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1233         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1234
1235         w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1236         w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
1237         w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
1238         writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1239
1240         w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
1241         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
1242         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1243         w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1244         w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1245         writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1246
1247         w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1248         w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1249         w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1250         w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
1251         w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1252         w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1253         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1254         w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1255         w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1256         w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1257         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1258         w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1259         w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1260         w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
1261         w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1262         w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1263         w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1264         w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1265         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1266
1267         w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1268         w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
1269         w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1270         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1271         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1272         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
1273         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
1274         w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1275         w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1276         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1277
1278         w100_pwr_state.auto_mode = 0;  /* manual mode */
1279 }
1280
1281
1282 /*
1283  * Setup the w100 clocks for the specified mode
1284  */
1285 static void w100_init_clocks(struct w100fb_par *par)
1286 {
1287         struct w100_mode *mode = par->mode;
1288
1289         if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1290                 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1291
1292         w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1293         w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1294         w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1295         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1296 }
1297
1298 static void w100_init_lcd(struct w100fb_par *par)
1299 {
1300         u32 temp32;
1301         struct w100_mode *mode = par->mode;
1302         struct w100_gen_regs *regs = par->mach->regs;
1303         union active_h_disp_u active_h_disp;
1304         union active_v_disp_u active_v_disp;
1305         union graphic_h_disp_u graphic_h_disp;
1306         union graphic_v_disp_u graphic_v_disp;
1307         union crtc_total_u crtc_total;
1308
1309         /* w3200 doesn't like undefined bits being set so zero register values first */
1310
1311         active_h_disp.val = 0;
1312         active_h_disp.f.active_h_start=mode->left_margin;
1313         active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1314         writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1315
1316         active_v_disp.val = 0;
1317         active_v_disp.f.active_v_start=mode->upper_margin;
1318         active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1319         writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1320
1321         graphic_h_disp.val = 0;
1322         graphic_h_disp.f.graphic_h_start=mode->left_margin;
1323         graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1324         writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1325
1326         graphic_v_disp.val = 0;
1327         graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1328         graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1329         writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1330
1331         crtc_total.val = 0;
1332         crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
1333         crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1334         writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1335
1336         writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1337         writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1338         writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1339         writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1340         writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1341         writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1342         writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1343         writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1344         writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1345
1346         writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1347         writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1348         writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1349         writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1350         writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1351         writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1352
1353         writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1354         writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1355         writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1356         writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1357
1358         /* Hack for overlay in ext memory */
1359         temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1360         temp32 |= 0xc0000000;
1361         writel(temp32, remapped_regs + mmDISP_DEBUG2);
1362 }
1363
1364
1365 static void w100_setup_memory(struct w100fb_par *par)
1366 {
1367         union mc_ext_mem_location_u extmem_location;
1368         union mc_fb_location_u intmem_location;
1369         struct w100_mem_info *mem = par->mach->mem;
1370         struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1371
1372         if (!par->extmem_active) {
1373                 w100_suspend(W100_SUSPEND_EXTMEM);
1374
1375                 /* Map Internal Memory at FB Base */
1376                 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1377                 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1378                 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1379
1380                 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1381                    to acceleration libraries */
1382                 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1383                 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1384                 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1385         } else {
1386                 /* Map Internal Memory to its default location */
1387                 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1388                 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1389                 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1390
1391                 /* Map External Memory at FB Base */
1392                 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1393                 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1394                 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1395
1396                 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1397                 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1398                 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1399                 udelay(100);
1400                 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1401                 udelay(100);
1402                 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1403                 udelay(100);
1404                 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1405                 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1406                 if (bm_mem) {
1407                         writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1408                         writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1409                         writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1410                         writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1411                         writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1412                         writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1413                         writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1414                 }
1415         }
1416 }
1417
1418 static void w100_set_dispregs(struct w100fb_par *par)
1419 {
1420         unsigned long rot=0, divider, offset=0;
1421         union graphic_ctrl_u graphic_ctrl;
1422
1423         /* See if the mode has been rotated */
1424         if (par->xres == par->mode->xres) {
1425                 if (par->flip) {
1426                         rot=3; /* 180 degree */
1427                         offset=(par->xres * par->yres) - 1;
1428                 } /* else 0 degree */
1429                 divider = par->mode->pixclk_divider;
1430         } else {
1431                 if (par->flip) {
1432                         rot=2; /* 270 degree */
1433                         offset=par->xres - 1;
1434                 } else {
1435                         rot=1; /* 90 degree */
1436                         offset=par->xres * (par->yres - 1);
1437                 }
1438                 divider = par->mode->pixclk_divider_rotated;
1439         }
1440
1441         graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1442         switch (par->chip_id) {
1443                 case CHIP_ID_W100:
1444                         graphic_ctrl.f_w100.color_depth=6;
1445                         graphic_ctrl.f_w100.en_crtc=1;
1446                         graphic_ctrl.f_w100.en_graphic_req=1;
1447                         graphic_ctrl.f_w100.en_graphic_crtc=1;
1448                         graphic_ctrl.f_w100.lcd_pclk_on=1;
1449                         graphic_ctrl.f_w100.lcd_sclk_on=1;
1450                         graphic_ctrl.f_w100.low_power_on=0;
1451                         graphic_ctrl.f_w100.req_freq=0;
1452                         graphic_ctrl.f_w100.portrait_mode=rot;
1453
1454                         /* Zaurus needs this */
1455                         switch(par->xres) {
1456                                 case 240:
1457                                 case 320:
1458                                 default:
1459                                         graphic_ctrl.f_w100.total_req_graphic=0xa0;
1460                                         break;
1461                                 case 480:
1462                                 case 640:
1463                                         switch(rot) {
1464                                                 case 0:  /* 0 */
1465                                                 case 3:  /* 180 */
1466                                                         graphic_ctrl.f_w100.low_power_on=1;
1467                                                         graphic_ctrl.f_w100.req_freq=5;
1468                                                 break;
1469                                                 case 1:  /* 90 */
1470                                                 case 2:  /* 270 */
1471                                                         graphic_ctrl.f_w100.req_freq=4;
1472                                                         break;
1473                                                 default:
1474                                                         break;
1475                                         }
1476                                         graphic_ctrl.f_w100.total_req_graphic=0xf0;
1477                                         break;
1478                         }
1479                         break;
1480                 case CHIP_ID_W3200:
1481                 case CHIP_ID_W3220:
1482                         graphic_ctrl.f_w32xx.color_depth=6;
1483                         graphic_ctrl.f_w32xx.en_crtc=1;
1484                         graphic_ctrl.f_w32xx.en_graphic_req=1;
1485                         graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1486                         graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1487                         graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1488                         graphic_ctrl.f_w32xx.low_power_on=0;
1489                         graphic_ctrl.f_w32xx.req_freq=0;
1490                         graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1491                         graphic_ctrl.f_w32xx.portrait_mode=rot;
1492                         break;
1493         }
1494
1495         /* Set the pixel clock source and divider */
1496         w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1497         w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1498         writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1499
1500         writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1501         writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1502         writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1503 }
1504
1505
1506 /*
1507  * Work out how long the sync pulse lasts
1508  * Value is 1/(time in seconds)
1509  */
1510 static void calc_hsync(struct w100fb_par *par)
1511 {
1512         unsigned long hsync;
1513         struct w100_mode *mode = par->mode;
1514         union crtc_ss_u crtc_ss;
1515
1516         if (mode->pixclk_src == CLK_SRC_XTAL)
1517                 hsync=par->mach->xtal_freq;
1518         else
1519                 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1520
1521         hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1522
1523         crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1524         if (crtc_ss.val)
1525                 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1526         else
1527                 par->hsync_len = 0;
1528 }
1529
1530 static void w100_suspend(u32 mode)
1531 {
1532         u32 val;
1533
1534         writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1535         writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1536
1537         val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1538         val &= ~(0x00100000);  /* bit20=0 */
1539         val |= 0xFF000000;     /* bit31:24=0xff */
1540         writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1541
1542         val = readl(remapped_regs + mmMEM_EXT_CNTL);
1543         val &= ~(0x00040000);  /* bit18=0 */
1544         val |= 0x00080000;     /* bit19=1 */
1545         writel(val, remapped_regs + mmMEM_EXT_CNTL);
1546
1547         udelay(1);  /* wait 1us */
1548
1549         if (mode == W100_SUSPEND_EXTMEM) {
1550                 /* CKE: Tri-State */
1551                 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1552                 val |= 0x40000000;  /* bit30=1 */
1553                 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1554
1555                 /* CLK: Stop */
1556                 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1557                 val &= ~(0x00000001);  /* bit0=0 */
1558                 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1559         } else {
1560                 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1561                 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1562                 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1563
1564                 udelay(5);
1565
1566                 val = readl(remapped_regs + mmPLL_CNTL);
1567                 val |= 0x00000004;  /* bit2=1 */
1568                 writel(val, remapped_regs + mmPLL_CNTL);
1569                 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1570         }
1571 }
1572
1573 static void w100_vsync(void)
1574 {
1575         u32 tmp;
1576         int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
1577
1578         tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1579
1580         /* set vline pos  */
1581         writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1582
1583         /* disable vline irq */
1584         tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1585
1586         tmp &= ~0x00000002;
1587         writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1588
1589         /* clear vline irq status */
1590         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1591
1592         /* enable vline irq */
1593         writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1594
1595         /* clear vline irq status */
1596         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1597
1598         while(timeout > 0) {
1599                 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1600                         break;
1601                 udelay(1);
1602                 timeout--;
1603         }
1604
1605         /* disable vline irq */
1606         writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1607
1608         /* clear vline irq status */
1609         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1610 }
1611
1612 static struct platform_driver w100fb_driver = {
1613         .probe          = w100fb_probe,
1614         .remove         = __devexit_p(w100fb_remove),
1615         .suspend        = w100fb_suspend,
1616         .resume         = w100fb_resume,
1617         .driver         = {
1618                 .name   = "w100fb",
1619         },
1620 };
1621
1622 int __init w100fb_init(void)
1623 {
1624         return platform_driver_register(&w100fb_driver);
1625 }
1626
1627 void __exit w100fb_cleanup(void)
1628 {
1629         platform_driver_unregister(&w100fb_driver);
1630 }
1631
1632 module_init(w100fb_init);
1633 module_exit(w100fb_cleanup);
1634
1635 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1636 MODULE_LICENSE("GPL");