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